chore: CRLF to LF
This commit is contained in:
+37
-37
@@ -1,37 +1,37 @@
|
||||
#include "bbc.h"
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sigscan.h"
|
||||
|
||||
namespace games::bbc {
|
||||
|
||||
BBCGame::BBCGame() : Game("Bishi Bashi Channel") {
|
||||
}
|
||||
|
||||
void BBCGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// window patch
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
unsigned char pattern[] = {
|
||||
0x48, 0x8D, 0x54, 0x24, 0x40, 0x41, 0x8D, 0x4E, 0x20, 0x41, 0x0F, 0xB6, 0xE8
|
||||
};
|
||||
unsigned char replace[] = {
|
||||
0x48, 0x8D, 0x54, 0x24, 0x40, 0x41, 0x8D, 0x4E, 0x20, 0x31, 0xED, 0x90, 0x90
|
||||
};
|
||||
std::string mask = "XXXXXXXXXXXXX";
|
||||
if (!replace_pattern(
|
||||
avs::game::DLL_INSTANCE,
|
||||
pattern,
|
||||
mask.c_str(),
|
||||
0,
|
||||
0,
|
||||
replace,
|
||||
mask.c_str()))
|
||||
log_warning("bbc", "windowed mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "bbc.h"
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sigscan.h"
|
||||
|
||||
namespace games::bbc {
|
||||
|
||||
BBCGame::BBCGame() : Game("Bishi Bashi Channel") {
|
||||
}
|
||||
|
||||
void BBCGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// window patch
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
unsigned char pattern[] = {
|
||||
0x48, 0x8D, 0x54, 0x24, 0x40, 0x41, 0x8D, 0x4E, 0x20, 0x41, 0x0F, 0xB6, 0xE8
|
||||
};
|
||||
unsigned char replace[] = {
|
||||
0x48, 0x8D, 0x54, 0x24, 0x40, 0x41, 0x8D, 0x4E, 0x20, 0x31, 0xED, 0x90, 0x90
|
||||
};
|
||||
std::string mask = "XXXXXXXXXXXXX";
|
||||
if (!replace_pattern(
|
||||
avs::game::DLL_INSTANCE,
|
||||
pattern,
|
||||
mask.c_str(),
|
||||
0,
|
||||
0,
|
||||
replace,
|
||||
mask.c_str()))
|
||||
log_warning("bbc", "windowed mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::bbc {
|
||||
|
||||
class BBCGame : public games::Game {
|
||||
public:
|
||||
BBCGame();
|
||||
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::bbc {
|
||||
|
||||
class BBCGame : public games::Game {
|
||||
public:
|
||||
BBCGame();
|
||||
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+105
-105
@@ -1,105 +1,105 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::bbc::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Bishi Bashi Channel");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"P1 R",
|
||||
"P1 G",
|
||||
"P1 B",
|
||||
"P1 Disk-",
|
||||
"P1 Disk+",
|
||||
"P1 Disk -/+ Slowdown",
|
||||
"P2 R",
|
||||
"P2 G",
|
||||
"P2 B",
|
||||
"P2 Disk-",
|
||||
"P2 Disk+",
|
||||
"P2 Disk -/+ Slowdown",
|
||||
"P3 R",
|
||||
"P3 G",
|
||||
"P3 B",
|
||||
"P3 Disk-",
|
||||
"P3 Disk+",
|
||||
"P3 Disk -/+ Slowdown",
|
||||
"P4 R",
|
||||
"P4 G",
|
||||
"P4 B",
|
||||
"P4 Disk-",
|
||||
"P4 Disk+",
|
||||
"P4 Disk -/+ Slowdown"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::bbc::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Bishi Bashi Channel");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"P1 Disk",
|
||||
"P2 Disk",
|
||||
"P3 Disk",
|
||||
"P4 Disk"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::bbc::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Bishi Bashi Channel");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"P1 R",
|
||||
"P1 B",
|
||||
"P1 Disc R",
|
||||
"P1 Disc G",
|
||||
"P1 Disc B",
|
||||
"P2 R",
|
||||
"P2 B",
|
||||
"P2 Disc R",
|
||||
"P2 Disc G",
|
||||
"P2 Disc B",
|
||||
"P3 R",
|
||||
"P3 B",
|
||||
"P3 Disc R",
|
||||
"P3 Disc G",
|
||||
"P3 Disc B",
|
||||
"P4 R",
|
||||
"P4 B",
|
||||
"P4 Disc R",
|
||||
"P4 Disc G",
|
||||
"P4 Disc B",
|
||||
"IC Card R",
|
||||
"IC Card G",
|
||||
"IC Card B",
|
||||
"Under LED1 R",
|
||||
"Under LED1 G",
|
||||
"Under LED1 B",
|
||||
"Under LED2 R",
|
||||
"Under LED2 G",
|
||||
"Under LED2 B",
|
||||
"Under LED3 R",
|
||||
"Under LED3 G",
|
||||
"Under LED3 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::bbc::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Bishi Bashi Channel");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"P1 R",
|
||||
"P1 G",
|
||||
"P1 B",
|
||||
"P1 Disk-",
|
||||
"P1 Disk+",
|
||||
"P1 Disk -/+ Slowdown",
|
||||
"P2 R",
|
||||
"P2 G",
|
||||
"P2 B",
|
||||
"P2 Disk-",
|
||||
"P2 Disk+",
|
||||
"P2 Disk -/+ Slowdown",
|
||||
"P3 R",
|
||||
"P3 G",
|
||||
"P3 B",
|
||||
"P3 Disk-",
|
||||
"P3 Disk+",
|
||||
"P3 Disk -/+ Slowdown",
|
||||
"P4 R",
|
||||
"P4 G",
|
||||
"P4 B",
|
||||
"P4 Disk-",
|
||||
"P4 Disk+",
|
||||
"P4 Disk -/+ Slowdown"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::bbc::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Bishi Bashi Channel");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"P1 Disk",
|
||||
"P2 Disk",
|
||||
"P3 Disk",
|
||||
"P4 Disk"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::bbc::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Bishi Bashi Channel");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"P1 R",
|
||||
"P1 B",
|
||||
"P1 Disc R",
|
||||
"P1 Disc G",
|
||||
"P1 Disc B",
|
||||
"P2 R",
|
||||
"P2 B",
|
||||
"P2 Disc R",
|
||||
"P2 Disc G",
|
||||
"P2 Disc B",
|
||||
"P3 R",
|
||||
"P3 B",
|
||||
"P3 Disc R",
|
||||
"P3 Disc G",
|
||||
"P3 Disc B",
|
||||
"P4 R",
|
||||
"P4 B",
|
||||
"P4 Disc R",
|
||||
"P4 Disc G",
|
||||
"P4 Disc B",
|
||||
"IC Card R",
|
||||
"IC Card G",
|
||||
"IC Card B",
|
||||
"Under LED1 R",
|
||||
"Under LED1 G",
|
||||
"Under LED1 B",
|
||||
"Under LED2 R",
|
||||
"Under LED2 G",
|
||||
"Under LED2 B",
|
||||
"Under LED3 R",
|
||||
"Under LED3 G",
|
||||
"Under LED3 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+92
-92
@@ -1,92 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::bbc {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
P1_R,
|
||||
P1_G,
|
||||
P1_B,
|
||||
P1_DiskMinus,
|
||||
P1_DiskPlus,
|
||||
P1_DiskSlowdown,
|
||||
P2_R,
|
||||
P2_G,
|
||||
P2_B,
|
||||
P2_DiskMinus,
|
||||
P2_DiskPlus,
|
||||
P2_DiskSlowdown,
|
||||
P3_R,
|
||||
P3_G,
|
||||
P3_B,
|
||||
P3_DiskMinus,
|
||||
P3_DiskPlus,
|
||||
P3_DiskSlowdown,
|
||||
P4_R,
|
||||
P4_G,
|
||||
P4_B,
|
||||
P4_DiskMinus,
|
||||
P4_DiskPlus,
|
||||
P4_DiskSlowdown,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
P1_Disk,
|
||||
P2_Disk,
|
||||
P3_Disk,
|
||||
P4_Disk,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
P1_R,
|
||||
P1_B,
|
||||
P1_DISC_R,
|
||||
P1_DISC_G,
|
||||
P1_DISC_B,
|
||||
P2_R,
|
||||
P2_B,
|
||||
P2_DISC_R,
|
||||
P2_DISC_G,
|
||||
P2_DISC_B,
|
||||
P3_R,
|
||||
P3_B,
|
||||
P3_DISC_R,
|
||||
P3_DISC_G,
|
||||
P3_DISC_B,
|
||||
P4_R,
|
||||
P4_B,
|
||||
P4_DISC_R,
|
||||
P4_DISC_G,
|
||||
P4_DISC_B,
|
||||
IC_CARD_R,
|
||||
IC_CARD_G,
|
||||
IC_CARD_B,
|
||||
UNDER_LED1_R,
|
||||
UNDER_LED1_G,
|
||||
UNDER_LED1_B,
|
||||
UNDER_LED2_R,
|
||||
UNDER_LED2_G,
|
||||
UNDER_LED2_B,
|
||||
UNDER_LED3_R,
|
||||
UNDER_LED3_G,
|
||||
UNDER_LED3_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::bbc {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
P1_R,
|
||||
P1_G,
|
||||
P1_B,
|
||||
P1_DiskMinus,
|
||||
P1_DiskPlus,
|
||||
P1_DiskSlowdown,
|
||||
P2_R,
|
||||
P2_G,
|
||||
P2_B,
|
||||
P2_DiskMinus,
|
||||
P2_DiskPlus,
|
||||
P2_DiskSlowdown,
|
||||
P3_R,
|
||||
P3_G,
|
||||
P3_B,
|
||||
P3_DiskMinus,
|
||||
P3_DiskPlus,
|
||||
P3_DiskSlowdown,
|
||||
P4_R,
|
||||
P4_G,
|
||||
P4_B,
|
||||
P4_DiskMinus,
|
||||
P4_DiskPlus,
|
||||
P4_DiskSlowdown,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
P1_Disk,
|
||||
P2_Disk,
|
||||
P3_Disk,
|
||||
P4_Disk,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
P1_R,
|
||||
P1_B,
|
||||
P1_DISC_R,
|
||||
P1_DISC_G,
|
||||
P1_DISC_B,
|
||||
P2_R,
|
||||
P2_B,
|
||||
P2_DISC_R,
|
||||
P2_DISC_G,
|
||||
P2_DISC_B,
|
||||
P3_R,
|
||||
P3_B,
|
||||
P3_DISC_R,
|
||||
P3_DISC_G,
|
||||
P3_DISC_B,
|
||||
P4_R,
|
||||
P4_B,
|
||||
P4_DISC_R,
|
||||
P4_DISC_G,
|
||||
P4_DISC_B,
|
||||
IC_CARD_R,
|
||||
IC_CARD_G,
|
||||
IC_CARD_B,
|
||||
UNDER_LED1_R,
|
||||
UNDER_LED1_G,
|
||||
UNDER_LED1_B,
|
||||
UNDER_LED2_R,
|
||||
UNDER_LED2_G,
|
||||
UNDER_LED2_B,
|
||||
UNDER_LED3_R,
|
||||
UNDER_LED3_G,
|
||||
UNDER_LED3_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+53
-53
@@ -1,53 +1,53 @@
|
||||
#include "bs.h"
|
||||
#include "avs/game.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace games::bs {
|
||||
|
||||
BSGame::BSGame() : Game("Beatstream") {
|
||||
}
|
||||
|
||||
inline bool touchscreen_has_bug() {
|
||||
|
||||
// get devices
|
||||
auto devices = RI_MGR->devices_get();
|
||||
for (auto &device : devices) {
|
||||
|
||||
// filter by HID
|
||||
if (device.type == rawinput::HID) {
|
||||
auto &hid = device.hidInfo;
|
||||
auto &attributes = hid->attributes;
|
||||
|
||||
// P2314T
|
||||
// it apparently cannot do holds using Beatstream's wintouch code
|
||||
if (attributes.VendorID == 0x2149 && attributes.ProductID == 0x2316)
|
||||
return true;
|
||||
|
||||
// P2418HT
|
||||
// it apparently cannot do holds using Beatstream's wintouch code
|
||||
if (attributes.VendorID == 0x1FD2 && attributes.ProductID == 0x6103)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// looks all clean
|
||||
return false;
|
||||
}
|
||||
|
||||
void BSGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// for bugged touch screens
|
||||
if (touchscreen_has_bug()) {
|
||||
log_info("bs", "detected bugged touchscreen, forcing wintouchemu");
|
||||
wintouchemu::FORCE = true;
|
||||
}
|
||||
|
||||
// for mouse support
|
||||
wintouchemu::hook("BeatStream", avs::game::DLL_INSTANCE);
|
||||
}
|
||||
}
|
||||
#include "bs.h"
|
||||
#include "avs/game.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace games::bs {
|
||||
|
||||
BSGame::BSGame() : Game("Beatstream") {
|
||||
}
|
||||
|
||||
inline bool touchscreen_has_bug() {
|
||||
|
||||
// get devices
|
||||
auto devices = RI_MGR->devices_get();
|
||||
for (auto &device : devices) {
|
||||
|
||||
// filter by HID
|
||||
if (device.type == rawinput::HID) {
|
||||
auto &hid = device.hidInfo;
|
||||
auto &attributes = hid->attributes;
|
||||
|
||||
// P2314T
|
||||
// it apparently cannot do holds using Beatstream's wintouch code
|
||||
if (attributes.VendorID == 0x2149 && attributes.ProductID == 0x2316)
|
||||
return true;
|
||||
|
||||
// P2418HT
|
||||
// it apparently cannot do holds using Beatstream's wintouch code
|
||||
if (attributes.VendorID == 0x1FD2 && attributes.ProductID == 0x6103)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// looks all clean
|
||||
return false;
|
||||
}
|
||||
|
||||
void BSGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// for bugged touch screens
|
||||
if (touchscreen_has_bug()) {
|
||||
log_info("bs", "detected bugged touchscreen, forcing wintouchemu");
|
||||
wintouchemu::FORCE = true;
|
||||
}
|
||||
|
||||
// for mouse support
|
||||
wintouchemu::hook("BeatStream", avs::game::DLL_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::bs {
|
||||
|
||||
class BSGame : public games::Game {
|
||||
public:
|
||||
BSGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::bs {
|
||||
|
||||
class BSGame : public games::Game {
|
||||
public:
|
||||
BSGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+41
-41
@@ -1,41 +1,41 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::bs::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Beatstream");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::bs::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Beatstream");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Bottom R",
|
||||
"Bottom G",
|
||||
"Bottom B",
|
||||
"Left R",
|
||||
"Left G",
|
||||
"Left B",
|
||||
"Right R",
|
||||
"Right G",
|
||||
"Right B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::bs::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Beatstream");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::bs::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Beatstream");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Bottom R",
|
||||
"Bottom G",
|
||||
"Bottom B",
|
||||
"Left R",
|
||||
"Left G",
|
||||
"Left B",
|
||||
"Right R",
|
||||
"Right G",
|
||||
"Right B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+35
-35
@@ -1,35 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::bs {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
BottomR,
|
||||
BottomG,
|
||||
BottomB,
|
||||
LeftR,
|
||||
LeftG,
|
||||
LeftB,
|
||||
RightR,
|
||||
RightG,
|
||||
RightB,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::bs {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
BottomR,
|
||||
BottomG,
|
||||
BottomB,
|
||||
LeftR,
|
||||
LeftG,
|
||||
LeftB,
|
||||
RightR,
|
||||
RightG,
|
||||
RightB,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+117
-117
@@ -1,117 +1,117 @@
|
||||
#include "ddr.h"
|
||||
|
||||
#include "acioemu/handle.h"
|
||||
#include "avs/game.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "hooks/setupapihook.h"
|
||||
#include "hooks/sleephook.h"
|
||||
#include "hooks/input/dinput8/hook.h"
|
||||
#include "util/utils.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "util/detour.h"
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#include "p3io/foot.h"
|
||||
#include "p3io/p3io.h"
|
||||
#include "p3io/sate.h"
|
||||
#include "p3io/usbmem.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
// settings
|
||||
bool SDMODE = false;
|
||||
|
||||
static decltype(SendMessage) *SendMessage_real = nullptr;
|
||||
|
||||
static SHORT WINAPI GetAsyncKeyState_hook(int vKey) {
|
||||
|
||||
// disable debug keys
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI SendMessage_hook(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
// ignore broadcasts
|
||||
if (hWnd == HWND_BROADCAST) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fallback
|
||||
return SendMessage_real(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
DDRGame::DDRGame() : Game("Dance Dance Revolution") {
|
||||
}
|
||||
|
||||
void DDRGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// dinput hook on this dll since the game dll doesn't load it
|
||||
auto game_mdx = libutils::try_library(MODULE_PATH / "gamemdx.dll");
|
||||
hooks::input::dinput8::init(game_mdx);
|
||||
|
||||
// init device hook
|
||||
devicehook_init();
|
||||
|
||||
// add fake devices
|
||||
if (avs::game::DLL_NAME == "arkmdxbio2.dll") {
|
||||
devicehook_add(new acioemu::ACIOHandle(L"COM1"));
|
||||
} else {
|
||||
devicehook_add(new DDRFOOTHandle());
|
||||
devicehook_add(new DDRSATEHandle());
|
||||
devicehook_add(new DDRUSBMEMHandle());
|
||||
devicehook_add(new DDRP3IOHandle());
|
||||
}
|
||||
|
||||
// has nothing to do with P3IO, but is enough to trick the game into SD/HD mode
|
||||
const char *settings_property = ddr::SDMODE ? "Generic Television" : "Generic Monitor";
|
||||
const char settings_detail[] = R"(\\.\P3IO)";
|
||||
|
||||
// settings 1
|
||||
SETUPAPI_SETTINGS settings1 {};
|
||||
settings1.class_guid[0] = 0x1FA4A480;
|
||||
settings1.class_guid[1] = 0x40C7AC60;
|
||||
settings1.class_guid[2] = 0x7952ACA7;
|
||||
settings1.class_guid[3] = 0x5A57340F;
|
||||
memcpy(settings1.property_devicedesc, settings_property, strlen(settings_property) + 1);
|
||||
memcpy(settings1.interface_detail, settings_detail, sizeof(settings_detail));
|
||||
|
||||
// settings 2
|
||||
SETUPAPI_SETTINGS settings2 {};
|
||||
settings2.class_guid[0] = 0x4D36E96E;
|
||||
settings2.class_guid[1] = 0x11CEE325;
|
||||
settings2.class_guid[2] = 0x8C1BF;
|
||||
settings2.class_guid[3] = 0x1803E12B;
|
||||
memcpy(settings2.property_devicedesc, settings_property, strlen(settings_property) + 1);
|
||||
memcpy(settings2.interface_detail, settings_detail, sizeof(settings_detail));
|
||||
|
||||
// init SETUP API
|
||||
setupapihook_init(avs::game::DLL_INSTANCE);
|
||||
|
||||
// DDR ACE actually uses another DLL for things
|
||||
if (game_mdx != nullptr) {
|
||||
setupapihook_init(game_mdx);
|
||||
}
|
||||
|
||||
// add settings
|
||||
setupapihook_add(settings1);
|
||||
setupapihook_add(settings2);
|
||||
|
||||
// misc hooks
|
||||
detour::iat_try("GetAsyncKeyState", GetAsyncKeyState_hook, avs::game::DLL_INSTANCE);
|
||||
detour::iat_try("GetKeyState", GetAsyncKeyState_hook, avs::game::DLL_INSTANCE);
|
||||
SendMessage_real = detour::iat_try("SendMessageW", SendMessage_hook, avs::game::DLL_INSTANCE);
|
||||
detour::iat_try("SendMessageA", SendMessage_hook, avs::game::DLL_INSTANCE);
|
||||
}
|
||||
|
||||
void DDRGame::detach() {
|
||||
Game::detach();
|
||||
|
||||
// dispose device hook
|
||||
devicehook_dispose();
|
||||
}
|
||||
}
|
||||
#include "ddr.h"
|
||||
|
||||
#include "acioemu/handle.h"
|
||||
#include "avs/game.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "hooks/setupapihook.h"
|
||||
#include "hooks/sleephook.h"
|
||||
#include "hooks/input/dinput8/hook.h"
|
||||
#include "util/utils.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "util/detour.h"
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#include "p3io/foot.h"
|
||||
#include "p3io/p3io.h"
|
||||
#include "p3io/sate.h"
|
||||
#include "p3io/usbmem.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
// settings
|
||||
bool SDMODE = false;
|
||||
|
||||
static decltype(SendMessage) *SendMessage_real = nullptr;
|
||||
|
||||
static SHORT WINAPI GetAsyncKeyState_hook(int vKey) {
|
||||
|
||||
// disable debug keys
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI SendMessage_hook(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
// ignore broadcasts
|
||||
if (hWnd == HWND_BROADCAST) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fallback
|
||||
return SendMessage_real(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
DDRGame::DDRGame() : Game("Dance Dance Revolution") {
|
||||
}
|
||||
|
||||
void DDRGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// dinput hook on this dll since the game dll doesn't load it
|
||||
auto game_mdx = libutils::try_library(MODULE_PATH / "gamemdx.dll");
|
||||
hooks::input::dinput8::init(game_mdx);
|
||||
|
||||
// init device hook
|
||||
devicehook_init();
|
||||
|
||||
// add fake devices
|
||||
if (avs::game::DLL_NAME == "arkmdxbio2.dll") {
|
||||
devicehook_add(new acioemu::ACIOHandle(L"COM1"));
|
||||
} else {
|
||||
devicehook_add(new DDRFOOTHandle());
|
||||
devicehook_add(new DDRSATEHandle());
|
||||
devicehook_add(new DDRUSBMEMHandle());
|
||||
devicehook_add(new DDRP3IOHandle());
|
||||
}
|
||||
|
||||
// has nothing to do with P3IO, but is enough to trick the game into SD/HD mode
|
||||
const char *settings_property = ddr::SDMODE ? "Generic Television" : "Generic Monitor";
|
||||
const char settings_detail[] = R"(\\.\P3IO)";
|
||||
|
||||
// settings 1
|
||||
SETUPAPI_SETTINGS settings1 {};
|
||||
settings1.class_guid[0] = 0x1FA4A480;
|
||||
settings1.class_guid[1] = 0x40C7AC60;
|
||||
settings1.class_guid[2] = 0x7952ACA7;
|
||||
settings1.class_guid[3] = 0x5A57340F;
|
||||
memcpy(settings1.property_devicedesc, settings_property, strlen(settings_property) + 1);
|
||||
memcpy(settings1.interface_detail, settings_detail, sizeof(settings_detail));
|
||||
|
||||
// settings 2
|
||||
SETUPAPI_SETTINGS settings2 {};
|
||||
settings2.class_guid[0] = 0x4D36E96E;
|
||||
settings2.class_guid[1] = 0x11CEE325;
|
||||
settings2.class_guid[2] = 0x8C1BF;
|
||||
settings2.class_guid[3] = 0x1803E12B;
|
||||
memcpy(settings2.property_devicedesc, settings_property, strlen(settings_property) + 1);
|
||||
memcpy(settings2.interface_detail, settings_detail, sizeof(settings_detail));
|
||||
|
||||
// init SETUP API
|
||||
setupapihook_init(avs::game::DLL_INSTANCE);
|
||||
|
||||
// DDR ACE actually uses another DLL for things
|
||||
if (game_mdx != nullptr) {
|
||||
setupapihook_init(game_mdx);
|
||||
}
|
||||
|
||||
// add settings
|
||||
setupapihook_add(settings1);
|
||||
setupapihook_add(settings2);
|
||||
|
||||
// misc hooks
|
||||
detour::iat_try("GetAsyncKeyState", GetAsyncKeyState_hook, avs::game::DLL_INSTANCE);
|
||||
detour::iat_try("GetKeyState", GetAsyncKeyState_hook, avs::game::DLL_INSTANCE);
|
||||
SendMessage_real = detour::iat_try("SendMessageW", SendMessage_hook, avs::game::DLL_INSTANCE);
|
||||
detour::iat_try("SendMessageA", SendMessage_hook, avs::game::DLL_INSTANCE);
|
||||
}
|
||||
|
||||
void DDRGame::detach() {
|
||||
Game::detach();
|
||||
|
||||
// dispose device hook
|
||||
devicehook_dispose();
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
// settings
|
||||
extern bool SDMODE;
|
||||
|
||||
class DDRGame : public games::Game {
|
||||
public:
|
||||
DDRGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
// settings
|
||||
extern bool SDMODE;
|
||||
|
||||
class DDRGame : public games::Game {
|
||||
public:
|
||||
DDRGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+87
-87
@@ -1,87 +1,87 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::ddr::get_buttons() {
|
||||
static std::vector<Button> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Buttons::getButtons("Dance Dance Revolution");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&analogs,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"P1 Start",
|
||||
"P1 Panel Up",
|
||||
"P1 Panel Down",
|
||||
"P1 Panel Left",
|
||||
"P1 Panel Right",
|
||||
"P1 Menu Up",
|
||||
"P1 Menu Down",
|
||||
"P1 Menu Left",
|
||||
"P1 Menu Right",
|
||||
"P2 Start",
|
||||
"P2 Panel Up",
|
||||
"P2 Panel Down",
|
||||
"P2 Panel Left",
|
||||
"P2 Panel Right",
|
||||
"P2 Menu Up",
|
||||
"P2 Menu Down",
|
||||
"P2 Menu Left",
|
||||
"P2 Menu Right"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::ddr::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Dance Dance Revolution");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"P1 Foot Left",
|
||||
"P1 Foot Up",
|
||||
"P1 Foot Right",
|
||||
"P1 Foot Down",
|
||||
"P2 Foot Left",
|
||||
"P2 Foot Up",
|
||||
"P2 Foot Right",
|
||||
"P2 Foot Down",
|
||||
"Spot Red",
|
||||
"Spot Blue",
|
||||
"Top Spot Red",
|
||||
"Top Spot Blue",
|
||||
"P1 Halogen Upper",
|
||||
"P1 Halogen Lower",
|
||||
"P2 Halogen Upper",
|
||||
"P2 Halogen Lower",
|
||||
"P1 Button",
|
||||
"P2 Button",
|
||||
"Neon",
|
||||
"HD P1 Start",
|
||||
"HD P1 Menu Left-Right",
|
||||
"HD P1 Menu Up-Down",
|
||||
"HD P2 Start",
|
||||
"HD P2 Menu Left-Right",
|
||||
"HD P2 Menu Up-Down",
|
||||
"HD P1 Speaker F R",
|
||||
"HD P1 Speaker F G",
|
||||
"HD P1 Speaker F B",
|
||||
"HD P1 Speaker W R",
|
||||
"HD P1 Speaker W G",
|
||||
"HD P1 Speaker W B",
|
||||
"HD P2 Speaker F R",
|
||||
"HD P2 Speaker F G",
|
||||
"HD P2 Speaker F B",
|
||||
"HD P2 Speaker W R",
|
||||
"HD P2 Speaker W G",
|
||||
"HD P2 Speaker W B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::ddr::get_buttons() {
|
||||
static std::vector<Button> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Buttons::getButtons("Dance Dance Revolution");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&analogs,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"P1 Start",
|
||||
"P1 Panel Up",
|
||||
"P1 Panel Down",
|
||||
"P1 Panel Left",
|
||||
"P1 Panel Right",
|
||||
"P1 Menu Up",
|
||||
"P1 Menu Down",
|
||||
"P1 Menu Left",
|
||||
"P1 Menu Right",
|
||||
"P2 Start",
|
||||
"P2 Panel Up",
|
||||
"P2 Panel Down",
|
||||
"P2 Panel Left",
|
||||
"P2 Panel Right",
|
||||
"P2 Menu Up",
|
||||
"P2 Menu Down",
|
||||
"P2 Menu Left",
|
||||
"P2 Menu Right"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::ddr::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Dance Dance Revolution");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"P1 Foot Left",
|
||||
"P1 Foot Up",
|
||||
"P1 Foot Right",
|
||||
"P1 Foot Down",
|
||||
"P2 Foot Left",
|
||||
"P2 Foot Up",
|
||||
"P2 Foot Right",
|
||||
"P2 Foot Down",
|
||||
"Spot Red",
|
||||
"Spot Blue",
|
||||
"Top Spot Red",
|
||||
"Top Spot Blue",
|
||||
"P1 Halogen Upper",
|
||||
"P1 Halogen Lower",
|
||||
"P2 Halogen Upper",
|
||||
"P2 Halogen Lower",
|
||||
"P1 Button",
|
||||
"P2 Button",
|
||||
"Neon",
|
||||
"HD P1 Start",
|
||||
"HD P1 Menu Left-Right",
|
||||
"HD P1 Menu Up-Down",
|
||||
"HD P2 Start",
|
||||
"HD P2 Menu Left-Right",
|
||||
"HD P2 Menu Up-Down",
|
||||
"HD P1 Speaker F R",
|
||||
"HD P1 Speaker F G",
|
||||
"HD P1 Speaker F B",
|
||||
"HD P1 Speaker W R",
|
||||
"HD P1 Speaker W G",
|
||||
"HD P1 Speaker W B",
|
||||
"HD P2 Speaker F R",
|
||||
"HD P2 Speaker F G",
|
||||
"HD P2 Speaker F B",
|
||||
"HD P2 Speaker W R",
|
||||
"HD P2 Speaker W G",
|
||||
"HD P2 Speaker W B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+82
-82
@@ -1,82 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
SERVICE,
|
||||
TEST,
|
||||
COIN_MECH,
|
||||
P1_START,
|
||||
P1_PANEL_UP,
|
||||
P1_PANEL_DOWN,
|
||||
P1_PANEL_LEFT,
|
||||
P1_PANEL_RIGHT,
|
||||
P1_MENU_UP,
|
||||
P1_MENU_DOWN,
|
||||
P1_MENU_LEFT,
|
||||
P1_MENU_RIGHT,
|
||||
P2_START,
|
||||
P2_PANEL_UP,
|
||||
P2_PANEL_DOWN,
|
||||
P2_PANEL_LEFT,
|
||||
P2_PANEL_RIGHT,
|
||||
P2_MENU_UP,
|
||||
P2_MENU_DOWN,
|
||||
P2_MENU_LEFT,
|
||||
P2_MENU_RIGHT,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
P1_FOOT_LEFT,
|
||||
P1_FOOT_UP,
|
||||
P1_FOOT_RIGHT,
|
||||
P1_FOOT_DOWN,
|
||||
P2_FOOT_LEFT,
|
||||
P2_FOOT_UP,
|
||||
P2_FOOT_RIGHT,
|
||||
P2_FOOT_DOWN,
|
||||
SPOT_RED,
|
||||
SPOT_BLUE,
|
||||
TOP_SPOT_RED,
|
||||
TOP_SPOT_BLUE,
|
||||
P1_HALOGEN_UPPER,
|
||||
P1_HALOGEN_LOWER,
|
||||
P2_HALOGEN_UPPER,
|
||||
P2_HALOGEN_LOWER,
|
||||
P1_BUTTON,
|
||||
P2_BUTTON,
|
||||
NEON,
|
||||
HD_P1_START,
|
||||
HD_P1_LEFT_RIGHT,
|
||||
HD_P1_UP_DOWN,
|
||||
HD_P2_START,
|
||||
HD_P2_LEFT_RIGHT,
|
||||
HD_P2_UP_DOWN,
|
||||
HD_P1_SPEAKER_F_R,
|
||||
HD_P1_SPEAKER_F_G,
|
||||
HD_P1_SPEAKER_F_B,
|
||||
HD_P1_SPEAKER_W_R,
|
||||
HD_P1_SPEAKER_W_G,
|
||||
HD_P1_SPEAKER_W_B,
|
||||
HD_P2_SPEAKER_F_R,
|
||||
HD_P2_SPEAKER_F_G,
|
||||
HD_P2_SPEAKER_F_B,
|
||||
HD_P2_SPEAKER_W_R,
|
||||
HD_P2_SPEAKER_W_G,
|
||||
HD_P2_SPEAKER_W_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
SERVICE,
|
||||
TEST,
|
||||
COIN_MECH,
|
||||
P1_START,
|
||||
P1_PANEL_UP,
|
||||
P1_PANEL_DOWN,
|
||||
P1_PANEL_LEFT,
|
||||
P1_PANEL_RIGHT,
|
||||
P1_MENU_UP,
|
||||
P1_MENU_DOWN,
|
||||
P1_MENU_LEFT,
|
||||
P1_MENU_RIGHT,
|
||||
P2_START,
|
||||
P2_PANEL_UP,
|
||||
P2_PANEL_DOWN,
|
||||
P2_PANEL_LEFT,
|
||||
P2_PANEL_RIGHT,
|
||||
P2_MENU_UP,
|
||||
P2_MENU_DOWN,
|
||||
P2_MENU_LEFT,
|
||||
P2_MENU_RIGHT,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
P1_FOOT_LEFT,
|
||||
P1_FOOT_UP,
|
||||
P1_FOOT_RIGHT,
|
||||
P1_FOOT_DOWN,
|
||||
P2_FOOT_LEFT,
|
||||
P2_FOOT_UP,
|
||||
P2_FOOT_RIGHT,
|
||||
P2_FOOT_DOWN,
|
||||
SPOT_RED,
|
||||
SPOT_BLUE,
|
||||
TOP_SPOT_RED,
|
||||
TOP_SPOT_BLUE,
|
||||
P1_HALOGEN_UPPER,
|
||||
P1_HALOGEN_LOWER,
|
||||
P2_HALOGEN_UPPER,
|
||||
P2_HALOGEN_LOWER,
|
||||
P1_BUTTON,
|
||||
P2_BUTTON,
|
||||
NEON,
|
||||
HD_P1_START,
|
||||
HD_P1_LEFT_RIGHT,
|
||||
HD_P1_UP_DOWN,
|
||||
HD_P2_START,
|
||||
HD_P2_LEFT_RIGHT,
|
||||
HD_P2_UP_DOWN,
|
||||
HD_P1_SPEAKER_F_R,
|
||||
HD_P1_SPEAKER_F_G,
|
||||
HD_P1_SPEAKER_F_B,
|
||||
HD_P1_SPEAKER_W_R,
|
||||
HD_P1_SPEAKER_W_G,
|
||||
HD_P1_SPEAKER_W_B,
|
||||
HD_P2_SPEAKER_F_R,
|
||||
HD_P2_SPEAKER_F_G,
|
||||
HD_P2_SPEAKER_F_B,
|
||||
HD_P2_SPEAKER_W_R,
|
||||
HD_P2_SPEAKER_W_G,
|
||||
HD_P2_SPEAKER_W_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+92
-92
@@ -1,92 +1,92 @@
|
||||
#include "foot.h"
|
||||
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "../ddr.h"
|
||||
#include "../io.h"
|
||||
|
||||
bool games::ddr::DDRFOOTHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("ddr", "Opened COM1 (FOOT)");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::ddr::DDRFOOTHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// check data trigger and buffer size
|
||||
if (data_trigger && nNumberOfBytesToRead >= 1) {
|
||||
data_trigger = false;
|
||||
memset(lpBuffer, 0x11, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// no data
|
||||
return 0;
|
||||
}
|
||||
|
||||
int games::ddr::DDRFOOTHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// check buffer size for lights
|
||||
if (nNumberOfBytesToWrite == 4) {
|
||||
|
||||
// mappings
|
||||
static const size_t mapping_bits[] = {
|
||||
4, 6, 3, 5, // P1 L, U, R, D,
|
||||
12, 14, 11, 13, // P2 L, U, R, D
|
||||
22 // NEON
|
||||
};
|
||||
|
||||
static const size_t mapping[] = {
|
||||
Lights::P1_FOOT_LEFT,
|
||||
Lights::P1_FOOT_UP,
|
||||
Lights::P1_FOOT_RIGHT,
|
||||
Lights::P1_FOOT_DOWN,
|
||||
Lights::P2_FOOT_LEFT,
|
||||
Lights::P2_FOOT_UP,
|
||||
Lights::P2_FOOT_RIGHT,
|
||||
Lights::P2_FOOT_DOWN,
|
||||
Lights::NEON
|
||||
};
|
||||
|
||||
// get light bits
|
||||
uint32_t light_bits = *((uint32_t*) lpBuffer);
|
||||
|
||||
// get lights
|
||||
auto &lights = get_lights();
|
||||
|
||||
// bit scan
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
float value = (light_bits & (1 << mapping_bits[i])) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
|
||||
}
|
||||
|
||||
// only set the neon if in SD mode
|
||||
// p3io sets it for HD mode.
|
||||
if (games::ddr::SDMODE) {
|
||||
float value = (light_bits & (1 << mapping_bits[8])) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[8]), value);
|
||||
}
|
||||
|
||||
// flush
|
||||
RI_MGR->devices_flush_output();
|
||||
}
|
||||
|
||||
// trigger out data
|
||||
data_trigger = true;
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::ddr::DDRFOOTHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRFOOTHandle::close() {
|
||||
log_info("ddr", "Closed COM1 (FOOT).");
|
||||
return true;
|
||||
}
|
||||
#include "foot.h"
|
||||
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "../ddr.h"
|
||||
#include "../io.h"
|
||||
|
||||
bool games::ddr::DDRFOOTHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("ddr", "Opened COM1 (FOOT)");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::ddr::DDRFOOTHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// check data trigger and buffer size
|
||||
if (data_trigger && nNumberOfBytesToRead >= 1) {
|
||||
data_trigger = false;
|
||||
memset(lpBuffer, 0x11, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// no data
|
||||
return 0;
|
||||
}
|
||||
|
||||
int games::ddr::DDRFOOTHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// check buffer size for lights
|
||||
if (nNumberOfBytesToWrite == 4) {
|
||||
|
||||
// mappings
|
||||
static const size_t mapping_bits[] = {
|
||||
4, 6, 3, 5, // P1 L, U, R, D,
|
||||
12, 14, 11, 13, // P2 L, U, R, D
|
||||
22 // NEON
|
||||
};
|
||||
|
||||
static const size_t mapping[] = {
|
||||
Lights::P1_FOOT_LEFT,
|
||||
Lights::P1_FOOT_UP,
|
||||
Lights::P1_FOOT_RIGHT,
|
||||
Lights::P1_FOOT_DOWN,
|
||||
Lights::P2_FOOT_LEFT,
|
||||
Lights::P2_FOOT_UP,
|
||||
Lights::P2_FOOT_RIGHT,
|
||||
Lights::P2_FOOT_DOWN,
|
||||
Lights::NEON
|
||||
};
|
||||
|
||||
// get light bits
|
||||
uint32_t light_bits = *((uint32_t*) lpBuffer);
|
||||
|
||||
// get lights
|
||||
auto &lights = get_lights();
|
||||
|
||||
// bit scan
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
float value = (light_bits & (1 << mapping_bits[i])) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
|
||||
}
|
||||
|
||||
// only set the neon if in SD mode
|
||||
// p3io sets it for HD mode.
|
||||
if (games::ddr::SDMODE) {
|
||||
float value = (light_bits & (1 << mapping_bits[8])) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[8]), value);
|
||||
}
|
||||
|
||||
// flush
|
||||
RI_MGR->devices_flush_output();
|
||||
}
|
||||
|
||||
// trigger out data
|
||||
data_trigger = true;
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::ddr::DDRFOOTHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRFOOTHandle::close() {
|
||||
log_info("ddr", "Closed COM1 (FOOT).");
|
||||
return true;
|
||||
}
|
||||
|
||||
+23
-23
@@ -1,23 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRFOOTHandle : public CustomHandle {
|
||||
private:
|
||||
bool data_trigger = false;
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRFOOTHandle : public CustomHandle {
|
||||
private:
|
||||
bool data_trigger = false;
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+550
-550
File diff suppressed because it is too large
Load Diff
+37
-37
@@ -1,37 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "acioemu/acioemu.h"
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRP3IOHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu *acio_emu;
|
||||
circular_buffer<uint8_t> read_buf = circular_buffer<uint8_t>(1024);
|
||||
|
||||
class HDXSDevice : public acioemu::ACIODeviceEmu {
|
||||
public:
|
||||
HDXSDevice();
|
||||
|
||||
bool parse_msg(
|
||||
acioemu::MessageData* msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) override;
|
||||
};
|
||||
|
||||
void write_msg(const uint8_t *data, size_t len);
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "acioemu/acioemu.h"
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRP3IOHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu *acio_emu;
|
||||
circular_buffer<uint8_t> read_buf = circular_buffer<uint8_t>(1024);
|
||||
|
||||
class HDXSDevice : public acioemu::ACIODeviceEmu {
|
||||
public:
|
||||
HDXSDevice();
|
||||
|
||||
bool parse_msg(
|
||||
acioemu::MessageData* msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) override;
|
||||
};
|
||||
|
||||
void write_msg(const uint8_t *data, size_t len);
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+102
-102
@@ -1,102 +1,102 @@
|
||||
#include "sate.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
games::ddr::DDRSATEHandle::SATEDevice::SATEDevice() {
|
||||
this->node_count = 7;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRSATEHandle::SATEDevice::parse_msg(
|
||||
acioemu::MessageData *msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) {
|
||||
|
||||
// check command
|
||||
switch (msg_in->cmd.code) {
|
||||
case ACIO_CMD_GET_VERSION: {
|
||||
|
||||
// send version data
|
||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||
this->set_version(msg, 0x105, 0, 1, 1, 0, "DDRS");
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case ACIO_CMD_CLEAR:
|
||||
case ACIO_CMD_STARTUP:
|
||||
case 0xFF: // BROADCAST
|
||||
{
|
||||
// send status 0
|
||||
auto msg = this->create_msg_status(msg_in, 0x00);
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark as handled
|
||||
return true;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRSATEHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM2") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("ddr", "Opened COM2 (SATE)");
|
||||
|
||||
// ACIO device
|
||||
acio_emu.add_device(new SATEDevice());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::ddr::DDRSATEHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
|
||||
|
||||
// read from emu
|
||||
DWORD bytes_read = 0;
|
||||
while (bytes_read < nNumberOfBytesToRead) {
|
||||
auto cur_byte = acio_emu.read();
|
||||
|
||||
if (cur_byte.has_value()) {
|
||||
buffer[bytes_read++] = cur_byte.value();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// return amount of bytes read
|
||||
return (int) bytes_read;
|
||||
}
|
||||
|
||||
int games::ddr::DDRSATEHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
|
||||
|
||||
// write to emu
|
||||
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
|
||||
acio_emu.write(buffer[i]);
|
||||
}
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::ddr::DDRSATEHandle::device_io(
|
||||
DWORD dwIoControlCode,
|
||||
LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRSATEHandle::close() {
|
||||
log_info("ddr", "Closed COM2 (SATE).");
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "sate.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
games::ddr::DDRSATEHandle::SATEDevice::SATEDevice() {
|
||||
this->node_count = 7;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRSATEHandle::SATEDevice::parse_msg(
|
||||
acioemu::MessageData *msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) {
|
||||
|
||||
// check command
|
||||
switch (msg_in->cmd.code) {
|
||||
case ACIO_CMD_GET_VERSION: {
|
||||
|
||||
// send version data
|
||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||
this->set_version(msg, 0x105, 0, 1, 1, 0, "DDRS");
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case ACIO_CMD_CLEAR:
|
||||
case ACIO_CMD_STARTUP:
|
||||
case 0xFF: // BROADCAST
|
||||
{
|
||||
// send status 0
|
||||
auto msg = this->create_msg_status(msg_in, 0x00);
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark as handled
|
||||
return true;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRSATEHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM2") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("ddr", "Opened COM2 (SATE)");
|
||||
|
||||
// ACIO device
|
||||
acio_emu.add_device(new SATEDevice());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::ddr::DDRSATEHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
|
||||
|
||||
// read from emu
|
||||
DWORD bytes_read = 0;
|
||||
while (bytes_read < nNumberOfBytesToRead) {
|
||||
auto cur_byte = acio_emu.read();
|
||||
|
||||
if (cur_byte.has_value()) {
|
||||
buffer[bytes_read++] = cur_byte.value();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// return amount of bytes read
|
||||
return (int) bytes_read;
|
||||
}
|
||||
|
||||
int games::ddr::DDRSATEHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
|
||||
|
||||
// write to emu
|
||||
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
|
||||
acio_emu.write(buffer[i]);
|
||||
}
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::ddr::DDRSATEHandle::device_io(
|
||||
DWORD dwIoControlCode,
|
||||
LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRSATEHandle::close() {
|
||||
log_info("ddr", "Closed COM2 (SATE).");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
#include "acioemu/acioemu.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRSATEHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu acio_emu;
|
||||
|
||||
class SATEDevice : public acioemu::ACIODeviceEmu {
|
||||
public:
|
||||
SATEDevice();
|
||||
|
||||
bool parse_msg(acioemu::MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
|
||||
};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
#include "acioemu/acioemu.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRSATEHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu acio_emu;
|
||||
|
||||
class SATEDevice : public acioemu::ACIODeviceEmu {
|
||||
public:
|
||||
SATEDevice();
|
||||
|
||||
bool parse_msg(acioemu::MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
|
||||
};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+60
-60
@@ -1,60 +1,60 @@
|
||||
#include "usbmem.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
void games::ddr::DDRUSBMEMHandle::respond(const char *data) {
|
||||
size_t len = strlen(data) + 1;
|
||||
memcpy(response_data, data, len);
|
||||
memcpy(response_data + len, "\r>", 2);
|
||||
response_data_size = len + 2;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRUSBMEMHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM3") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("ddr", "Opened COM3 (USBMEM)");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::ddr::DDRUSBMEMHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// check for response
|
||||
if (response_data_size && nNumberOfBytesToRead >= response_data_size) {
|
||||
size_t bytes_read = response_data_size;
|
||||
memcpy(lpBuffer, response_data, response_data_size);
|
||||
response_data_size = 0;
|
||||
return (int) bytes_read;
|
||||
}
|
||||
|
||||
// no data
|
||||
return 0;
|
||||
}
|
||||
|
||||
int games::ddr::DDRUSBMEMHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// check CMD
|
||||
if (!memcmp(lpBuffer, "sver", 4))
|
||||
respond("done GQHDXJAA SPICE");
|
||||
else if (!memcmp(lpBuffer, "on_a", 4) ||
|
||||
!memcmp(lpBuffer, "on_b", 4) ||
|
||||
!memcmp(lpBuffer, "offa", 4) ||
|
||||
!memcmp(lpBuffer, "offb", 4) ||
|
||||
!memcmp(lpBuffer, "lma ", 4) ||
|
||||
!memcmp(lpBuffer, "lmb ", 4))
|
||||
respond("done");
|
||||
else
|
||||
respond("not connected");
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::ddr::DDRUSBMEMHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRUSBMEMHandle::close() {
|
||||
log_info("ddr", "Closed COM3 (USBMEM).");
|
||||
return true;
|
||||
}
|
||||
#include "usbmem.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
void games::ddr::DDRUSBMEMHandle::respond(const char *data) {
|
||||
size_t len = strlen(data) + 1;
|
||||
memcpy(response_data, data, len);
|
||||
memcpy(response_data + len, "\r>", 2);
|
||||
response_data_size = len + 2;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRUSBMEMHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM3") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("ddr", "Opened COM3 (USBMEM)");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::ddr::DDRUSBMEMHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// check for response
|
||||
if (response_data_size && nNumberOfBytesToRead >= response_data_size) {
|
||||
size_t bytes_read = response_data_size;
|
||||
memcpy(lpBuffer, response_data, response_data_size);
|
||||
response_data_size = 0;
|
||||
return (int) bytes_read;
|
||||
}
|
||||
|
||||
// no data
|
||||
return 0;
|
||||
}
|
||||
|
||||
int games::ddr::DDRUSBMEMHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// check CMD
|
||||
if (!memcmp(lpBuffer, "sver", 4))
|
||||
respond("done GQHDXJAA SPICE");
|
||||
else if (!memcmp(lpBuffer, "on_a", 4) ||
|
||||
!memcmp(lpBuffer, "on_b", 4) ||
|
||||
!memcmp(lpBuffer, "offa", 4) ||
|
||||
!memcmp(lpBuffer, "offb", 4) ||
|
||||
!memcmp(lpBuffer, "lma ", 4) ||
|
||||
!memcmp(lpBuffer, "lmb ", 4))
|
||||
respond("done");
|
||||
else
|
||||
respond("not connected");
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::ddr::DDRUSBMEMHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::ddr::DDRUSBMEMHandle::close() {
|
||||
log_info("ddr", "Closed COM3 (USBMEM).");
|
||||
return true;
|
||||
}
|
||||
|
||||
+26
-26
@@ -1,26 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRUSBMEMHandle : public CustomHandle {
|
||||
private:
|
||||
char response_data[256]{};
|
||||
size_t response_data_size = 0;
|
||||
|
||||
void respond(const char *data);
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::ddr {
|
||||
|
||||
class DDRUSBMEMHandle : public CustomHandle {
|
||||
private:
|
||||
char response_data[256]{};
|
||||
size_t response_data_size = 0;
|
||||
|
||||
void respond(const char *data);
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+26
-26
@@ -1,26 +1,26 @@
|
||||
#include "dea.h"
|
||||
|
||||
#include "launcher/launcher.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace games::dea {
|
||||
|
||||
DEAGame::DEAGame() : Game("Dance Evolution") {
|
||||
}
|
||||
|
||||
void DEAGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// since this DLL isn't automatically loaded the hooks don't work unless we load it manually
|
||||
libutils::try_library(MODULE_PATH / "gamekdm.dll");
|
||||
|
||||
// Has the user actually performed first-time setup?
|
||||
auto kinect10 = libutils::try_library("Kinect10.dll");
|
||||
if (!kinect10) {
|
||||
log_warning("dea", "Failed to load 'Kinect10.dll'. Game will boot in Test Mode. Have you installed the Kinect SDK?");
|
||||
} else {
|
||||
FreeLibrary(kinect10);
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "dea.h"
|
||||
|
||||
#include "launcher/launcher.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace games::dea {
|
||||
|
||||
DEAGame::DEAGame() : Game("Dance Evolution") {
|
||||
}
|
||||
|
||||
void DEAGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// since this DLL isn't automatically loaded the hooks don't work unless we load it manually
|
||||
libutils::try_library(MODULE_PATH / "gamekdm.dll");
|
||||
|
||||
// Has the user actually performed first-time setup?
|
||||
auto kinect10 = libutils::try_library("Kinect10.dll");
|
||||
if (!kinect10) {
|
||||
log_warning("dea", "Failed to load 'Kinect10.dll'. Game will boot in Test Mode. Have you installed the Kinect SDK?");
|
||||
} else {
|
||||
FreeLibrary(kinect10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::dea {
|
||||
|
||||
class DEAGame : public games::Game {
|
||||
public:
|
||||
DEAGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::dea {
|
||||
|
||||
class DEAGame : public games::Game {
|
||||
public:
|
||||
DEAGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+68
-68
@@ -1,68 +1,68 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::dea::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Dance Evolution");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"P1 Start",
|
||||
"P1 Left",
|
||||
"P1 Right",
|
||||
"P2 Start",
|
||||
"P2 Left",
|
||||
"P2 Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::dea::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Dance Evolution");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Side Upper Left R",
|
||||
"Side Upper Left G",
|
||||
"Side Upper Left B",
|
||||
"Side Upper Right R",
|
||||
"Side Upper Right G",
|
||||
"Side Upper Right B",
|
||||
"P1 Start",
|
||||
"P1 L/R Button",
|
||||
"P2 Start",
|
||||
"P2 L/R Button",
|
||||
"Side Lower Left 1 R",
|
||||
"Side Lower Left 1 G",
|
||||
"Side Lower Left 1 B",
|
||||
"Side Lower Left 2 R",
|
||||
"Side Lower Left 2 G",
|
||||
"Side Lower Left 2 B",
|
||||
"Side Lower Left 3 R",
|
||||
"Side Lower Left 3 G",
|
||||
"Side Lower Left 3 B",
|
||||
"Side Lower Right 1 R",
|
||||
"Side Lower Right 1 G",
|
||||
"Side Lower Right 1 B",
|
||||
"Side Lower Right 2 R",
|
||||
"Side Lower Right 2 G",
|
||||
"Side Lower Right 2 B",
|
||||
"Side Lower Right 3 R",
|
||||
"Side Lower Right 3 G",
|
||||
"Side Lower Right 3 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::dea::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Dance Evolution");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"P1 Start",
|
||||
"P1 Left",
|
||||
"P1 Right",
|
||||
"P2 Start",
|
||||
"P2 Left",
|
||||
"P2 Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::dea::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Dance Evolution");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Side Upper Left R",
|
||||
"Side Upper Left G",
|
||||
"Side Upper Left B",
|
||||
"Side Upper Right R",
|
||||
"Side Upper Right G",
|
||||
"Side Upper Right B",
|
||||
"P1 Start",
|
||||
"P1 L/R Button",
|
||||
"P2 Start",
|
||||
"P2 L/R Button",
|
||||
"Side Lower Left 1 R",
|
||||
"Side Lower Left 1 G",
|
||||
"Side Lower Left 1 B",
|
||||
"Side Lower Left 2 R",
|
||||
"Side Lower Left 2 G",
|
||||
"Side Lower Left 2 B",
|
||||
"Side Lower Left 3 R",
|
||||
"Side Lower Left 3 G",
|
||||
"Side Lower Left 3 B",
|
||||
"Side Lower Right 1 R",
|
||||
"Side Lower Right 1 G",
|
||||
"Side Lower Right 1 B",
|
||||
"Side Lower Right 2 R",
|
||||
"Side Lower Right 2 G",
|
||||
"Side Lower Right 2 B",
|
||||
"Side Lower Right 3 R",
|
||||
"Side Lower Right 3 G",
|
||||
"Side Lower Right 3 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+62
-62
@@ -1,62 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::dea {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
P1Start,
|
||||
P1Left,
|
||||
P1Right,
|
||||
P2Start,
|
||||
P2Left,
|
||||
P2Right
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
SideUpperLeftR,
|
||||
SideUpperLeftG,
|
||||
SideUpperLeftB,
|
||||
SideUpperRightR,
|
||||
SideUpperRightG,
|
||||
SideUpperRightB,
|
||||
P1Start,
|
||||
P1LRButton,
|
||||
P2Start,
|
||||
P2LRButton,
|
||||
SideLowerLeft1R,
|
||||
SideLowerLeft1G,
|
||||
SideLowerLeft1B,
|
||||
SideLowerLeft2R,
|
||||
SideLowerLeft2G,
|
||||
SideLowerLeft2B,
|
||||
SideLowerLeft3R,
|
||||
SideLowerLeft3G,
|
||||
SideLowerLeft3B,
|
||||
SideLowerRight1R,
|
||||
SideLowerRight1G,
|
||||
SideLowerRight1B,
|
||||
SideLowerRight2R,
|
||||
SideLowerRight2G,
|
||||
SideLowerRight2B,
|
||||
SideLowerRight3R,
|
||||
SideLowerRight3G,
|
||||
SideLowerRight3B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::dea {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
P1Start,
|
||||
P1Left,
|
||||
P1Right,
|
||||
P2Start,
|
||||
P2Left,
|
||||
P2Right
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
SideUpperLeftR,
|
||||
SideUpperLeftG,
|
||||
SideUpperLeftB,
|
||||
SideUpperRightR,
|
||||
SideUpperRightG,
|
||||
SideUpperRightB,
|
||||
P1Start,
|
||||
P1LRButton,
|
||||
P2Start,
|
||||
P2LRButton,
|
||||
SideLowerLeft1R,
|
||||
SideLowerLeft1G,
|
||||
SideLowerLeft1B,
|
||||
SideLowerLeft2R,
|
||||
SideLowerLeft2G,
|
||||
SideLowerLeft2B,
|
||||
SideLowerLeft3R,
|
||||
SideLowerLeft3G,
|
||||
SideLowerLeft3B,
|
||||
SideLowerRight1R,
|
||||
SideLowerRight1G,
|
||||
SideLowerRight1B,
|
||||
SideLowerRight2R,
|
||||
SideLowerRight2G,
|
||||
SideLowerRight2B,
|
||||
SideLowerRight3R,
|
||||
SideLowerRight3G,
|
||||
SideLowerRight3B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+409
-409
@@ -1,409 +1,409 @@
|
||||
#include "drs.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <thread>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "games/game.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/memutils.h"
|
||||
#include "misc/vrutil.h"
|
||||
|
||||
#pragma pack(push)
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
WORD unk1;
|
||||
WORD unk2;
|
||||
WORD device_id;
|
||||
WORD vid;
|
||||
WORD pid;
|
||||
WORD pvn;
|
||||
WORD max_point_num;
|
||||
};
|
||||
uint8_t raw[2356];
|
||||
};
|
||||
} dev_info_t;
|
||||
|
||||
typedef struct {
|
||||
DWORD cid;
|
||||
DWORD type;
|
||||
DWORD unused;
|
||||
DWORD y;
|
||||
DWORD x;
|
||||
DWORD height;
|
||||
DWORD width;
|
||||
DWORD unk8;
|
||||
} touch_data_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
enum touch_type {
|
||||
TS_DOWN = 1,
|
||||
TS_MOVE = 2,
|
||||
TS_UP = 3,
|
||||
};
|
||||
|
||||
void *user_data = nullptr;
|
||||
void (*touch_callback)(
|
||||
dev_info_t *dev_info,
|
||||
const touch_data_t *touch_data,
|
||||
int touch_points,
|
||||
int unk1,
|
||||
const void *user_data);
|
||||
|
||||
namespace games::drs {
|
||||
|
||||
void* TouchSDK_Constructor(void* in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
bool TouchSDK_SendData(dev_info_t*,
|
||||
unsigned char * const, int, unsigned char * const,
|
||||
unsigned char* output, int output_size) {
|
||||
|
||||
// fake success
|
||||
if (output_size >= 4) {
|
||||
output[0] = 0xfc;
|
||||
output[1] = 0xa5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_SetSignalInit(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TouchSDK_Destructor(void* This) {
|
||||
}
|
||||
|
||||
int TouchSDK_GetYLedTotal(dev_info_t*, int) {
|
||||
return 53;
|
||||
}
|
||||
|
||||
int TouchSDK_GetXLedTotal(dev_info_t*, int) {
|
||||
return 41;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableTouch(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableDrag(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableWheel(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableRightClick(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_SetMultiTouchMode(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_EnableTouchWidthData(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_EnableRawData(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_SetAllEnable(dev_info_t*, bool, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int TouchSDK_GetTouchDeviceCount(void* This) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int TouchSDK_GetTouchSDKVersion(void) {
|
||||
return 0x01030307;
|
||||
}
|
||||
|
||||
int TouchSDK_InitTouch(void* This, dev_info_t *devices, int max_devices, void* touch_event_cb,
|
||||
void* hotplug_callback, void* userdata) {
|
||||
|
||||
// fake touch device
|
||||
memset(devices, 0, sizeof(devices[0].raw));
|
||||
devices[0].unk1 = 0x1122;
|
||||
devices[0].unk2 = 0x3344;
|
||||
devices[0].device_id = 0;
|
||||
devices[0].vid = 0xDEAD;
|
||||
devices[0].pid = 0xBEEF;
|
||||
devices[0].pvn = 0xC0DE;
|
||||
devices[0].max_point_num = 16;
|
||||
|
||||
// remember provided callback and userdata
|
||||
touch_callback = (decltype(touch_callback)) touch_event_cb;
|
||||
user_data = userdata;
|
||||
|
||||
// success
|
||||
return 1;
|
||||
}
|
||||
|
||||
char DRS_TAPELED[38 * 49][3] {};
|
||||
bool VR_STARTED = false;
|
||||
linalg::aliases::float3 VR_SCALE(100, 100, 1.f);
|
||||
linalg::aliases::float3 VR_OFFSET(0.f, 0.f, -0.1f);
|
||||
float VR_ROTATION = 0.f;
|
||||
VRFoot VR_FOOTS[2] {
|
||||
{1},
|
||||
{2},
|
||||
};
|
||||
|
||||
inline DWORD scale_double_to_xy(double val) {
|
||||
return static_cast<DWORD>(val * 32768);
|
||||
}
|
||||
|
||||
inline DWORD scale_double_to_height(double val) {
|
||||
return static_cast<DWORD>(val * 1312);
|
||||
}
|
||||
|
||||
inline DWORD scale_double_to_width(double val) {
|
||||
return static_cast<DWORD>(val * 1696);
|
||||
}
|
||||
|
||||
void fire_touches(drs_touch_t *events, size_t event_count) {
|
||||
|
||||
// check callback first
|
||||
if (!touch_callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// generate touch data
|
||||
auto game_touches = std::make_unique<touch_data_t[]>(event_count);
|
||||
for (size_t i = 0; i < event_count; i++) {
|
||||
|
||||
// initialize touch value
|
||||
game_touches[i].cid = (DWORD) events[i].id;
|
||||
game_touches[i].unk8 = 0;
|
||||
|
||||
// copy scaled values
|
||||
game_touches[i].x = scale_double_to_xy(events[i].x);
|
||||
game_touches[i].y = scale_double_to_xy(events[i].y);
|
||||
game_touches[i].width = scale_double_to_width(events[i].width);
|
||||
game_touches[i].height = scale_double_to_height(events[i].height);
|
||||
|
||||
// decide touch type
|
||||
switch(events[i].type) {
|
||||
case DRS_DOWN:
|
||||
game_touches[i].type = TS_DOWN;
|
||||
break;
|
||||
case DRS_UP:
|
||||
game_touches[i].type = TS_UP;
|
||||
break;
|
||||
case DRS_MOVE:
|
||||
game_touches[i].type = TS_MOVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// build device information
|
||||
dev_info_t dev;
|
||||
dev.unk1 = 0;
|
||||
dev.unk2 = 0;
|
||||
dev.device_id = 0;
|
||||
dev.vid = 0xDEAD;
|
||||
dev.pid = 0xBEEF;
|
||||
dev.pvn = 0xC0DE;
|
||||
dev.max_point_num = 16;
|
||||
|
||||
// fire callback
|
||||
touch_callback(&dev, game_touches.get(), (int) event_count, 0, user_data);
|
||||
}
|
||||
|
||||
uint32_t VRFoot::get_index() {
|
||||
if (index == ~0u) {
|
||||
if (id == 1) return vrutil::INDEX_LEFT;
|
||||
if (id == 2) return vrutil::INDEX_RIGHT;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
linalg::aliases::float3 VRFoot::to_world(linalg::aliases::float3 pos) {
|
||||
pos = linalg::aliases::float3(-pos.z, pos.x, pos.y);
|
||||
const float deg_to_rad = (float) (1 / 180.f * M_PI);
|
||||
auto s = sinf(VR_ROTATION * deg_to_rad);
|
||||
auto c = cosf(VR_ROTATION * deg_to_rad);
|
||||
pos = linalg::aliases::float3(pos.x * c - pos.y * s,
|
||||
pos.x * s + pos.y * c,
|
||||
pos.z);
|
||||
return pos * VR_SCALE + VR_OFFSET;
|
||||
}
|
||||
|
||||
void start_vr() {
|
||||
if (vrutil::STATUS != vrutil::VRStatus::Running) return;
|
||||
if (!VR_STARTED) {
|
||||
VR_STARTED = true;
|
||||
std::thread t([] {
|
||||
log_info("drs", "starting VR thread");
|
||||
|
||||
// dance floor plane
|
||||
const linalg::aliases::float3 plane_normal(0, 0, 1);
|
||||
const linalg::aliases::float3 plane_point(0, 0, 0);
|
||||
const float touch_width = 1.f;
|
||||
const float touch_height = 1.f;
|
||||
|
||||
// main loop
|
||||
while (vrutil::STATUS == vrutil::VRStatus::Running) {
|
||||
|
||||
// iterate foots
|
||||
for (auto &foot : VR_FOOTS) {
|
||||
vr::TrackedDevicePose_t pose;
|
||||
vr::VRControllerState_t state;
|
||||
vrutil::get_con_pose(foot.get_index(), &pose, &state);
|
||||
|
||||
// only accept valid poses
|
||||
if (pose.bPoseIsValid) {
|
||||
auto length = std::max(foot.length, 0.001f);
|
||||
|
||||
// get components
|
||||
auto translation = foot.to_world(vrutil::get_translation(
|
||||
pose.mDeviceToAbsoluteTracking));
|
||||
auto direction = -linalg::qzdir(linalg::qmul(
|
||||
vrutil::get_rotation(pose.mDeviceToAbsoluteTracking.m),
|
||||
foot.rotation));
|
||||
direction = linalg::aliases::float3 {
|
||||
-direction.z, direction.x, direction.y
|
||||
};
|
||||
|
||||
// get intersection point
|
||||
auto intersection = vrutil::intersect_point(
|
||||
direction, translation,
|
||||
plane_normal, plane_point);
|
||||
auto distance = linalg::distance(
|
||||
translation, intersection);
|
||||
|
||||
// update event details
|
||||
foot.height = std::max(0.f, translation.z - intersection.z);
|
||||
foot.event.id = foot.id;
|
||||
foot.event.x = (intersection.x / 38.f) * touch_width;
|
||||
foot.event.y = (intersection.y / 49.f) * touch_height;
|
||||
if (translation.z > intersection.z) {
|
||||
foot.event.width = foot.size_base
|
||||
+ foot.size_scale * std::max(0.f, 1.f - distance / length);
|
||||
} else {
|
||||
foot.event.width = foot.size_base + foot.size_scale;
|
||||
}
|
||||
foot.event.height = foot.event.width;
|
||||
|
||||
// check if controller points down
|
||||
if (direction.z < 0) {
|
||||
|
||||
// check if plane in range
|
||||
if (distance <= length) {
|
||||
|
||||
// check previous event
|
||||
switch (foot.event.type) {
|
||||
case DRS_UP:
|
||||
|
||||
// generate down event
|
||||
foot.event.type = DRS_DOWN;
|
||||
break;
|
||||
|
||||
case DRS_DOWN:
|
||||
case DRS_MOVE:
|
||||
|
||||
// generate move event
|
||||
foot.event.type = DRS_MOVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// send event
|
||||
drs::fire_touches(&foot.event, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// foot not intersecting with plane
|
||||
switch (foot.event.type) {
|
||||
case DRS_DOWN:
|
||||
case DRS_MOVE:
|
||||
|
||||
// generate up event
|
||||
foot.event.type = DRS_UP;
|
||||
drs::fire_touches(&foot.event, 1);
|
||||
break;
|
||||
|
||||
case DRS_UP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// slow down
|
||||
vrutil::scan();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
VR_STARTED = false;
|
||||
return nullptr;
|
||||
});
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
|
||||
DRSGame::DRSGame() : Game("DANCERUSH") {
|
||||
}
|
||||
|
||||
void DRSGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// TouchSDK hooks
|
||||
detour::iat("??0TouchSDK@@QEAA@XZ",
|
||||
(void *) &TouchSDK_Constructor, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SendData@TouchSDK@@QEAA_NU_DeviceInfo@@QEAEH1HH@Z",
|
||||
(void *) &TouchSDK_SendData, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SetSignalInit@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_SetSignalInit, avs::game::DLL_INSTANCE);
|
||||
detour::iat("??1TouchSDK@@QEAA@XZ",
|
||||
(void *) &TouchSDK_Destructor, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetYLedTotal@TouchSDK@@QEAAHU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_GetYLedTotal, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetXLedTotal@TouchSDK@@QEAAHU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_GetXLedTotal, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableTouch@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableTouch, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableDrag@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableDrag, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableWheel@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableWheel, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableRightClick@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableRightClick, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SetMultiTouchMode@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_SetMultiTouchMode, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?EnableTouchWidthData@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_EnableTouchWidthData, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?EnableRawData@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_EnableRawData, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SetAllEnable@TouchSDK@@QEAA_NU_DeviceInfo@@_NH@Z",
|
||||
(void *) &TouchSDK_SetAllEnable, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetTouchDeviceCount@TouchSDK@@QEAAHXZ",
|
||||
(void *) &TouchSDK_GetTouchDeviceCount, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetTouchSDKVersion@TouchSDK@@QEAAIXZ",
|
||||
(void *) &TouchSDK_GetTouchSDKVersion, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?InitTouch@TouchSDK@@QEAAHPEAU_DeviceInfo@@HP6AXU2@PEBU_TouchPointData@@HHPEBX@ZP6AX1_N3@ZPEAX@Z",
|
||||
(void *) &TouchSDK_InitTouch, avs::game::DLL_INSTANCE);
|
||||
|
||||
// VR
|
||||
if (vrutil::STATUS == vrutil::VRStatus::Running) {
|
||||
start_vr();
|
||||
}
|
||||
}
|
||||
|
||||
void DRSGame::detach() {
|
||||
Game::detach();
|
||||
}
|
||||
}
|
||||
#include "drs.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <thread>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "games/game.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/memutils.h"
|
||||
#include "misc/vrutil.h"
|
||||
|
||||
#pragma pack(push)
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
WORD unk1;
|
||||
WORD unk2;
|
||||
WORD device_id;
|
||||
WORD vid;
|
||||
WORD pid;
|
||||
WORD pvn;
|
||||
WORD max_point_num;
|
||||
};
|
||||
uint8_t raw[2356];
|
||||
};
|
||||
} dev_info_t;
|
||||
|
||||
typedef struct {
|
||||
DWORD cid;
|
||||
DWORD type;
|
||||
DWORD unused;
|
||||
DWORD y;
|
||||
DWORD x;
|
||||
DWORD height;
|
||||
DWORD width;
|
||||
DWORD unk8;
|
||||
} touch_data_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
enum touch_type {
|
||||
TS_DOWN = 1,
|
||||
TS_MOVE = 2,
|
||||
TS_UP = 3,
|
||||
};
|
||||
|
||||
void *user_data = nullptr;
|
||||
void (*touch_callback)(
|
||||
dev_info_t *dev_info,
|
||||
const touch_data_t *touch_data,
|
||||
int touch_points,
|
||||
int unk1,
|
||||
const void *user_data);
|
||||
|
||||
namespace games::drs {
|
||||
|
||||
void* TouchSDK_Constructor(void* in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
bool TouchSDK_SendData(dev_info_t*,
|
||||
unsigned char * const, int, unsigned char * const,
|
||||
unsigned char* output, int output_size) {
|
||||
|
||||
// fake success
|
||||
if (output_size >= 4) {
|
||||
output[0] = 0xfc;
|
||||
output[1] = 0xa5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_SetSignalInit(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TouchSDK_Destructor(void* This) {
|
||||
}
|
||||
|
||||
int TouchSDK_GetYLedTotal(dev_info_t*, int) {
|
||||
return 53;
|
||||
}
|
||||
|
||||
int TouchSDK_GetXLedTotal(dev_info_t*, int) {
|
||||
return 41;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableTouch(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableDrag(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableWheel(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_DisableRightClick(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_SetMultiTouchMode(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_EnableTouchWidthData(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_EnableRawData(dev_info_t*, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TouchSDK_SetAllEnable(dev_info_t*, bool, int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int TouchSDK_GetTouchDeviceCount(void* This) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int TouchSDK_GetTouchSDKVersion(void) {
|
||||
return 0x01030307;
|
||||
}
|
||||
|
||||
int TouchSDK_InitTouch(void* This, dev_info_t *devices, int max_devices, void* touch_event_cb,
|
||||
void* hotplug_callback, void* userdata) {
|
||||
|
||||
// fake touch device
|
||||
memset(devices, 0, sizeof(devices[0].raw));
|
||||
devices[0].unk1 = 0x1122;
|
||||
devices[0].unk2 = 0x3344;
|
||||
devices[0].device_id = 0;
|
||||
devices[0].vid = 0xDEAD;
|
||||
devices[0].pid = 0xBEEF;
|
||||
devices[0].pvn = 0xC0DE;
|
||||
devices[0].max_point_num = 16;
|
||||
|
||||
// remember provided callback and userdata
|
||||
touch_callback = (decltype(touch_callback)) touch_event_cb;
|
||||
user_data = userdata;
|
||||
|
||||
// success
|
||||
return 1;
|
||||
}
|
||||
|
||||
char DRS_TAPELED[38 * 49][3] {};
|
||||
bool VR_STARTED = false;
|
||||
linalg::aliases::float3 VR_SCALE(100, 100, 1.f);
|
||||
linalg::aliases::float3 VR_OFFSET(0.f, 0.f, -0.1f);
|
||||
float VR_ROTATION = 0.f;
|
||||
VRFoot VR_FOOTS[2] {
|
||||
{1},
|
||||
{2},
|
||||
};
|
||||
|
||||
inline DWORD scale_double_to_xy(double val) {
|
||||
return static_cast<DWORD>(val * 32768);
|
||||
}
|
||||
|
||||
inline DWORD scale_double_to_height(double val) {
|
||||
return static_cast<DWORD>(val * 1312);
|
||||
}
|
||||
|
||||
inline DWORD scale_double_to_width(double val) {
|
||||
return static_cast<DWORD>(val * 1696);
|
||||
}
|
||||
|
||||
void fire_touches(drs_touch_t *events, size_t event_count) {
|
||||
|
||||
// check callback first
|
||||
if (!touch_callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// generate touch data
|
||||
auto game_touches = std::make_unique<touch_data_t[]>(event_count);
|
||||
for (size_t i = 0; i < event_count; i++) {
|
||||
|
||||
// initialize touch value
|
||||
game_touches[i].cid = (DWORD) events[i].id;
|
||||
game_touches[i].unk8 = 0;
|
||||
|
||||
// copy scaled values
|
||||
game_touches[i].x = scale_double_to_xy(events[i].x);
|
||||
game_touches[i].y = scale_double_to_xy(events[i].y);
|
||||
game_touches[i].width = scale_double_to_width(events[i].width);
|
||||
game_touches[i].height = scale_double_to_height(events[i].height);
|
||||
|
||||
// decide touch type
|
||||
switch(events[i].type) {
|
||||
case DRS_DOWN:
|
||||
game_touches[i].type = TS_DOWN;
|
||||
break;
|
||||
case DRS_UP:
|
||||
game_touches[i].type = TS_UP;
|
||||
break;
|
||||
case DRS_MOVE:
|
||||
game_touches[i].type = TS_MOVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// build device information
|
||||
dev_info_t dev;
|
||||
dev.unk1 = 0;
|
||||
dev.unk2 = 0;
|
||||
dev.device_id = 0;
|
||||
dev.vid = 0xDEAD;
|
||||
dev.pid = 0xBEEF;
|
||||
dev.pvn = 0xC0DE;
|
||||
dev.max_point_num = 16;
|
||||
|
||||
// fire callback
|
||||
touch_callback(&dev, game_touches.get(), (int) event_count, 0, user_data);
|
||||
}
|
||||
|
||||
uint32_t VRFoot::get_index() {
|
||||
if (index == ~0u) {
|
||||
if (id == 1) return vrutil::INDEX_LEFT;
|
||||
if (id == 2) return vrutil::INDEX_RIGHT;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
linalg::aliases::float3 VRFoot::to_world(linalg::aliases::float3 pos) {
|
||||
pos = linalg::aliases::float3(-pos.z, pos.x, pos.y);
|
||||
const float deg_to_rad = (float) (1 / 180.f * M_PI);
|
||||
auto s = sinf(VR_ROTATION * deg_to_rad);
|
||||
auto c = cosf(VR_ROTATION * deg_to_rad);
|
||||
pos = linalg::aliases::float3(pos.x * c - pos.y * s,
|
||||
pos.x * s + pos.y * c,
|
||||
pos.z);
|
||||
return pos * VR_SCALE + VR_OFFSET;
|
||||
}
|
||||
|
||||
void start_vr() {
|
||||
if (vrutil::STATUS != vrutil::VRStatus::Running) return;
|
||||
if (!VR_STARTED) {
|
||||
VR_STARTED = true;
|
||||
std::thread t([] {
|
||||
log_info("drs", "starting VR thread");
|
||||
|
||||
// dance floor plane
|
||||
const linalg::aliases::float3 plane_normal(0, 0, 1);
|
||||
const linalg::aliases::float3 plane_point(0, 0, 0);
|
||||
const float touch_width = 1.f;
|
||||
const float touch_height = 1.f;
|
||||
|
||||
// main loop
|
||||
while (vrutil::STATUS == vrutil::VRStatus::Running) {
|
||||
|
||||
// iterate foots
|
||||
for (auto &foot : VR_FOOTS) {
|
||||
vr::TrackedDevicePose_t pose;
|
||||
vr::VRControllerState_t state;
|
||||
vrutil::get_con_pose(foot.get_index(), &pose, &state);
|
||||
|
||||
// only accept valid poses
|
||||
if (pose.bPoseIsValid) {
|
||||
auto length = std::max(foot.length, 0.001f);
|
||||
|
||||
// get components
|
||||
auto translation = foot.to_world(vrutil::get_translation(
|
||||
pose.mDeviceToAbsoluteTracking));
|
||||
auto direction = -linalg::qzdir(linalg::qmul(
|
||||
vrutil::get_rotation(pose.mDeviceToAbsoluteTracking.m),
|
||||
foot.rotation));
|
||||
direction = linalg::aliases::float3 {
|
||||
-direction.z, direction.x, direction.y
|
||||
};
|
||||
|
||||
// get intersection point
|
||||
auto intersection = vrutil::intersect_point(
|
||||
direction, translation,
|
||||
plane_normal, plane_point);
|
||||
auto distance = linalg::distance(
|
||||
translation, intersection);
|
||||
|
||||
// update event details
|
||||
foot.height = std::max(0.f, translation.z - intersection.z);
|
||||
foot.event.id = foot.id;
|
||||
foot.event.x = (intersection.x / 38.f) * touch_width;
|
||||
foot.event.y = (intersection.y / 49.f) * touch_height;
|
||||
if (translation.z > intersection.z) {
|
||||
foot.event.width = foot.size_base
|
||||
+ foot.size_scale * std::max(0.f, 1.f - distance / length);
|
||||
} else {
|
||||
foot.event.width = foot.size_base + foot.size_scale;
|
||||
}
|
||||
foot.event.height = foot.event.width;
|
||||
|
||||
// check if controller points down
|
||||
if (direction.z < 0) {
|
||||
|
||||
// check if plane in range
|
||||
if (distance <= length) {
|
||||
|
||||
// check previous event
|
||||
switch (foot.event.type) {
|
||||
case DRS_UP:
|
||||
|
||||
// generate down event
|
||||
foot.event.type = DRS_DOWN;
|
||||
break;
|
||||
|
||||
case DRS_DOWN:
|
||||
case DRS_MOVE:
|
||||
|
||||
// generate move event
|
||||
foot.event.type = DRS_MOVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// send event
|
||||
drs::fire_touches(&foot.event, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// foot not intersecting with plane
|
||||
switch (foot.event.type) {
|
||||
case DRS_DOWN:
|
||||
case DRS_MOVE:
|
||||
|
||||
// generate up event
|
||||
foot.event.type = DRS_UP;
|
||||
drs::fire_touches(&foot.event, 1);
|
||||
break;
|
||||
|
||||
case DRS_UP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// slow down
|
||||
vrutil::scan();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
VR_STARTED = false;
|
||||
return nullptr;
|
||||
});
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
|
||||
DRSGame::DRSGame() : Game("DANCERUSH") {
|
||||
}
|
||||
|
||||
void DRSGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// TouchSDK hooks
|
||||
detour::iat("??0TouchSDK@@QEAA@XZ",
|
||||
(void *) &TouchSDK_Constructor, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SendData@TouchSDK@@QEAA_NU_DeviceInfo@@QEAEH1HH@Z",
|
||||
(void *) &TouchSDK_SendData, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SetSignalInit@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_SetSignalInit, avs::game::DLL_INSTANCE);
|
||||
detour::iat("??1TouchSDK@@QEAA@XZ",
|
||||
(void *) &TouchSDK_Destructor, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetYLedTotal@TouchSDK@@QEAAHU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_GetYLedTotal, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetXLedTotal@TouchSDK@@QEAAHU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_GetXLedTotal, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableTouch@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableTouch, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableDrag@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableDrag, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableWheel@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableWheel, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?DisableRightClick@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_DisableRightClick, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SetMultiTouchMode@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_SetMultiTouchMode, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?EnableTouchWidthData@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_EnableTouchWidthData, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?EnableRawData@TouchSDK@@QEAA_NU_DeviceInfo@@H@Z",
|
||||
(void *) &TouchSDK_EnableRawData, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?SetAllEnable@TouchSDK@@QEAA_NU_DeviceInfo@@_NH@Z",
|
||||
(void *) &TouchSDK_SetAllEnable, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetTouchDeviceCount@TouchSDK@@QEAAHXZ",
|
||||
(void *) &TouchSDK_GetTouchDeviceCount, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?GetTouchSDKVersion@TouchSDK@@QEAAIXZ",
|
||||
(void *) &TouchSDK_GetTouchSDKVersion, avs::game::DLL_INSTANCE);
|
||||
detour::iat("?InitTouch@TouchSDK@@QEAAHPEAU_DeviceInfo@@HP6AXU2@PEBU_TouchPointData@@HHPEBX@ZP6AX1_N3@ZPEAX@Z",
|
||||
(void *) &TouchSDK_InitTouch, avs::game::DLL_INSTANCE);
|
||||
|
||||
// VR
|
||||
if (vrutil::STATUS == vrutil::VRStatus::Running) {
|
||||
start_vr();
|
||||
}
|
||||
}
|
||||
|
||||
void DRSGame::detach() {
|
||||
Game::detach();
|
||||
}
|
||||
}
|
||||
|
||||
+51
-51
@@ -1,51 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
#include "external/linalg.h"
|
||||
|
||||
namespace games::drs {
|
||||
|
||||
enum DRS_TOUCH_TYPE {
|
||||
DRS_DOWN = 0,
|
||||
DRS_UP = 1,
|
||||
DRS_MOVE = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int type = DRS_UP;
|
||||
int id = 0;
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
double width = 1;
|
||||
double height = 1;
|
||||
} drs_touch_t;
|
||||
|
||||
struct VRFoot {
|
||||
uint32_t id;
|
||||
uint32_t index = ~0u;
|
||||
float length = 3.1f;
|
||||
float size_base = 0.05f;
|
||||
float size_scale = 0.1f;
|
||||
float height = 3.f;
|
||||
linalg::aliases::float4 rotation {0, 0, 0, 1};
|
||||
drs_touch_t event {};
|
||||
uint32_t get_index();
|
||||
linalg::aliases::float3 to_world(linalg::aliases::float3 pos);
|
||||
};
|
||||
|
||||
extern char DRS_TAPELED[38 * 49][3];
|
||||
extern linalg::aliases::float3 VR_SCALE;
|
||||
extern linalg::aliases::float3 VR_OFFSET;
|
||||
extern float VR_ROTATION;
|
||||
extern VRFoot VR_FOOTS[2];
|
||||
|
||||
void fire_touches(drs_touch_t *events, size_t event_count);
|
||||
void start_vr();
|
||||
|
||||
class DRSGame : public games::Game {
|
||||
public:
|
||||
DRSGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
#include "external/linalg.h"
|
||||
|
||||
namespace games::drs {
|
||||
|
||||
enum DRS_TOUCH_TYPE {
|
||||
DRS_DOWN = 0,
|
||||
DRS_UP = 1,
|
||||
DRS_MOVE = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int type = DRS_UP;
|
||||
int id = 0;
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
double width = 1;
|
||||
double height = 1;
|
||||
} drs_touch_t;
|
||||
|
||||
struct VRFoot {
|
||||
uint32_t id;
|
||||
uint32_t index = ~0u;
|
||||
float length = 3.1f;
|
||||
float size_base = 0.05f;
|
||||
float size_scale = 0.1f;
|
||||
float height = 3.f;
|
||||
linalg::aliases::float4 rotation {0, 0, 0, 1};
|
||||
drs_touch_t event {};
|
||||
uint32_t get_index();
|
||||
linalg::aliases::float3 to_world(linalg::aliases::float3 pos);
|
||||
};
|
||||
|
||||
extern char DRS_TAPELED[38 * 49][3];
|
||||
extern linalg::aliases::float3 VR_SCALE;
|
||||
extern linalg::aliases::float3 VR_OFFSET;
|
||||
extern float VR_ROTATION;
|
||||
extern VRFoot VR_FOOTS[2];
|
||||
|
||||
void fire_touches(drs_touch_t *events, size_t event_count);
|
||||
void start_vr();
|
||||
|
||||
class DRSGame : public games::Game {
|
||||
public:
|
||||
DRSGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+41
-41
@@ -1,41 +1,41 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::drs::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("DANCERUSH");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"P1 Start",
|
||||
"P1 Up",
|
||||
"P1 Down",
|
||||
"P1 Left",
|
||||
"P1 Right",
|
||||
"P2 Start",
|
||||
"P2 Up",
|
||||
"P2 Down",
|
||||
"P2 Left",
|
||||
"P2 Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::drs::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
//if (lights.empty()) {
|
||||
//lights = GameAPI::Lights::getLights("DANCERUSH");
|
||||
//GameAPI::Lights::sortLights(
|
||||
// &lights,
|
||||
//);
|
||||
//}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::drs::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("DANCERUSH");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"P1 Start",
|
||||
"P1 Up",
|
||||
"P1 Down",
|
||||
"P1 Left",
|
||||
"P1 Right",
|
||||
"P2 Start",
|
||||
"P2 Up",
|
||||
"P2 Down",
|
||||
"P2 Left",
|
||||
"P2 Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::drs::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
//if (lights.empty()) {
|
||||
//lights = GameAPI::Lights::getLights("DANCERUSH");
|
||||
//GameAPI::Lights::sortLights(
|
||||
// &lights,
|
||||
//);
|
||||
//}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+36
-36
@@ -1,36 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::drs {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
P1_Start,
|
||||
P1_Up,
|
||||
P1_Down,
|
||||
P1_Left,
|
||||
P1_Right,
|
||||
P2_Start,
|
||||
P2_Up,
|
||||
P2_Down,
|
||||
P2_Left,
|
||||
P2_Right
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::drs {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
P1_Start,
|
||||
P1_Up,
|
||||
P1_Down,
|
||||
P1_Left,
|
||||
P1_Right,
|
||||
P2_Start,
|
||||
P2_Up,
|
||||
P2_Down,
|
||||
P2_Left,
|
||||
P2_Right
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+152
-152
@@ -1,152 +1,152 @@
|
||||
#include "ftt.h"
|
||||
#include "nui.h"
|
||||
|
||||
#include "launcher/launcher.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sigscan.h"
|
||||
#include "util/memutils.h"
|
||||
|
||||
typedef HRESULT (WINAPI *NuiGetSensorCount_t)(int *pCount);
|
||||
typedef HRESULT (WINAPI *NuiCreateSensorByIndex_t)(int index, INuiSensor **ppNuiSensor);
|
||||
|
||||
static NuiGetSensorCount_t NuiGetSensorCount_orig = nullptr;
|
||||
static NuiCreateSensorByIndex_t NuiCreateSensorByIndex_orig = nullptr;
|
||||
|
||||
static VTBL_TYPE(INuiSensor, NuiInitialize) INuiSensor_NuiInitialize_orig = nullptr;
|
||||
static VTBL_TYPE(INuiSensor, NuiImageStreamOpen) INuiSensor_NuiImageStreamOpen_orig = nullptr;
|
||||
|
||||
static HRESULT __stdcall INuiSensor_NuiInitialize_hook(INuiSensor *This, DWORD dwFlags) {
|
||||
log_misc("ftt", "INuiSensor::NuiInitialize hook hit (dwFlags: {})", dwFlags);
|
||||
|
||||
// call original function
|
||||
HRESULT ret = INuiSensor_NuiInitialize_orig(This, dwFlags);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "INuiSensor::NuiInitialize failed, hr={}", FMT_HRESULT(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT __stdcall INuiSensor_NuiImageStreamOpen_hook(
|
||||
INuiSensor *This,
|
||||
NUI_IMAGE_TYPE eImageType,
|
||||
NUI_IMAGE_RESOLUTION eResolution,
|
||||
DWORD dwImageFrameFlags,
|
||||
DWORD dwFrameLimit,
|
||||
HANDLE hNextFrameEvent,
|
||||
HANDLE *phStreamHandle) {
|
||||
log_misc("ftt", "INuiSensor::NuiImageStreamOpen hook hit");
|
||||
|
||||
// fix unsupported flag
|
||||
if (eImageType == NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX) {
|
||||
dwImageFrameFlags = 0;
|
||||
}
|
||||
|
||||
// call original function
|
||||
HRESULT ret = INuiSensor_NuiImageStreamOpen_orig(This, eImageType, eResolution, dwImageFrameFlags, dwFrameLimit, hNextFrameEvent, phStreamHandle);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "INuiSensor::NuiImageStreamOpen failed, hr={}", FMT_HRESULT(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI NuiGetSensorCount_hook(int *pCount) {
|
||||
log_misc("ftt", "NuiGetSensorCount hook hit");
|
||||
|
||||
// call original function
|
||||
HRESULT ret = NuiGetSensorCount_orig(pCount);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "NuiGetSensorCount failed, hr={}", FMT_HRESULT(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pCount == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
log_info("ftt", "found {} Kinect sensors", *pCount);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI NuiCreateSensorByIndex_hook(int index, INuiSensor **ppNuiSensor) {
|
||||
log_misc("ftt", "NuiCreateSensorByIndex hook hit");
|
||||
|
||||
// call original function
|
||||
HRESULT ret = NuiCreateSensorByIndex_orig(index, ppNuiSensor);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "NuiCreateSensorByIndex failed, hr={}", FMT_HRESULT(ret));
|
||||
return ret;
|
||||
}
|
||||
if (ppNuiSensor == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// save original functions
|
||||
INuiSensor *pNuiSensor = *ppNuiSensor;
|
||||
if (INuiSensor_NuiInitialize_orig == nullptr) {
|
||||
INuiSensor_NuiInitialize_orig = pNuiSensor->lpVtbl->NuiInitialize;
|
||||
}
|
||||
if (INuiSensor_NuiImageStreamOpen_orig == nullptr) {
|
||||
INuiSensor_NuiImageStreamOpen_orig = pNuiSensor->lpVtbl->NuiImageStreamOpen;
|
||||
}
|
||||
|
||||
// unlock interface
|
||||
memutils::VProtectGuard pNuiSensor_guard(pNuiSensor->lpVtbl);
|
||||
|
||||
// hook interface
|
||||
pNuiSensor->lpVtbl->NuiInitialize = INuiSensor_NuiInitialize_hook;
|
||||
pNuiSensor->lpVtbl->NuiImageStreamOpen = INuiSensor_NuiImageStreamOpen_hook;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace games::ftt {
|
||||
|
||||
FTTGame::FTTGame() : Game("FutureTomTom") {
|
||||
}
|
||||
|
||||
void FTTGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// load main game module so patches work
|
||||
auto game_dll = libutils::load_library(MODULE_PATH / "gamemmd.dll");
|
||||
|
||||
// patch kinect to always poll
|
||||
if (!replace_pattern(game_dll,
|
||||
"78??837B340775??488BCBE8",
|
||||
"????????????9090????????",
|
||||
0,
|
||||
0))
|
||||
{
|
||||
log_warning("ftt", "kinect polling patch failed");
|
||||
}
|
||||
|
||||
// patch kinect to not time out
|
||||
if (!replace_pattern(game_dll,
|
||||
"3D3075000072??C74334060000004883C420",
|
||||
"??????????????90909090909090????????",
|
||||
0,
|
||||
0))
|
||||
{
|
||||
log_warning("ftt", "kinect timeout patch failed");
|
||||
}
|
||||
|
||||
// hook Kinect calls
|
||||
NuiGetSensorCount_orig = (NuiGetSensorCount_t) detour::iat_ordinal(
|
||||
"Kinect10.dll", 5, (void *) NuiGetSensorCount_hook, game_dll);
|
||||
NuiCreateSensorByIndex_orig = (NuiCreateSensorByIndex_t) detour::iat_ordinal(
|
||||
"Kinect10.dll", 6, (void *) NuiCreateSensorByIndex_hook, game_dll);
|
||||
}
|
||||
}
|
||||
#include "ftt.h"
|
||||
#include "nui.h"
|
||||
|
||||
#include "launcher/launcher.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sigscan.h"
|
||||
#include "util/memutils.h"
|
||||
|
||||
typedef HRESULT (WINAPI *NuiGetSensorCount_t)(int *pCount);
|
||||
typedef HRESULT (WINAPI *NuiCreateSensorByIndex_t)(int index, INuiSensor **ppNuiSensor);
|
||||
|
||||
static NuiGetSensorCount_t NuiGetSensorCount_orig = nullptr;
|
||||
static NuiCreateSensorByIndex_t NuiCreateSensorByIndex_orig = nullptr;
|
||||
|
||||
static VTBL_TYPE(INuiSensor, NuiInitialize) INuiSensor_NuiInitialize_orig = nullptr;
|
||||
static VTBL_TYPE(INuiSensor, NuiImageStreamOpen) INuiSensor_NuiImageStreamOpen_orig = nullptr;
|
||||
|
||||
static HRESULT __stdcall INuiSensor_NuiInitialize_hook(INuiSensor *This, DWORD dwFlags) {
|
||||
log_misc("ftt", "INuiSensor::NuiInitialize hook hit (dwFlags: {})", dwFlags);
|
||||
|
||||
// call original function
|
||||
HRESULT ret = INuiSensor_NuiInitialize_orig(This, dwFlags);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "INuiSensor::NuiInitialize failed, hr={}", FMT_HRESULT(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT __stdcall INuiSensor_NuiImageStreamOpen_hook(
|
||||
INuiSensor *This,
|
||||
NUI_IMAGE_TYPE eImageType,
|
||||
NUI_IMAGE_RESOLUTION eResolution,
|
||||
DWORD dwImageFrameFlags,
|
||||
DWORD dwFrameLimit,
|
||||
HANDLE hNextFrameEvent,
|
||||
HANDLE *phStreamHandle) {
|
||||
log_misc("ftt", "INuiSensor::NuiImageStreamOpen hook hit");
|
||||
|
||||
// fix unsupported flag
|
||||
if (eImageType == NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX) {
|
||||
dwImageFrameFlags = 0;
|
||||
}
|
||||
|
||||
// call original function
|
||||
HRESULT ret = INuiSensor_NuiImageStreamOpen_orig(This, eImageType, eResolution, dwImageFrameFlags, dwFrameLimit, hNextFrameEvent, phStreamHandle);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "INuiSensor::NuiImageStreamOpen failed, hr={}", FMT_HRESULT(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI NuiGetSensorCount_hook(int *pCount) {
|
||||
log_misc("ftt", "NuiGetSensorCount hook hit");
|
||||
|
||||
// call original function
|
||||
HRESULT ret = NuiGetSensorCount_orig(pCount);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "NuiGetSensorCount failed, hr={}", FMT_HRESULT(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pCount == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
log_info("ftt", "found {} Kinect sensors", *pCount);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI NuiCreateSensorByIndex_hook(int index, INuiSensor **ppNuiSensor) {
|
||||
log_misc("ftt", "NuiCreateSensorByIndex hook hit");
|
||||
|
||||
// call original function
|
||||
HRESULT ret = NuiCreateSensorByIndex_orig(index, ppNuiSensor);
|
||||
|
||||
// check return value
|
||||
if (FAILED(ret)) {
|
||||
log_warning("ftt", "NuiCreateSensorByIndex failed, hr={}", FMT_HRESULT(ret));
|
||||
return ret;
|
||||
}
|
||||
if (ppNuiSensor == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// save original functions
|
||||
INuiSensor *pNuiSensor = *ppNuiSensor;
|
||||
if (INuiSensor_NuiInitialize_orig == nullptr) {
|
||||
INuiSensor_NuiInitialize_orig = pNuiSensor->lpVtbl->NuiInitialize;
|
||||
}
|
||||
if (INuiSensor_NuiImageStreamOpen_orig == nullptr) {
|
||||
INuiSensor_NuiImageStreamOpen_orig = pNuiSensor->lpVtbl->NuiImageStreamOpen;
|
||||
}
|
||||
|
||||
// unlock interface
|
||||
memutils::VProtectGuard pNuiSensor_guard(pNuiSensor->lpVtbl);
|
||||
|
||||
// hook interface
|
||||
pNuiSensor->lpVtbl->NuiInitialize = INuiSensor_NuiInitialize_hook;
|
||||
pNuiSensor->lpVtbl->NuiImageStreamOpen = INuiSensor_NuiImageStreamOpen_hook;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace games::ftt {
|
||||
|
||||
FTTGame::FTTGame() : Game("FutureTomTom") {
|
||||
}
|
||||
|
||||
void FTTGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// load main game module so patches work
|
||||
auto game_dll = libutils::load_library(MODULE_PATH / "gamemmd.dll");
|
||||
|
||||
// patch kinect to always poll
|
||||
if (!replace_pattern(game_dll,
|
||||
"78??837B340775??488BCBE8",
|
||||
"????????????9090????????",
|
||||
0,
|
||||
0))
|
||||
{
|
||||
log_warning("ftt", "kinect polling patch failed");
|
||||
}
|
||||
|
||||
// patch kinect to not time out
|
||||
if (!replace_pattern(game_dll,
|
||||
"3D3075000072??C74334060000004883C420",
|
||||
"??????????????90909090909090????????",
|
||||
0,
|
||||
0))
|
||||
{
|
||||
log_warning("ftt", "kinect timeout patch failed");
|
||||
}
|
||||
|
||||
// hook Kinect calls
|
||||
NuiGetSensorCount_orig = (NuiGetSensorCount_t) detour::iat_ordinal(
|
||||
"Kinect10.dll", 5, (void *) NuiGetSensorCount_hook, game_dll);
|
||||
NuiCreateSensorByIndex_orig = (NuiCreateSensorByIndex_t) detour::iat_ordinal(
|
||||
"Kinect10.dll", 6, (void *) NuiCreateSensorByIndex_hook, game_dll);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::ftt {
|
||||
|
||||
class FTTGame : public games::Game {
|
||||
public:
|
||||
FTTGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::ftt {
|
||||
|
||||
class FTTGame : public games::Game {
|
||||
public:
|
||||
FTTGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+65
-65
@@ -1,65 +1,65 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::ftt::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("FutureTomTom");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Pad 1",
|
||||
"Pad 2",
|
||||
"Pad 3",
|
||||
"Pad 4"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::ftt::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("FutureTomTom");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Pad 1",
|
||||
"Pad 2",
|
||||
"Pad 3",
|
||||
"Pad 4"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::ftt::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("FutureTomTom");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Pad 1 Red",
|
||||
"Pad 1 Green",
|
||||
"Pad 1 Blue",
|
||||
"Pad 2 Red",
|
||||
"Pad 2 Green",
|
||||
"Pad 2 Blue",
|
||||
"Pad 3 Red",
|
||||
"Pad 3 Green",
|
||||
"Pad 3 Blue",
|
||||
"Pad 4 Red",
|
||||
"Pad 4 Green",
|
||||
"Pad 4 Blue"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::ftt::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("FutureTomTom");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Pad 1",
|
||||
"Pad 2",
|
||||
"Pad 3",
|
||||
"Pad 4"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::ftt::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("FutureTomTom");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Pad 1",
|
||||
"Pad 2",
|
||||
"Pad 3",
|
||||
"Pad 4"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::ftt::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("FutureTomTom");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Pad 1 Red",
|
||||
"Pad 1 Green",
|
||||
"Pad 1 Blue",
|
||||
"Pad 2 Red",
|
||||
"Pad 2 Green",
|
||||
"Pad 2 Blue",
|
||||
"Pad 3 Red",
|
||||
"Pad 3 Green",
|
||||
"Pad 3 Blue",
|
||||
"Pad 4 Red",
|
||||
"Pad 4 Green",
|
||||
"Pad 4 Blue"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::ftt {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Pad1,
|
||||
Pad2,
|
||||
Pad3,
|
||||
Pad4,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
Pad1,
|
||||
Pad2,
|
||||
Pad3,
|
||||
Pad4,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Pad1_R,
|
||||
Pad1_G,
|
||||
Pad1_B,
|
||||
Pad2_R,
|
||||
Pad2_G,
|
||||
Pad2_B,
|
||||
Pad3_R,
|
||||
Pad3_G,
|
||||
Pad3_B,
|
||||
Pad4_R,
|
||||
Pad4_G,
|
||||
Pad4_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::ftt {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Pad1,
|
||||
Pad2,
|
||||
Pad3,
|
||||
Pad4,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
Pad1,
|
||||
Pad2,
|
||||
Pad3,
|
||||
Pad4,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Pad1_R,
|
||||
Pad1_G,
|
||||
Pad1_B,
|
||||
Pad2_R,
|
||||
Pad2_G,
|
||||
Pad2_B,
|
||||
Pad3_R,
|
||||
Pad3_G,
|
||||
Pad3_B,
|
||||
Pad4_R,
|
||||
Pad4_G,
|
||||
Pad4_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+183
-183
@@ -1,183 +1,183 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <unknwn.h>
|
||||
|
||||
enum NUI_IMAGE_TYPE {
|
||||
NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX = 0x0,
|
||||
NUI_IMAGE_TYPE_COLOR = 0x1,
|
||||
NUI_IMAGE_TYPE_COLOR_YUV = 0x2,
|
||||
NUI_IMAGE_TYPE_COLOR_RAW_YUV = 0x3,
|
||||
NUI_IMAGE_TYPE_DEPTH = 0x4,
|
||||
NUI_IMAGE_TYPE_COLOR_INFRARED = 0x5,
|
||||
NUI_IMAGE_TYPE_COLOR_RAW_BAYER = 0x6,
|
||||
};
|
||||
|
||||
enum NUI_IMAGE_RESOLUTION {
|
||||
NUI_IMAGE_RESOLUTION_80x60 = 0x0,
|
||||
NUI_IMAGE_RESOLUTION_320x240 = 0x1,
|
||||
NUI_IMAGE_RESOLUTION_640x480 = 0x2,
|
||||
NUI_IMAGE_RESOLUTION_1280x960 = 0x3,
|
||||
NUI_IMAGE_RESOLUTION_INVALID = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
#pragma pack(push, 8)
|
||||
struct INuiSensor {
|
||||
struct INuiSensorVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
struct INuiSensorVtbl {
|
||||
HRESULT (__stdcall *QueryInterface)(IUnknown *This, const IID *const riid, void **ppvObject);
|
||||
ULONG (__stdcall *AddRef)(IUnknown *This);
|
||||
ULONG (__stdcall *Release)(IUnknown *This);
|
||||
|
||||
HRESULT (__stdcall *NuiInitialize)(
|
||||
INuiSensor *This,
|
||||
DWORD dwFlags);
|
||||
|
||||
void (__stdcall *NuiShutdown)(INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiSetFrameEndEvent)(
|
||||
INuiSensor *This,
|
||||
HANDLE hEvent,
|
||||
DWORD dwFrameEventFlag);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamOpen)(
|
||||
INuiSensor *This,
|
||||
NUI_IMAGE_TYPE eImageType,
|
||||
NUI_IMAGE_RESOLUTION eResolution,
|
||||
DWORD dwImageFrameFlags,
|
||||
DWORD dwFrameLimit,
|
||||
HANDLE hNextFrameEvent,
|
||||
HANDLE *phStreamHandle);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamSetImageFrameFlags)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
DWORD dwImageFrameFlags);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamGetImageFrameFlags)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
DWORD *pdwImageFrameFlags);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamGetNextFrame)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
DWORD dwMillisecondsToWait,
|
||||
void *pImageFrame);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamReleaseFrame)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
void *pImageFrame);
|
||||
|
||||
HRESULT (__stdcall *NuiImageGetColorPixelCoordinatesFromDepthPixel)(
|
||||
INuiSensor *This,
|
||||
DWORD eColorResolution,
|
||||
const void *pcViewArea,
|
||||
LONG lDepthX,
|
||||
LONG lDepthY,
|
||||
USHORT usDepthValue,
|
||||
LONG *plColorX,
|
||||
LONG *plColorY);
|
||||
|
||||
HRESULT (__stdcall *NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution)(
|
||||
INuiSensor *This,
|
||||
DWORD eColorResolution,
|
||||
DWORD eDepthResolution,
|
||||
const void *pcViewArea,
|
||||
LONG lDepthX,
|
||||
LONG lDepthY,
|
||||
USHORT usDepthValue,
|
||||
LONG *plColorX,
|
||||
LONG *plColorY);
|
||||
|
||||
HRESULT (__stdcall *NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution)(
|
||||
INuiSensor *This,
|
||||
DWORD eColorResolution,
|
||||
DWORD eDepthResolution,
|
||||
DWORD cDepthValues,
|
||||
USHORT *pDepthValues,
|
||||
DWORD cColorCoordinates,
|
||||
LONG *pColorCoordinates);
|
||||
|
||||
HRESULT (__stdcall *NuiCameraElevationSetAngle)(
|
||||
INuiSensor *This,
|
||||
LONG lAngleDegrees);
|
||||
|
||||
HRESULT (__stdcall *NuiCameraElevationGetAngle)(
|
||||
INuiSensor *This,
|
||||
LONG *plAngleDegrees);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonTrackingEnable)(
|
||||
INuiSensor *This,
|
||||
HANDLE hNextFrameEvent,
|
||||
DWORD dwFlags);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonTrackingDisable)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonSetTrackedSkeletons)(
|
||||
INuiSensor *This,
|
||||
DWORD *TrackingIDs);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonGetNextFrame)(
|
||||
INuiSensor *This,
|
||||
DWORD dwMillisecondsToWait,
|
||||
void *pSkeletonFrame);
|
||||
|
||||
HRESULT (__stdcall *NuiTransformSmooth)(
|
||||
INuiSensor *This,
|
||||
void *pSkeletonFrame,
|
||||
const void *pSmoothingParams);
|
||||
|
||||
HRESULT (__stdcall *NuiGetAudioSource)(
|
||||
INuiSensor *This,
|
||||
void **ppDmo);
|
||||
|
||||
int (__stdcall *NuiInstanceIndex)(
|
||||
INuiSensor *This);
|
||||
|
||||
BSTR (__stdcall *NuiDeviceConnectionId)(
|
||||
INuiSensor *This);
|
||||
|
||||
BSTR (__stdcall *NuiUniqueId)(
|
||||
INuiSensor *This);
|
||||
|
||||
BSTR (__stdcall *NuiAudioArrayId)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiStatus)(
|
||||
INuiSensor *This);
|
||||
|
||||
DWORD (__stdcall *NuiInitializationFlags)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiGetCoordinateMapper)(
|
||||
INuiSensor *This,
|
||||
void **pMapping);
|
||||
|
||||
HRESULT (__stdcall *NuiImageFrameGetDepthImagePixelFrameTexture)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
void *pImageFrame,
|
||||
BOOL *pNearMode,
|
||||
void **ppFrameTexture);
|
||||
|
||||
HRESULT (__stdcall *NuiGetColorCameraSettings)(
|
||||
INuiSensor *This,
|
||||
void **pCameraSettings);
|
||||
|
||||
BOOL (__stdcall *NuiGetForceInfraredEmitterOff)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiSetForceInfraredEmitterOff)(
|
||||
INuiSensor *This,
|
||||
BOOL fForceInfraredEmitterOff);
|
||||
|
||||
HRESULT (__stdcall *NuiAccelerometerGetCurrentReading)(
|
||||
INuiSensor *This,
|
||||
void *pReading);
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <unknwn.h>
|
||||
|
||||
enum NUI_IMAGE_TYPE {
|
||||
NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX = 0x0,
|
||||
NUI_IMAGE_TYPE_COLOR = 0x1,
|
||||
NUI_IMAGE_TYPE_COLOR_YUV = 0x2,
|
||||
NUI_IMAGE_TYPE_COLOR_RAW_YUV = 0x3,
|
||||
NUI_IMAGE_TYPE_DEPTH = 0x4,
|
||||
NUI_IMAGE_TYPE_COLOR_INFRARED = 0x5,
|
||||
NUI_IMAGE_TYPE_COLOR_RAW_BAYER = 0x6,
|
||||
};
|
||||
|
||||
enum NUI_IMAGE_RESOLUTION {
|
||||
NUI_IMAGE_RESOLUTION_80x60 = 0x0,
|
||||
NUI_IMAGE_RESOLUTION_320x240 = 0x1,
|
||||
NUI_IMAGE_RESOLUTION_640x480 = 0x2,
|
||||
NUI_IMAGE_RESOLUTION_1280x960 = 0x3,
|
||||
NUI_IMAGE_RESOLUTION_INVALID = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
#pragma pack(push, 8)
|
||||
struct INuiSensor {
|
||||
struct INuiSensorVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
struct INuiSensorVtbl {
|
||||
HRESULT (__stdcall *QueryInterface)(IUnknown *This, const IID *const riid, void **ppvObject);
|
||||
ULONG (__stdcall *AddRef)(IUnknown *This);
|
||||
ULONG (__stdcall *Release)(IUnknown *This);
|
||||
|
||||
HRESULT (__stdcall *NuiInitialize)(
|
||||
INuiSensor *This,
|
||||
DWORD dwFlags);
|
||||
|
||||
void (__stdcall *NuiShutdown)(INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiSetFrameEndEvent)(
|
||||
INuiSensor *This,
|
||||
HANDLE hEvent,
|
||||
DWORD dwFrameEventFlag);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamOpen)(
|
||||
INuiSensor *This,
|
||||
NUI_IMAGE_TYPE eImageType,
|
||||
NUI_IMAGE_RESOLUTION eResolution,
|
||||
DWORD dwImageFrameFlags,
|
||||
DWORD dwFrameLimit,
|
||||
HANDLE hNextFrameEvent,
|
||||
HANDLE *phStreamHandle);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamSetImageFrameFlags)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
DWORD dwImageFrameFlags);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamGetImageFrameFlags)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
DWORD *pdwImageFrameFlags);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamGetNextFrame)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
DWORD dwMillisecondsToWait,
|
||||
void *pImageFrame);
|
||||
|
||||
HRESULT (__stdcall *NuiImageStreamReleaseFrame)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
void *pImageFrame);
|
||||
|
||||
HRESULT (__stdcall *NuiImageGetColorPixelCoordinatesFromDepthPixel)(
|
||||
INuiSensor *This,
|
||||
DWORD eColorResolution,
|
||||
const void *pcViewArea,
|
||||
LONG lDepthX,
|
||||
LONG lDepthY,
|
||||
USHORT usDepthValue,
|
||||
LONG *plColorX,
|
||||
LONG *plColorY);
|
||||
|
||||
HRESULT (__stdcall *NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution)(
|
||||
INuiSensor *This,
|
||||
DWORD eColorResolution,
|
||||
DWORD eDepthResolution,
|
||||
const void *pcViewArea,
|
||||
LONG lDepthX,
|
||||
LONG lDepthY,
|
||||
USHORT usDepthValue,
|
||||
LONG *plColorX,
|
||||
LONG *plColorY);
|
||||
|
||||
HRESULT (__stdcall *NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution)(
|
||||
INuiSensor *This,
|
||||
DWORD eColorResolution,
|
||||
DWORD eDepthResolution,
|
||||
DWORD cDepthValues,
|
||||
USHORT *pDepthValues,
|
||||
DWORD cColorCoordinates,
|
||||
LONG *pColorCoordinates);
|
||||
|
||||
HRESULT (__stdcall *NuiCameraElevationSetAngle)(
|
||||
INuiSensor *This,
|
||||
LONG lAngleDegrees);
|
||||
|
||||
HRESULT (__stdcall *NuiCameraElevationGetAngle)(
|
||||
INuiSensor *This,
|
||||
LONG *plAngleDegrees);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonTrackingEnable)(
|
||||
INuiSensor *This,
|
||||
HANDLE hNextFrameEvent,
|
||||
DWORD dwFlags);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonTrackingDisable)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonSetTrackedSkeletons)(
|
||||
INuiSensor *This,
|
||||
DWORD *TrackingIDs);
|
||||
|
||||
HRESULT (__stdcall *NuiSkeletonGetNextFrame)(
|
||||
INuiSensor *This,
|
||||
DWORD dwMillisecondsToWait,
|
||||
void *pSkeletonFrame);
|
||||
|
||||
HRESULT (__stdcall *NuiTransformSmooth)(
|
||||
INuiSensor *This,
|
||||
void *pSkeletonFrame,
|
||||
const void *pSmoothingParams);
|
||||
|
||||
HRESULT (__stdcall *NuiGetAudioSource)(
|
||||
INuiSensor *This,
|
||||
void **ppDmo);
|
||||
|
||||
int (__stdcall *NuiInstanceIndex)(
|
||||
INuiSensor *This);
|
||||
|
||||
BSTR (__stdcall *NuiDeviceConnectionId)(
|
||||
INuiSensor *This);
|
||||
|
||||
BSTR (__stdcall *NuiUniqueId)(
|
||||
INuiSensor *This);
|
||||
|
||||
BSTR (__stdcall *NuiAudioArrayId)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiStatus)(
|
||||
INuiSensor *This);
|
||||
|
||||
DWORD (__stdcall *NuiInitializationFlags)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiGetCoordinateMapper)(
|
||||
INuiSensor *This,
|
||||
void **pMapping);
|
||||
|
||||
HRESULT (__stdcall *NuiImageFrameGetDepthImagePixelFrameTexture)(
|
||||
INuiSensor *This,
|
||||
HANDLE hStream,
|
||||
void *pImageFrame,
|
||||
BOOL *pNearMode,
|
||||
void **ppFrameTexture);
|
||||
|
||||
HRESULT (__stdcall *NuiGetColorCameraSettings)(
|
||||
INuiSensor *This,
|
||||
void **pCameraSettings);
|
||||
|
||||
BOOL (__stdcall *NuiGetForceInfraredEmitterOff)(
|
||||
INuiSensor *This);
|
||||
|
||||
HRESULT (__stdcall *NuiSetForceInfraredEmitterOff)(
|
||||
INuiSensor *This,
|
||||
BOOL fForceInfraredEmitterOff);
|
||||
|
||||
HRESULT (__stdcall *NuiAccelerometerGetCurrentReading)(
|
||||
INuiSensor *This,
|
||||
void *pReading);
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
+22
-22
@@ -1,22 +1,22 @@
|
||||
#include "game.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
games::Game::Game(std::string name) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
void games::Game::attach() {
|
||||
log_info("game", "attach: {}", name);
|
||||
}
|
||||
|
||||
void games::Game::pre_attach() {
|
||||
log_info("game", "pre_attach: {}", name);
|
||||
}
|
||||
|
||||
void games::Game::post_attach() {
|
||||
log_info("game", "post_attach: {}", name);
|
||||
}
|
||||
|
||||
void games::Game::detach() {
|
||||
log_info("game", "detach: {}", name);
|
||||
}
|
||||
#include "game.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
games::Game::Game(std::string name) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
void games::Game::attach() {
|
||||
log_info("game", "attach: {}", name);
|
||||
}
|
||||
|
||||
void games::Game::pre_attach() {
|
||||
log_info("game", "pre_attach: {}", name);
|
||||
}
|
||||
|
||||
void games::Game::post_attach() {
|
||||
log_info("game", "post_attach: {}", name);
|
||||
}
|
||||
|
||||
void games::Game::detach() {
|
||||
log_info("game", "detach: {}", name);
|
||||
}
|
||||
|
||||
+24
-24
@@ -1,24 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace games {
|
||||
|
||||
class Game {
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
|
||||
Game(std::string name);
|
||||
virtual ~Game() = default;
|
||||
|
||||
// where the main magic will happen
|
||||
virtual void attach();
|
||||
|
||||
// optional
|
||||
virtual void pre_attach();
|
||||
virtual void post_attach();
|
||||
virtual void detach();
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace games {
|
||||
|
||||
class Game {
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
|
||||
Game(std::string name);
|
||||
virtual ~Game() = default;
|
||||
|
||||
// where the main magic will happen
|
||||
virtual void attach();
|
||||
|
||||
// optional
|
||||
virtual void pre_attach();
|
||||
virtual void post_attach();
|
||||
virtual void detach();
|
||||
};
|
||||
}
|
||||
|
||||
+206
-206
@@ -1,206 +1,206 @@
|
||||
#include "gitadora.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sigscan.h"
|
||||
|
||||
namespace games::gitadora {
|
||||
|
||||
// settings
|
||||
bool TWOCHANNEL = false;
|
||||
std::optional<unsigned int> CAB_TYPE = std::nullopt;
|
||||
|
||||
/*
|
||||
* GitaDora checks if the IP address has changed, and if it has it throws 5-1506-0000 like jubeat.
|
||||
* We don't want this so we patch it out.
|
||||
*/
|
||||
static char __cdecl eam_network_detected_ip_change() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GitaDora checks if the server it connects to is in the 192.168.0.0/16 or 169.254.0.0/16 subnet.
|
||||
* If it is, it downright refuses to use it and errors with no visible indication.
|
||||
* We don't want this so we patch it out.
|
||||
*/
|
||||
static char __cdecl eam_network_settings_conflict() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent GitaDora from changing the volume setting.
|
||||
*/
|
||||
static long __cdecl bmsd2_set_windows_volume(int volume) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two Channel Audio Mode
|
||||
* We proxy bmsd2_boot_hook and modify the last parameter which is apparently the channel count.
|
||||
* Since this apparently isn't the only thing required we need a signature scan to modify a value as well.
|
||||
*/
|
||||
typedef int (__cdecl *bmsd2_boot_t)(long a1, int a2, long a3, char channel_count);
|
||||
static bmsd2_boot_t bmsd2_boot_orig = nullptr;
|
||||
static int __cdecl bmsd2_boot_hook(long a1, int a2, long a3, char channel_count) {
|
||||
return bmsd2_boot_orig(a1, a2, a3, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Command Line Arguments
|
||||
* We hook this to override specific values.
|
||||
* This currently disables the ability to specify your own in the app-config.xml (param/cmdline __type="str")
|
||||
*/
|
||||
static bool __cdecl sys_code_get_cmdline(const char *cmdline) {
|
||||
if (strcmp(cmdline, "-d") == 0) {
|
||||
return true;
|
||||
} else if (strcmp(cmdline, "-DM") == 0) {
|
||||
return true;
|
||||
} else if (strcmp(cmdline, "-WINDOW") == 0) {
|
||||
return GRAPHICS_WINDOWED;
|
||||
} else if (strcmp(cmdline, "-LOGOUT") == 0) {
|
||||
return false;
|
||||
} else if (strcmp(cmdline, "-AOU") == 0) {
|
||||
return false;
|
||||
} else if (strcmp(cmdline, "-QCMODE") == 0) {
|
||||
return false;
|
||||
} else if (strcmp(cmdline, "-FACTORY") == 0) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* System Setting Parameter Overrides
|
||||
*/
|
||||
static std::unordered_map<std::string, long> SYS_SETTINGS;
|
||||
static std::unordered_map<std::string, long> SYS_DEBUG_DIPS;
|
||||
|
||||
static long __cdecl sys_setting_get_param(const char *param) {
|
||||
|
||||
// overrides
|
||||
if (strcmp(param, "PRODUCTION_MODE") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "ENABLE_DISP_ID") == 0) {
|
||||
return 0;
|
||||
} else if (CAB_TYPE.has_value() && strcmp(param, "VER_MACHINE") == 0) {
|
||||
return CAB_TYPE.value() << 12;
|
||||
}
|
||||
|
||||
// map lookup
|
||||
auto it = SYS_SETTINGS.find(param);
|
||||
if (it != SYS_SETTINGS.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long __cdecl sys_setting_set_param(const char *param, long value) {
|
||||
SYS_SETTINGS[std::string(param)] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long __cdecl sys_debug_dip_get_param(const char *param) {
|
||||
|
||||
// overrides
|
||||
if (strcmp(param, "sysinfo") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "jobbar1") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "jobbar2") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "serial") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "warnvpf") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "scrshot") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "eamxml") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "offset") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "autodbg") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "develop") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "effect_test") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "voice_type2") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// map lookup
|
||||
auto it = SYS_DEBUG_DIPS.find(param);
|
||||
if (it != SYS_DEBUG_DIPS.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long __cdecl sys_debug_dip_set_param(const char *param, long value) {
|
||||
SYS_DEBUG_DIPS[std::string(param)] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
GitaDoraGame::GitaDoraGame() : Game("GitaDora") {
|
||||
}
|
||||
|
||||
void GitaDoraGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// modules
|
||||
HMODULE sharepj_module = libutils::try_module("libshare-pj.dll");
|
||||
HMODULE bmsd_engine_module = libutils::try_module("libbmsd-engine.dll");
|
||||
HMODULE bmsd_module = libutils::try_module("libbmsd.dll");
|
||||
HMODULE bmsd2_module = libutils::try_module("libbmsd2.dll");
|
||||
HMODULE gdme_module = libutils::try_module("libgdme.dll");
|
||||
HMODULE system_module = libutils::try_module("libsystem.dll");
|
||||
|
||||
// patches
|
||||
detour::inline_hook((void *) eam_network_detected_ip_change, libutils::try_proc(
|
||||
sharepj_module, "eam_network_detected_ip_change"));
|
||||
detour::inline_hook((void *) eam_network_settings_conflict, libutils::try_proc(
|
||||
sharepj_module, "eam_network_settings_conflict"));
|
||||
detour::inline_hook((void *) bmsd2_set_windows_volume, libutils::try_proc(
|
||||
bmsd2_module, "bmsd2_set_windows_volume"));
|
||||
detour::inline_hook((void *) bmsd2_set_windows_volume, libutils::try_proc(
|
||||
bmsd2_module, "bmsd2_set_windows_volume"));
|
||||
detour::inline_hook((void *) sys_code_get_cmdline, libutils::try_proc(
|
||||
system_module, "sys_code_get_cmdline"));
|
||||
detour::inline_hook((void *) sys_setting_get_param, libutils::try_proc(
|
||||
system_module, "sys_setting_get_param"));
|
||||
detour::inline_hook((void *) sys_setting_set_param, libutils::try_proc(
|
||||
system_module, "sys_setting_set_param"));
|
||||
detour::inline_hook((void *) sys_debug_dip_get_param, libutils::try_proc(
|
||||
system_module, "sys_debug_dip_get_param"));
|
||||
detour::inline_hook((void *) sys_debug_dip_set_param, libutils::try_proc(
|
||||
system_module, "sys_debug_dip_set_param"));
|
||||
|
||||
// window patch
|
||||
if (GRAPHICS_WINDOWED && !replace_pattern(
|
||||
gdme_module,
|
||||
"754185ED753D8B4118BF0000CB02",
|
||||
"9090????9090??????????????12", 0, 0))
|
||||
{
|
||||
log_warning("gitadora", "windowed mode failed");
|
||||
}
|
||||
|
||||
// two channel mod
|
||||
if (TWOCHANNEL) {
|
||||
bmsd2_boot_orig = detour::iat_try("bmsd2_boot", bmsd2_boot_hook, bmsd_module);
|
||||
|
||||
if (!(replace_pattern(bmsd_engine_module, "33000000488D", "03??????????", 0, 0) ||
|
||||
replace_pattern(bmsd_engine_module, "330000000F10", "03??????????", 0, 0)))
|
||||
{
|
||||
log_warning("gitadora", "two channel mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "gitadora.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sigscan.h"
|
||||
|
||||
namespace games::gitadora {
|
||||
|
||||
// settings
|
||||
bool TWOCHANNEL = false;
|
||||
std::optional<unsigned int> CAB_TYPE = std::nullopt;
|
||||
|
||||
/*
|
||||
* GitaDora checks if the IP address has changed, and if it has it throws 5-1506-0000 like jubeat.
|
||||
* We don't want this so we patch it out.
|
||||
*/
|
||||
static char __cdecl eam_network_detected_ip_change() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GitaDora checks if the server it connects to is in the 192.168.0.0/16 or 169.254.0.0/16 subnet.
|
||||
* If it is, it downright refuses to use it and errors with no visible indication.
|
||||
* We don't want this so we patch it out.
|
||||
*/
|
||||
static char __cdecl eam_network_settings_conflict() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent GitaDora from changing the volume setting.
|
||||
*/
|
||||
static long __cdecl bmsd2_set_windows_volume(int volume) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two Channel Audio Mode
|
||||
* We proxy bmsd2_boot_hook and modify the last parameter which is apparently the channel count.
|
||||
* Since this apparently isn't the only thing required we need a signature scan to modify a value as well.
|
||||
*/
|
||||
typedef int (__cdecl *bmsd2_boot_t)(long a1, int a2, long a3, char channel_count);
|
||||
static bmsd2_boot_t bmsd2_boot_orig = nullptr;
|
||||
static int __cdecl bmsd2_boot_hook(long a1, int a2, long a3, char channel_count) {
|
||||
return bmsd2_boot_orig(a1, a2, a3, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Command Line Arguments
|
||||
* We hook this to override specific values.
|
||||
* This currently disables the ability to specify your own in the app-config.xml (param/cmdline __type="str")
|
||||
*/
|
||||
static bool __cdecl sys_code_get_cmdline(const char *cmdline) {
|
||||
if (strcmp(cmdline, "-d") == 0) {
|
||||
return true;
|
||||
} else if (strcmp(cmdline, "-DM") == 0) {
|
||||
return true;
|
||||
} else if (strcmp(cmdline, "-WINDOW") == 0) {
|
||||
return GRAPHICS_WINDOWED;
|
||||
} else if (strcmp(cmdline, "-LOGOUT") == 0) {
|
||||
return false;
|
||||
} else if (strcmp(cmdline, "-AOU") == 0) {
|
||||
return false;
|
||||
} else if (strcmp(cmdline, "-QCMODE") == 0) {
|
||||
return false;
|
||||
} else if (strcmp(cmdline, "-FACTORY") == 0) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* System Setting Parameter Overrides
|
||||
*/
|
||||
static std::unordered_map<std::string, long> SYS_SETTINGS;
|
||||
static std::unordered_map<std::string, long> SYS_DEBUG_DIPS;
|
||||
|
||||
static long __cdecl sys_setting_get_param(const char *param) {
|
||||
|
||||
// overrides
|
||||
if (strcmp(param, "PRODUCTION_MODE") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "ENABLE_DISP_ID") == 0) {
|
||||
return 0;
|
||||
} else if (CAB_TYPE.has_value() && strcmp(param, "VER_MACHINE") == 0) {
|
||||
return CAB_TYPE.value() << 12;
|
||||
}
|
||||
|
||||
// map lookup
|
||||
auto it = SYS_SETTINGS.find(param);
|
||||
if (it != SYS_SETTINGS.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long __cdecl sys_setting_set_param(const char *param, long value) {
|
||||
SYS_SETTINGS[std::string(param)] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long __cdecl sys_debug_dip_get_param(const char *param) {
|
||||
|
||||
// overrides
|
||||
if (strcmp(param, "sysinfo") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "jobbar1") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "jobbar2") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "serial") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "warnvpf") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "scrshot") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "eamxml") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "offset") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "autodbg") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "develop") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "effect_test") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(param, "voice_type2") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// map lookup
|
||||
auto it = SYS_DEBUG_DIPS.find(param);
|
||||
if (it != SYS_DEBUG_DIPS.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long __cdecl sys_debug_dip_set_param(const char *param, long value) {
|
||||
SYS_DEBUG_DIPS[std::string(param)] = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
GitaDoraGame::GitaDoraGame() : Game("GitaDora") {
|
||||
}
|
||||
|
||||
void GitaDoraGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// modules
|
||||
HMODULE sharepj_module = libutils::try_module("libshare-pj.dll");
|
||||
HMODULE bmsd_engine_module = libutils::try_module("libbmsd-engine.dll");
|
||||
HMODULE bmsd_module = libutils::try_module("libbmsd.dll");
|
||||
HMODULE bmsd2_module = libutils::try_module("libbmsd2.dll");
|
||||
HMODULE gdme_module = libutils::try_module("libgdme.dll");
|
||||
HMODULE system_module = libutils::try_module("libsystem.dll");
|
||||
|
||||
// patches
|
||||
detour::inline_hook((void *) eam_network_detected_ip_change, libutils::try_proc(
|
||||
sharepj_module, "eam_network_detected_ip_change"));
|
||||
detour::inline_hook((void *) eam_network_settings_conflict, libutils::try_proc(
|
||||
sharepj_module, "eam_network_settings_conflict"));
|
||||
detour::inline_hook((void *) bmsd2_set_windows_volume, libutils::try_proc(
|
||||
bmsd2_module, "bmsd2_set_windows_volume"));
|
||||
detour::inline_hook((void *) bmsd2_set_windows_volume, libutils::try_proc(
|
||||
bmsd2_module, "bmsd2_set_windows_volume"));
|
||||
detour::inline_hook((void *) sys_code_get_cmdline, libutils::try_proc(
|
||||
system_module, "sys_code_get_cmdline"));
|
||||
detour::inline_hook((void *) sys_setting_get_param, libutils::try_proc(
|
||||
system_module, "sys_setting_get_param"));
|
||||
detour::inline_hook((void *) sys_setting_set_param, libutils::try_proc(
|
||||
system_module, "sys_setting_set_param"));
|
||||
detour::inline_hook((void *) sys_debug_dip_get_param, libutils::try_proc(
|
||||
system_module, "sys_debug_dip_get_param"));
|
||||
detour::inline_hook((void *) sys_debug_dip_set_param, libutils::try_proc(
|
||||
system_module, "sys_debug_dip_set_param"));
|
||||
|
||||
// window patch
|
||||
if (GRAPHICS_WINDOWED && !replace_pattern(
|
||||
gdme_module,
|
||||
"754185ED753D8B4118BF0000CB02",
|
||||
"9090????9090??????????????12", 0, 0))
|
||||
{
|
||||
log_warning("gitadora", "windowed mode failed");
|
||||
}
|
||||
|
||||
// two channel mod
|
||||
if (TWOCHANNEL) {
|
||||
bmsd2_boot_orig = detour::iat_try("bmsd2_boot", bmsd2_boot_hook, bmsd_module);
|
||||
|
||||
if (!(replace_pattern(bmsd_engine_module, "33000000488D", "03??????????", 0, 0) ||
|
||||
replace_pattern(bmsd_engine_module, "330000000F10", "03??????????", 0, 0)))
|
||||
{
|
||||
log_warning("gitadora", "two channel mode failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-18
@@ -1,18 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::gitadora {
|
||||
|
||||
// settings
|
||||
extern bool TWOCHANNEL;
|
||||
extern std::optional<unsigned int> CAB_TYPE;
|
||||
|
||||
class GitaDoraGame : public games::Game {
|
||||
public:
|
||||
GitaDoraGame();
|
||||
virtual void attach();
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::gitadora {
|
||||
|
||||
// settings
|
||||
extern bool TWOCHANNEL;
|
||||
extern std::optional<unsigned int> CAB_TYPE;
|
||||
|
||||
class GitaDoraGame : public games::Game {
|
||||
public:
|
||||
GitaDoraGame();
|
||||
virtual void attach();
|
||||
};
|
||||
}
|
||||
|
||||
+118
-118
@@ -1,118 +1,118 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::gitadora::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("GitaDora");
|
||||
|
||||
GameAPI::Buttons::sortButtons(&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin",
|
||||
"Guitar P1 Start",
|
||||
"Guitar P1 Up",
|
||||
"Guitar P1 Down",
|
||||
"Guitar P1 Left",
|
||||
"Guitar P1 Right",
|
||||
"Guitar P1 Help",
|
||||
"Guitar P1 Effect 1",
|
||||
"Guitar P1 Effect 2",
|
||||
"Guitar P1 Effect 3",
|
||||
"Guitar P1 Effect Pedal",
|
||||
"Guitar P1 Button Extra 1",
|
||||
"Guitar P1 Button Extra 2",
|
||||
"Guitar P1 Pick Up",
|
||||
"Guitar P1 Pick Down",
|
||||
"Guitar P1 R",
|
||||
"Guitar P1 G",
|
||||
"Guitar P1 B",
|
||||
"Guitar P1 Y",
|
||||
"Guitar P1 P",
|
||||
"Guitar P1 Knob Up",
|
||||
"Guitar P1 Knob Down",
|
||||
"Guitar P1 Wail Up",
|
||||
"Guitar P1 Wail Down",
|
||||
"Guitar P2 Start",
|
||||
"Guitar P2 Up",
|
||||
"Guitar P2 Down",
|
||||
"Guitar P2 Left",
|
||||
"Guitar P2 Right",
|
||||
"Guitar P2 Help",
|
||||
"Guitar P2 Effect 1",
|
||||
"Guitar P2 Effect 2",
|
||||
"Guitar P2 Effect 3",
|
||||
"Guitar P2 Effect Pedal",
|
||||
"Guitar P2 Button Extra 1",
|
||||
"Guitar P2 Button Extra 2",
|
||||
"Guitar P2 Pick Up",
|
||||
"Guitar P2 Pick Down",
|
||||
"Guitar P2 R",
|
||||
"Guitar P2 G",
|
||||
"Guitar P2 B",
|
||||
"Guitar P2 Y",
|
||||
"Guitar P2 P",
|
||||
"Guitar P2 Knob Up",
|
||||
"Guitar P2 Knob Down",
|
||||
"Guitar P2 Wail Up",
|
||||
"Guitar P2 Wail Down",
|
||||
"Drum Start",
|
||||
"Drum Up",
|
||||
"Drum Down",
|
||||
"Drum Left",
|
||||
"Drum Right",
|
||||
"Drum Help",
|
||||
"Drum Button Extra 1",
|
||||
"Drum Button Extra 2",
|
||||
"Drum Hi-Hat",
|
||||
"Drum Hi-Hat Closed",
|
||||
"Drum Hi-Hat Half-Open",
|
||||
"Drum Snare",
|
||||
"Drum Hi-Tom",
|
||||
"Drum Low-Tom",
|
||||
"Drum Right Cymbal",
|
||||
"Drum Bass Pedal",
|
||||
"Drum Left Cymbal",
|
||||
"Drum Left Pedal",
|
||||
"Drum Floor Tom"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::gitadora::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("GitaDora");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(&analogs,
|
||||
"Guitar P1 Wail X",
|
||||
"Guitar P1 Wail Y",
|
||||
"Guitar P1 Wail Z",
|
||||
"Guitar P1 Knob",
|
||||
"Guitar P2 Wail X",
|
||||
"Guitar P2 Wail Y",
|
||||
"Guitar P2 Wail Z",
|
||||
"Guitar P2 Knob"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::gitadora::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("GitaDora");
|
||||
|
||||
GameAPI::Lights::sortLights(&lights,
|
||||
"Guitar P1 Motor",
|
||||
"Guitar P2 Motor"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::gitadora::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("GitaDora");
|
||||
|
||||
GameAPI::Buttons::sortButtons(&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin",
|
||||
"Guitar P1 Start",
|
||||
"Guitar P1 Up",
|
||||
"Guitar P1 Down",
|
||||
"Guitar P1 Left",
|
||||
"Guitar P1 Right",
|
||||
"Guitar P1 Help",
|
||||
"Guitar P1 Effect 1",
|
||||
"Guitar P1 Effect 2",
|
||||
"Guitar P1 Effect 3",
|
||||
"Guitar P1 Effect Pedal",
|
||||
"Guitar P1 Button Extra 1",
|
||||
"Guitar P1 Button Extra 2",
|
||||
"Guitar P1 Pick Up",
|
||||
"Guitar P1 Pick Down",
|
||||
"Guitar P1 R",
|
||||
"Guitar P1 G",
|
||||
"Guitar P1 B",
|
||||
"Guitar P1 Y",
|
||||
"Guitar P1 P",
|
||||
"Guitar P1 Knob Up",
|
||||
"Guitar P1 Knob Down",
|
||||
"Guitar P1 Wail Up",
|
||||
"Guitar P1 Wail Down",
|
||||
"Guitar P2 Start",
|
||||
"Guitar P2 Up",
|
||||
"Guitar P2 Down",
|
||||
"Guitar P2 Left",
|
||||
"Guitar P2 Right",
|
||||
"Guitar P2 Help",
|
||||
"Guitar P2 Effect 1",
|
||||
"Guitar P2 Effect 2",
|
||||
"Guitar P2 Effect 3",
|
||||
"Guitar P2 Effect Pedal",
|
||||
"Guitar P2 Button Extra 1",
|
||||
"Guitar P2 Button Extra 2",
|
||||
"Guitar P2 Pick Up",
|
||||
"Guitar P2 Pick Down",
|
||||
"Guitar P2 R",
|
||||
"Guitar P2 G",
|
||||
"Guitar P2 B",
|
||||
"Guitar P2 Y",
|
||||
"Guitar P2 P",
|
||||
"Guitar P2 Knob Up",
|
||||
"Guitar P2 Knob Down",
|
||||
"Guitar P2 Wail Up",
|
||||
"Guitar P2 Wail Down",
|
||||
"Drum Start",
|
||||
"Drum Up",
|
||||
"Drum Down",
|
||||
"Drum Left",
|
||||
"Drum Right",
|
||||
"Drum Help",
|
||||
"Drum Button Extra 1",
|
||||
"Drum Button Extra 2",
|
||||
"Drum Hi-Hat",
|
||||
"Drum Hi-Hat Closed",
|
||||
"Drum Hi-Hat Half-Open",
|
||||
"Drum Snare",
|
||||
"Drum Hi-Tom",
|
||||
"Drum Low-Tom",
|
||||
"Drum Right Cymbal",
|
||||
"Drum Bass Pedal",
|
||||
"Drum Left Cymbal",
|
||||
"Drum Left Pedal",
|
||||
"Drum Floor Tom"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::gitadora::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("GitaDora");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(&analogs,
|
||||
"Guitar P1 Wail X",
|
||||
"Guitar P1 Wail Y",
|
||||
"Guitar P1 Wail Z",
|
||||
"Guitar P1 Knob",
|
||||
"Guitar P2 Wail X",
|
||||
"Guitar P2 Wail Y",
|
||||
"Guitar P2 Wail Z",
|
||||
"Guitar P2 Knob"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::gitadora::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("GitaDora");
|
||||
|
||||
GameAPI::Lights::sortLights(&lights,
|
||||
"Guitar P1 Motor",
|
||||
"Guitar P2 Motor"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+108
-108
@@ -1,108 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::gitadora {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Coin,
|
||||
GuitarP1Start,
|
||||
GuitarP1Up,
|
||||
GuitarP1Down,
|
||||
GuitarP1Left,
|
||||
GuitarP1Right,
|
||||
GuitarP1Help,
|
||||
GuitarP1Effect1,
|
||||
GuitarP1Effect2,
|
||||
GuitarP1Effect3,
|
||||
GuitarP1EffectPedal,
|
||||
GuitarP1ButtonExtra1,
|
||||
GuitarP1ButtonExtra2,
|
||||
GuitarP1PickUp,
|
||||
GuitarP1PickDown,
|
||||
GuitarP1R,
|
||||
GuitarP1G,
|
||||
GuitarP1B,
|
||||
GuitarP1Y,
|
||||
GuitarP1P,
|
||||
GuitarP1KnobUp,
|
||||
GuitarP1KnobDown,
|
||||
GuitarP1WailUp,
|
||||
GuitarP1WailDown,
|
||||
GuitarP2Start,
|
||||
GuitarP2Up,
|
||||
GuitarP2Down,
|
||||
GuitarP2Left,
|
||||
GuitarP2Right,
|
||||
GuitarP2Help,
|
||||
GuitarP2Effect1,
|
||||
GuitarP2Effect2,
|
||||
GuitarP2Effect3,
|
||||
GuitarP2EffectPedal,
|
||||
GuitarP2ButtonExtra1,
|
||||
GuitarP2ButtonExtra2,
|
||||
GuitarP2PickUp,
|
||||
GuitarP2PickDown,
|
||||
GuitarP2R,
|
||||
GuitarP2G,
|
||||
GuitarP2B,
|
||||
GuitarP2Y,
|
||||
GuitarP2P,
|
||||
GuitarP2KnobUp,
|
||||
GuitarP2KnobDown,
|
||||
GuitarP2WailUp,
|
||||
GuitarP2WailDown,
|
||||
DrumStart,
|
||||
DrumUp,
|
||||
DrumDown,
|
||||
DrumLeft,
|
||||
DrumRight,
|
||||
DrumHelp,
|
||||
DrumButtonExtra1,
|
||||
DrumButtonExtra2,
|
||||
DrumHiHat,
|
||||
DrumHiHatClosed,
|
||||
DrumHiHatHalfOpen,
|
||||
DrumSnare,
|
||||
DrumHiTom,
|
||||
DrumLowTom,
|
||||
DrumRightCymbal,
|
||||
DrumBassPedal,
|
||||
DrumLeftCymbal,
|
||||
DrumLeftPedal,
|
||||
DrumFloorTom
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
GuitarP1WailX,
|
||||
GuitarP1WailY,
|
||||
GuitarP1WailZ,
|
||||
GuitarP1Knob,
|
||||
GuitarP2WailX,
|
||||
GuitarP2WailY,
|
||||
GuitarP2WailZ,
|
||||
GuitarP2Knob
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
GuitarP1Motor,
|
||||
GuitarP2Motor,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::gitadora {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Coin,
|
||||
GuitarP1Start,
|
||||
GuitarP1Up,
|
||||
GuitarP1Down,
|
||||
GuitarP1Left,
|
||||
GuitarP1Right,
|
||||
GuitarP1Help,
|
||||
GuitarP1Effect1,
|
||||
GuitarP1Effect2,
|
||||
GuitarP1Effect3,
|
||||
GuitarP1EffectPedal,
|
||||
GuitarP1ButtonExtra1,
|
||||
GuitarP1ButtonExtra2,
|
||||
GuitarP1PickUp,
|
||||
GuitarP1PickDown,
|
||||
GuitarP1R,
|
||||
GuitarP1G,
|
||||
GuitarP1B,
|
||||
GuitarP1Y,
|
||||
GuitarP1P,
|
||||
GuitarP1KnobUp,
|
||||
GuitarP1KnobDown,
|
||||
GuitarP1WailUp,
|
||||
GuitarP1WailDown,
|
||||
GuitarP2Start,
|
||||
GuitarP2Up,
|
||||
GuitarP2Down,
|
||||
GuitarP2Left,
|
||||
GuitarP2Right,
|
||||
GuitarP2Help,
|
||||
GuitarP2Effect1,
|
||||
GuitarP2Effect2,
|
||||
GuitarP2Effect3,
|
||||
GuitarP2EffectPedal,
|
||||
GuitarP2ButtonExtra1,
|
||||
GuitarP2ButtonExtra2,
|
||||
GuitarP2PickUp,
|
||||
GuitarP2PickDown,
|
||||
GuitarP2R,
|
||||
GuitarP2G,
|
||||
GuitarP2B,
|
||||
GuitarP2Y,
|
||||
GuitarP2P,
|
||||
GuitarP2KnobUp,
|
||||
GuitarP2KnobDown,
|
||||
GuitarP2WailUp,
|
||||
GuitarP2WailDown,
|
||||
DrumStart,
|
||||
DrumUp,
|
||||
DrumDown,
|
||||
DrumLeft,
|
||||
DrumRight,
|
||||
DrumHelp,
|
||||
DrumButtonExtra1,
|
||||
DrumButtonExtra2,
|
||||
DrumHiHat,
|
||||
DrumHiHatClosed,
|
||||
DrumHiHatHalfOpen,
|
||||
DrumSnare,
|
||||
DrumHiTom,
|
||||
DrumLowTom,
|
||||
DrumRightCymbal,
|
||||
DrumBassPedal,
|
||||
DrumLeftCymbal,
|
||||
DrumLeftPedal,
|
||||
DrumFloorTom
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
GuitarP1WailX,
|
||||
GuitarP1WailY,
|
||||
GuitarP1WailZ,
|
||||
GuitarP1Knob,
|
||||
GuitarP2WailX,
|
||||
GuitarP2WailY,
|
||||
GuitarP2WailZ,
|
||||
GuitarP2Knob
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
GuitarP1Motor,
|
||||
GuitarP2Motor,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+38
-38
@@ -1,38 +1,38 @@
|
||||
#include "avs/game.h"
|
||||
#include "hpm.h"
|
||||
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
namespace games::hpm {
|
||||
|
||||
BOOL WINAPI SetCurrentDirectoryW_hook(LPCTSTR lpPathName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static decltype(mixerSetControlDetails)* mixerSetControlDetails_real = nullptr;
|
||||
|
||||
static MMRESULT WINAPI mixerSetControlDetails_hook(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
|
||||
|
||||
mixerSetControlDetails_real(hmxobj, pmxcd, fdwDetails);
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
HPMGame::HPMGame() : Game("HELLO! Pop'n Music") {
|
||||
}
|
||||
|
||||
void HPMGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
HMODULE kernel32_module = libutils::try_module("kernel32.dll");
|
||||
|
||||
// patches
|
||||
detour::inline_hook((void *) SetCurrentDirectoryW_hook, libutils::try_proc(
|
||||
kernel32_module, "SetCurrentDirectoryW"));
|
||||
|
||||
mixerSetControlDetails_real = detour::iat_try("mixerSetControlDetails", mixerSetControlDetails_hook, avs::game::DLL_INSTANCE);
|
||||
}
|
||||
}
|
||||
#include "avs/game.h"
|
||||
#include "hpm.h"
|
||||
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
namespace games::hpm {
|
||||
|
||||
BOOL WINAPI SetCurrentDirectoryW_hook(LPCTSTR lpPathName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static decltype(mixerSetControlDetails)* mixerSetControlDetails_real = nullptr;
|
||||
|
||||
static MMRESULT WINAPI mixerSetControlDetails_hook(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
|
||||
|
||||
mixerSetControlDetails_real(hmxobj, pmxcd, fdwDetails);
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
HPMGame::HPMGame() : Game("HELLO! Pop'n Music") {
|
||||
}
|
||||
|
||||
void HPMGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
HMODULE kernel32_module = libutils::try_module("kernel32.dll");
|
||||
|
||||
// patches
|
||||
detour::inline_hook((void *) SetCurrentDirectoryW_hook, libutils::try_proc(
|
||||
kernel32_module, "SetCurrentDirectoryW"));
|
||||
|
||||
mixerSetControlDetails_real = detour::iat_try("mixerSetControlDetails", mixerSetControlDetails_hook, avs::game::DLL_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::hpm {
|
||||
|
||||
class HPMGame : public games::Game {
|
||||
public:
|
||||
HPMGame();
|
||||
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::hpm {
|
||||
|
||||
class HPMGame : public games::Game {
|
||||
public:
|
||||
HPMGame();
|
||||
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+54
-54
@@ -1,54 +1,54 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::hpm::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("HELLO! Pop'n Music");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"P1 Start",
|
||||
"P1 1",
|
||||
"P1 2",
|
||||
"P1 3",
|
||||
"P1 4",
|
||||
"P2 Start",
|
||||
"P2 1",
|
||||
"P2 2",
|
||||
"P2 3",
|
||||
"P2 4"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::hpm::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("HELLO! Pop'n Music");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Speaker Red",
|
||||
"Speaker Orange",
|
||||
"Speaker Blue",
|
||||
"P1 Start",
|
||||
"P1 Red & P2 Green",
|
||||
"P1 Blue",
|
||||
"P1 Yellow",
|
||||
"P1 Green",
|
||||
"P2 Start",
|
||||
"P2 Red",
|
||||
"P2 Blue",
|
||||
"P2 Yellow"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::hpm::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("HELLO! Pop'n Music");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"P1 Start",
|
||||
"P1 1",
|
||||
"P1 2",
|
||||
"P1 3",
|
||||
"P1 4",
|
||||
"P2 Start",
|
||||
"P2 1",
|
||||
"P2 2",
|
||||
"P2 3",
|
||||
"P2 4"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::hpm::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("HELLO! Pop'n Music");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Speaker Red",
|
||||
"Speaker Orange",
|
||||
"Speaker Blue",
|
||||
"P1 Start",
|
||||
"P1 Red & P2 Green",
|
||||
"P1 Blue",
|
||||
"P1 Yellow",
|
||||
"P1 Green",
|
||||
"P2 Start",
|
||||
"P2 Red",
|
||||
"P2 Blue",
|
||||
"P2 Yellow"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+48
-48
@@ -1,48 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::hpm {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
P1_Start,
|
||||
P1_1,
|
||||
P1_2,
|
||||
P1_3,
|
||||
P1_4,
|
||||
P2_Start,
|
||||
P2_1,
|
||||
P2_2,
|
||||
P2_3,
|
||||
P2_4,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
SPEAKER_RED,
|
||||
SPEAKER_ORANGE,
|
||||
SPEAKER_BLUE,
|
||||
P1_START,
|
||||
P1_RED_P2_GREEN,
|
||||
P1_BLUE,
|
||||
P1_YELLOW,
|
||||
P1_GREEN,
|
||||
P2_START,
|
||||
P2_RED,
|
||||
P2_BLUE,
|
||||
P2_YELLOW,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::hpm {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
P1_Start,
|
||||
P1_1,
|
||||
P1_2,
|
||||
P1_3,
|
||||
P1_4,
|
||||
P2_Start,
|
||||
P2_1,
|
||||
P2_2,
|
||||
P2_3,
|
||||
P2_4,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
SPEAKER_RED,
|
||||
SPEAKER_ORANGE,
|
||||
SPEAKER_BLUE,
|
||||
P1_START,
|
||||
P1_RED_P2_GREEN,
|
||||
P1_BLUE,
|
||||
P1_YELLOW,
|
||||
P1_GREEN,
|
||||
P2_START,
|
||||
P2_RED,
|
||||
P2_BLUE,
|
||||
P2_YELLOW,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+241
-241
@@ -1,241 +1,241 @@
|
||||
#include "bi2a.h"
|
||||
|
||||
#include "misc/eamuse.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#include "iidx.h"
|
||||
#include "io.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
games::iidx::IIDXFMSerialHandle::FMSerialDevice::FMSerialDevice() {
|
||||
this->node_count = 1;
|
||||
}
|
||||
|
||||
bool games::iidx::IIDXFMSerialHandle::FMSerialDevice::parse_msg(
|
||||
MessageData *msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) {
|
||||
#ifdef ACIOEMU_LOG
|
||||
log_info("iidx", "BI2A ADDR: {}, CMD: 0x{:04x}", msg_in->addr, msg_in->cmd.code);
|
||||
#endif
|
||||
|
||||
// check command
|
||||
switch (msg_in->cmd.code) {
|
||||
case ACIO_CMD_GET_VERSION: {
|
||||
|
||||
// send version data
|
||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||
this->set_version(msg, 0x03, 0, 4, 2, 0, "BI2A");
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case 0x0152: { // STATUS
|
||||
|
||||
// check input data length
|
||||
if (msg_in->cmd.data_size == 0x30) {
|
||||
|
||||
// LED TICKER
|
||||
IIDX_LED_TICKER_LOCK.lock();
|
||||
if (!IIDXIO_LED_TICKER_READONLY)
|
||||
memcpy(IIDXIO_LED_TICKER, &msg_in->cmd.raw[0x17], 9);
|
||||
IIDX_LED_TICKER_LOCK.unlock();
|
||||
|
||||
// NEON LIGHT
|
||||
bool neon_light = msg_in->cmd.raw[0x24] != 0;
|
||||
write_top_neon(neon_light ? (uint8_t) 0xFF : (uint8_t) 0);
|
||||
|
||||
// SPOT LIGHT
|
||||
uint8_t spot_light_bits = 0;
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
auto index = i > 3 ? i + 1 : i;
|
||||
if (msg_in->cmd.raw[0x20 + index] != 0)
|
||||
spot_light_bits |= 1 << i;
|
||||
}
|
||||
write_top_lamp(spot_light_bits);
|
||||
|
||||
// SWLED (DECK)
|
||||
uint16_t lamp_bits = 0;
|
||||
for (size_t i = 0; i < 14; i++) {
|
||||
if (msg_in->cmd.raw[0x07 + i] != 0)
|
||||
lamp_bits |= 1 << i;
|
||||
}
|
||||
write_lamp(lamp_bits);
|
||||
|
||||
// SWLED (PANEL)
|
||||
uint8_t led_bits = 0;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (msg_in->cmd.raw[0x03 + i] != 0)
|
||||
led_bits |= 1 << i;
|
||||
}
|
||||
write_led(led_bits);
|
||||
|
||||
// flush device output
|
||||
RI_MGR->devices_flush_output();
|
||||
}
|
||||
|
||||
// sleep - otherwise the IO thread will go too hard on the CPU
|
||||
Sleep(1);
|
||||
|
||||
// generate message
|
||||
auto msg = this->create_msg(msg_in, 0x2E);
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// player 1 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 151);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 167);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 183);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 199);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 215);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 231);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 247);
|
||||
|
||||
// player 2 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 263);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 279);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 295);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 311);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 327);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 343);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 359);
|
||||
|
||||
// player 1 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 79);
|
||||
|
||||
// player 2 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 78);
|
||||
|
||||
// VEFX
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::VEFX)))
|
||||
ARRAY_SETB(msg->cmd.raw, 77);
|
||||
|
||||
// EFFECT
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Effect)))
|
||||
ARRAY_SETB(msg->cmd.raw, 76);
|
||||
|
||||
// service
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service)))
|
||||
ARRAY_SETB(msg->cmd.raw, 10);
|
||||
|
||||
// test
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test)))
|
||||
ARRAY_SETB(msg->cmd.raw, 11);
|
||||
|
||||
// turntables
|
||||
msg->cmd.raw[16] = get_tt(0, true);
|
||||
msg->cmd.raw[17] = get_tt(1, true);
|
||||
|
||||
// slider
|
||||
msg->cmd.raw[0] |= get_slider(0) << 4;
|
||||
msg->cmd.raw[2] |= get_slider(1) << 4;
|
||||
msg->cmd.raw[4] |= get_slider(2) << 4;
|
||||
msg->cmd.raw[6] |= get_slider(3) << 4;
|
||||
msg->cmd.raw[7] |= get_slider(4) << 4;
|
||||
|
||||
// coin
|
||||
this->coin_counter += eamuse_coin_consume_stock();
|
||||
msg->cmd.raw[8] |= this->coin_counter;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* bit 9 appears to be the coin mech
|
||||
*/
|
||||
|
||||
// write message
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case ACIO_CMD_CLEAR:
|
||||
case ACIO_CMD_STARTUP:
|
||||
case 0x0120: // WD COMMAND
|
||||
case 0xFF: // BROADCAST
|
||||
{
|
||||
// send status 0
|
||||
auto msg = this->create_msg_status(msg_in, 0);
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark as handled
|
||||
return true;
|
||||
}
|
||||
|
||||
bool games::iidx::IIDXFMSerialHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM2") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("iidx", "Opened COM2 (FM DEVICE)");
|
||||
|
||||
// ACIO device
|
||||
acio_emu.add_device(new FMSerialDevice());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::iidx::IIDXFMSerialHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
|
||||
|
||||
// read from emu
|
||||
DWORD bytes_read = 0;
|
||||
while (bytes_read < nNumberOfBytesToRead) {
|
||||
auto cur_byte = acio_emu.read();
|
||||
|
||||
if (cur_byte.has_value()) {
|
||||
buffer[bytes_read++] = cur_byte.value();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// return amount of bytes read
|
||||
return (int) bytes_read;
|
||||
}
|
||||
|
||||
int games::iidx::IIDXFMSerialHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
|
||||
|
||||
// write to emu
|
||||
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
|
||||
acio_emu.write(buffer[i]);
|
||||
}
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::iidx::IIDXFMSerialHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::iidx::IIDXFMSerialHandle::close() {
|
||||
log_info("iidx", "Closed COM2 (FM DEVICE)");
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "bi2a.h"
|
||||
|
||||
#include "misc/eamuse.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#include "iidx.h"
|
||||
#include "io.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
games::iidx::IIDXFMSerialHandle::FMSerialDevice::FMSerialDevice() {
|
||||
this->node_count = 1;
|
||||
}
|
||||
|
||||
bool games::iidx::IIDXFMSerialHandle::FMSerialDevice::parse_msg(
|
||||
MessageData *msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) {
|
||||
#ifdef ACIOEMU_LOG
|
||||
log_info("iidx", "BI2A ADDR: {}, CMD: 0x{:04x}", msg_in->addr, msg_in->cmd.code);
|
||||
#endif
|
||||
|
||||
// check command
|
||||
switch (msg_in->cmd.code) {
|
||||
case ACIO_CMD_GET_VERSION: {
|
||||
|
||||
// send version data
|
||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||
this->set_version(msg, 0x03, 0, 4, 2, 0, "BI2A");
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case 0x0152: { // STATUS
|
||||
|
||||
// check input data length
|
||||
if (msg_in->cmd.data_size == 0x30) {
|
||||
|
||||
// LED TICKER
|
||||
IIDX_LED_TICKER_LOCK.lock();
|
||||
if (!IIDXIO_LED_TICKER_READONLY)
|
||||
memcpy(IIDXIO_LED_TICKER, &msg_in->cmd.raw[0x17], 9);
|
||||
IIDX_LED_TICKER_LOCK.unlock();
|
||||
|
||||
// NEON LIGHT
|
||||
bool neon_light = msg_in->cmd.raw[0x24] != 0;
|
||||
write_top_neon(neon_light ? (uint8_t) 0xFF : (uint8_t) 0);
|
||||
|
||||
// SPOT LIGHT
|
||||
uint8_t spot_light_bits = 0;
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
auto index = i > 3 ? i + 1 : i;
|
||||
if (msg_in->cmd.raw[0x20 + index] != 0)
|
||||
spot_light_bits |= 1 << i;
|
||||
}
|
||||
write_top_lamp(spot_light_bits);
|
||||
|
||||
// SWLED (DECK)
|
||||
uint16_t lamp_bits = 0;
|
||||
for (size_t i = 0; i < 14; i++) {
|
||||
if (msg_in->cmd.raw[0x07 + i] != 0)
|
||||
lamp_bits |= 1 << i;
|
||||
}
|
||||
write_lamp(lamp_bits);
|
||||
|
||||
// SWLED (PANEL)
|
||||
uint8_t led_bits = 0;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (msg_in->cmd.raw[0x03 + i] != 0)
|
||||
led_bits |= 1 << i;
|
||||
}
|
||||
write_led(led_bits);
|
||||
|
||||
// flush device output
|
||||
RI_MGR->devices_flush_output();
|
||||
}
|
||||
|
||||
// sleep - otherwise the IO thread will go too hard on the CPU
|
||||
Sleep(1);
|
||||
|
||||
// generate message
|
||||
auto msg = this->create_msg(msg_in, 0x2E);
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// player 1 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 151);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 167);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 183);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 199);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 215);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 231);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 247);
|
||||
|
||||
// player 2 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 263);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 279);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 295);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 311);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 327);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 343);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 359);
|
||||
|
||||
// player 1 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 79);
|
||||
|
||||
// player 2 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 78);
|
||||
|
||||
// VEFX
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::VEFX)))
|
||||
ARRAY_SETB(msg->cmd.raw, 77);
|
||||
|
||||
// EFFECT
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Effect)))
|
||||
ARRAY_SETB(msg->cmd.raw, 76);
|
||||
|
||||
// service
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service)))
|
||||
ARRAY_SETB(msg->cmd.raw, 10);
|
||||
|
||||
// test
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test)))
|
||||
ARRAY_SETB(msg->cmd.raw, 11);
|
||||
|
||||
// turntables
|
||||
msg->cmd.raw[16] = get_tt(0, true);
|
||||
msg->cmd.raw[17] = get_tt(1, true);
|
||||
|
||||
// slider
|
||||
msg->cmd.raw[0] |= get_slider(0) << 4;
|
||||
msg->cmd.raw[2] |= get_slider(1) << 4;
|
||||
msg->cmd.raw[4] |= get_slider(2) << 4;
|
||||
msg->cmd.raw[6] |= get_slider(3) << 4;
|
||||
msg->cmd.raw[7] |= get_slider(4) << 4;
|
||||
|
||||
// coin
|
||||
this->coin_counter += eamuse_coin_consume_stock();
|
||||
msg->cmd.raw[8] |= this->coin_counter;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* bit 9 appears to be the coin mech
|
||||
*/
|
||||
|
||||
// write message
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case ACIO_CMD_CLEAR:
|
||||
case ACIO_CMD_STARTUP:
|
||||
case 0x0120: // WD COMMAND
|
||||
case 0xFF: // BROADCAST
|
||||
{
|
||||
// send status 0
|
||||
auto msg = this->create_msg_status(msg_in, 0);
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark as handled
|
||||
return true;
|
||||
}
|
||||
|
||||
bool games::iidx::IIDXFMSerialHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM2") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("iidx", "Opened COM2 (FM DEVICE)");
|
||||
|
||||
// ACIO device
|
||||
acio_emu.add_device(new FMSerialDevice());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::iidx::IIDXFMSerialHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
|
||||
|
||||
// read from emu
|
||||
DWORD bytes_read = 0;
|
||||
while (bytes_read < nNumberOfBytesToRead) {
|
||||
auto cur_byte = acio_emu.read();
|
||||
|
||||
if (cur_byte.has_value()) {
|
||||
buffer[bytes_read++] = cur_byte.value();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// return amount of bytes read
|
||||
return (int) bytes_read;
|
||||
}
|
||||
|
||||
int games::iidx::IIDXFMSerialHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
|
||||
|
||||
// write to emu
|
||||
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
|
||||
acio_emu.write(buffer[i]);
|
||||
}
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::iidx::IIDXFMSerialHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::iidx::IIDXFMSerialHandle::close() {
|
||||
log_info("iidx", "Closed COM2 (FM DEVICE)");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+30
-30
@@ -1,30 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "acioemu/acioemu.h"
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
class IIDXFMSerialHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu acio_emu;
|
||||
|
||||
class FMSerialDevice : public acioemu::ACIODeviceEmu {
|
||||
private:
|
||||
uint8_t coin_counter = 0;
|
||||
|
||||
public:
|
||||
FMSerialDevice();
|
||||
|
||||
bool parse_msg(acioemu::MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
|
||||
};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "acioemu/acioemu.h"
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
class IIDXFMSerialHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu acio_emu;
|
||||
|
||||
class FMSerialDevice : public acioemu::ACIODeviceEmu {
|
||||
private:
|
||||
uint8_t coin_counter = 0;
|
||||
|
||||
public:
|
||||
FMSerialDevice();
|
||||
|
||||
bool parse_msg(acioemu::MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
|
||||
};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+248
-248
@@ -1,248 +1,248 @@
|
||||
#include "bi2x.h"
|
||||
|
||||
#include "misc/eamuse.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#include "iidx.h"
|
||||
#include "io.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
games::iidx::BI2XSerialHandle::BI2XDevice::BI2XDevice() {
|
||||
this->node_count = 1;
|
||||
}
|
||||
|
||||
bool games::iidx::BI2XSerialHandle::BI2XDevice::parse_msg(
|
||||
MessageData *msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) {
|
||||
#ifdef ACIOEMU_LOG
|
||||
log_info("iidx", "BI2X ADDR: {}, CMD: 0x{:04x}", msg_in->addr, msg_in->cmd.code);
|
||||
#endif
|
||||
|
||||
// check command
|
||||
switch (msg_in->cmd.code) {
|
||||
case ACIO_CMD_GET_VERSION: {
|
||||
|
||||
// send version data
|
||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||
this->set_version(msg, 0x03, 0, 4, 2, 0, "BI2X");
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case 0x0152: { // STATUS
|
||||
|
||||
// check input data length
|
||||
if (msg_in->cmd.data_size == 0x30) {
|
||||
|
||||
// LED TICKER
|
||||
IIDX_LED_TICKER_LOCK.lock();
|
||||
if (!IIDXIO_LED_TICKER_READONLY)
|
||||
memcpy(IIDXIO_LED_TICKER, &msg_in->cmd.raw[0x17], 9);
|
||||
IIDX_LED_TICKER_LOCK.unlock();
|
||||
|
||||
// NEON LIGHT
|
||||
bool neon_light = msg_in->cmd.raw[0x24] != 0;
|
||||
write_top_neon(neon_light ? (uint8_t) 0xFF : (uint8_t) 0);
|
||||
|
||||
// SPOT LIGHT
|
||||
uint8_t spot_light_bits = 0;
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
auto index = i > 3 ? i + 1 : i;
|
||||
if (msg_in->cmd.raw[0x20 + index] != 0)
|
||||
spot_light_bits |= 1 << i;
|
||||
}
|
||||
write_top_lamp(spot_light_bits);
|
||||
|
||||
// SWLED (DECK)
|
||||
uint16_t lamp_bits = 0;
|
||||
for (size_t i = 0; i < 14; i++) {
|
||||
if (msg_in->cmd.raw[0x07 + i] != 0)
|
||||
lamp_bits |= 1 << i;
|
||||
}
|
||||
write_lamp(lamp_bits);
|
||||
|
||||
// SWLED (PANEL)
|
||||
uint8_t led_bits = 0;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (msg_in->cmd.raw[0x03 + i] != 0)
|
||||
led_bits |= 1 << i;
|
||||
}
|
||||
write_led(led_bits);
|
||||
|
||||
// flush device output
|
||||
RI_MGR->devices_flush_output();
|
||||
}
|
||||
|
||||
// sleep - otherwise the IO thread will go too hard on the CPU
|
||||
Sleep(1);
|
||||
|
||||
// generate message
|
||||
auto msg = this->create_msg(msg_in, 0x2E);
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// player 1 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 151);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 167);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 183);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 199);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 215);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 231);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 247);
|
||||
|
||||
// player 2 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 263);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 279);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 295);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 311);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 327);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 343);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 359);
|
||||
|
||||
// player 1 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 79);
|
||||
|
||||
// player 2 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 78);
|
||||
|
||||
// VEFX
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::VEFX)))
|
||||
ARRAY_SETB(msg->cmd.raw, 77);
|
||||
|
||||
// EFFECT
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Effect)))
|
||||
ARRAY_SETB(msg->cmd.raw, 76);
|
||||
|
||||
// service
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service)))
|
||||
ARRAY_SETB(msg->cmd.raw, 10);
|
||||
|
||||
// test
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test)))
|
||||
ARRAY_SETB(msg->cmd.raw, 11);
|
||||
|
||||
// turntables
|
||||
msg->cmd.raw[16] = get_tt(0, true);
|
||||
msg->cmd.raw[17] = get_tt(1, true);
|
||||
|
||||
// slider
|
||||
msg->cmd.raw[0] |= get_slider(0) << 4;
|
||||
msg->cmd.raw[2] |= get_slider(1) << 4;
|
||||
msg->cmd.raw[4] |= get_slider(2) << 4;
|
||||
msg->cmd.raw[6] |= get_slider(3) << 4;
|
||||
msg->cmd.raw[7] |= get_slider(4) << 4;
|
||||
|
||||
// coin
|
||||
this->coin_counter += eamuse_coin_consume_stock();
|
||||
msg->cmd.raw[8] |= this->coin_counter;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* bit 9 appears to be the coin mech
|
||||
*/
|
||||
|
||||
// write message
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case ACIO_CMD_CLEAR:
|
||||
case ACIO_CMD_STARTUP:
|
||||
case 0x0120: // WD COMMAND
|
||||
case 0xFF: // BROADCAST
|
||||
{
|
||||
// send status 0
|
||||
auto msg = this->create_msg_status(msg_in, 0);
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark as handled
|
||||
return true;
|
||||
}
|
||||
|
||||
bool games::iidx::BI2XSerialHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM3") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("iidx", "Opened COM3 (BIO2)");
|
||||
|
||||
// ACIO device
|
||||
//acio_emu.add_device(new FMSerialDevice());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::iidx::BI2XSerialHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
//auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
|
||||
|
||||
// read from emu
|
||||
/*
|
||||
DWORD bytes_read = 0;
|
||||
while (bytes_read < nNumberOfBytesToRead) {
|
||||
auto cur_byte = acio_emu.read();
|
||||
|
||||
if (cur_byte.has_value()) {
|
||||
buffer[bytes_read++] = cur_byte.value();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// return amount of bytes read
|
||||
//return (int) bytes_read;
|
||||
return (int) nNumberOfBytesToRead;
|
||||
}
|
||||
|
||||
int games::iidx::BI2XSerialHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
|
||||
|
||||
log_info("iidx", "BIO2 Data: {}", bin2hex(buffer, nNumberOfBytesToWrite));
|
||||
|
||||
// write to emu
|
||||
/*
|
||||
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
|
||||
acio_emu.write(buffer[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::iidx::BI2XSerialHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::iidx::BI2XSerialHandle::close() {
|
||||
log_info("iidx", "Closed COM3 (BIO2)");
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "bi2x.h"
|
||||
|
||||
#include "misc/eamuse.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#include "iidx.h"
|
||||
#include "io.h"
|
||||
|
||||
using namespace acioemu;
|
||||
|
||||
games::iidx::BI2XSerialHandle::BI2XDevice::BI2XDevice() {
|
||||
this->node_count = 1;
|
||||
}
|
||||
|
||||
bool games::iidx::BI2XSerialHandle::BI2XDevice::parse_msg(
|
||||
MessageData *msg_in,
|
||||
circular_buffer<uint8_t> *response_buffer
|
||||
) {
|
||||
#ifdef ACIOEMU_LOG
|
||||
log_info("iidx", "BI2X ADDR: {}, CMD: 0x{:04x}", msg_in->addr, msg_in->cmd.code);
|
||||
#endif
|
||||
|
||||
// check command
|
||||
switch (msg_in->cmd.code) {
|
||||
case ACIO_CMD_GET_VERSION: {
|
||||
|
||||
// send version data
|
||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||
this->set_version(msg, 0x03, 0, 4, 2, 0, "BI2X");
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case 0x0152: { // STATUS
|
||||
|
||||
// check input data length
|
||||
if (msg_in->cmd.data_size == 0x30) {
|
||||
|
||||
// LED TICKER
|
||||
IIDX_LED_TICKER_LOCK.lock();
|
||||
if (!IIDXIO_LED_TICKER_READONLY)
|
||||
memcpy(IIDXIO_LED_TICKER, &msg_in->cmd.raw[0x17], 9);
|
||||
IIDX_LED_TICKER_LOCK.unlock();
|
||||
|
||||
// NEON LIGHT
|
||||
bool neon_light = msg_in->cmd.raw[0x24] != 0;
|
||||
write_top_neon(neon_light ? (uint8_t) 0xFF : (uint8_t) 0);
|
||||
|
||||
// SPOT LIGHT
|
||||
uint8_t spot_light_bits = 0;
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
auto index = i > 3 ? i + 1 : i;
|
||||
if (msg_in->cmd.raw[0x20 + index] != 0)
|
||||
spot_light_bits |= 1 << i;
|
||||
}
|
||||
write_top_lamp(spot_light_bits);
|
||||
|
||||
// SWLED (DECK)
|
||||
uint16_t lamp_bits = 0;
|
||||
for (size_t i = 0; i < 14; i++) {
|
||||
if (msg_in->cmd.raw[0x07 + i] != 0)
|
||||
lamp_bits |= 1 << i;
|
||||
}
|
||||
write_lamp(lamp_bits);
|
||||
|
||||
// SWLED (PANEL)
|
||||
uint8_t led_bits = 0;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (msg_in->cmd.raw[0x03 + i] != 0)
|
||||
led_bits |= 1 << i;
|
||||
}
|
||||
write_led(led_bits);
|
||||
|
||||
// flush device output
|
||||
RI_MGR->devices_flush_output();
|
||||
}
|
||||
|
||||
// sleep - otherwise the IO thread will go too hard on the CPU
|
||||
Sleep(1);
|
||||
|
||||
// generate message
|
||||
auto msg = this->create_msg(msg_in, 0x2E);
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// player 1 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 151);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 167);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 183);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 199);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 215);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 231);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 247);
|
||||
|
||||
// player 2 buttons
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_1)))
|
||||
ARRAY_SETB(msg->cmd.raw, 263);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_2)))
|
||||
ARRAY_SETB(msg->cmd.raw, 279);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_3)))
|
||||
ARRAY_SETB(msg->cmd.raw, 295);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_4)))
|
||||
ARRAY_SETB(msg->cmd.raw, 311);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_5)))
|
||||
ARRAY_SETB(msg->cmd.raw, 327);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_6)))
|
||||
ARRAY_SETB(msg->cmd.raw, 343);
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_7)))
|
||||
ARRAY_SETB(msg->cmd.raw, 359);
|
||||
|
||||
// player 1 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P1_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 79);
|
||||
|
||||
// player 2 start
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::P2_Start)))
|
||||
ARRAY_SETB(msg->cmd.raw, 78);
|
||||
|
||||
// VEFX
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::VEFX)))
|
||||
ARRAY_SETB(msg->cmd.raw, 77);
|
||||
|
||||
// EFFECT
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Effect)))
|
||||
ARRAY_SETB(msg->cmd.raw, 76);
|
||||
|
||||
// service
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service)))
|
||||
ARRAY_SETB(msg->cmd.raw, 10);
|
||||
|
||||
// test
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test)))
|
||||
ARRAY_SETB(msg->cmd.raw, 11);
|
||||
|
||||
// turntables
|
||||
msg->cmd.raw[16] = get_tt(0, true);
|
||||
msg->cmd.raw[17] = get_tt(1, true);
|
||||
|
||||
// slider
|
||||
msg->cmd.raw[0] |= get_slider(0) << 4;
|
||||
msg->cmd.raw[2] |= get_slider(1) << 4;
|
||||
msg->cmd.raw[4] |= get_slider(2) << 4;
|
||||
msg->cmd.raw[6] |= get_slider(3) << 4;
|
||||
msg->cmd.raw[7] |= get_slider(4) << 4;
|
||||
|
||||
// coin
|
||||
this->coin_counter += eamuse_coin_consume_stock();
|
||||
msg->cmd.raw[8] |= this->coin_counter;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* bit 9 appears to be the coin mech
|
||||
*/
|
||||
|
||||
// write message
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
case ACIO_CMD_CLEAR:
|
||||
case ACIO_CMD_STARTUP:
|
||||
case 0x0120: // WD COMMAND
|
||||
case 0xFF: // BROADCAST
|
||||
{
|
||||
// send status 0
|
||||
auto msg = this->create_msg_status(msg_in, 0);
|
||||
write_msg(msg, response_buffer);
|
||||
delete msg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark as handled
|
||||
return true;
|
||||
}
|
||||
|
||||
bool games::iidx::BI2XSerialHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM3") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("iidx", "Opened COM3 (BIO2)");
|
||||
|
||||
// ACIO device
|
||||
//acio_emu.add_device(new FMSerialDevice());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::iidx::BI2XSerialHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
//auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
|
||||
|
||||
// read from emu
|
||||
/*
|
||||
DWORD bytes_read = 0;
|
||||
while (bytes_read < nNumberOfBytesToRead) {
|
||||
auto cur_byte = acio_emu.read();
|
||||
|
||||
if (cur_byte.has_value()) {
|
||||
buffer[bytes_read++] = cur_byte.value();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// return amount of bytes read
|
||||
//return (int) bytes_read;
|
||||
return (int) nNumberOfBytesToRead;
|
||||
}
|
||||
|
||||
int games::iidx::BI2XSerialHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
|
||||
|
||||
log_info("iidx", "BIO2 Data: {}", bin2hex(buffer, nNumberOfBytesToWrite));
|
||||
|
||||
// write to emu
|
||||
/*
|
||||
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
|
||||
acio_emu.write(buffer[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
// return all data written
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::iidx::BI2XSerialHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::iidx::BI2XSerialHandle::close() {
|
||||
log_info("iidx", "Closed COM3 (BIO2)");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+30
-30
@@ -1,30 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "acioemu/acioemu.h"
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
class BI2XSerialHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu acio_emu;
|
||||
|
||||
class BI2XDevice : public acioemu::ACIODeviceEmu {
|
||||
private:
|
||||
uint8_t coin_counter = 0;
|
||||
|
||||
public:
|
||||
BI2XDevice();
|
||||
|
||||
bool parse_msg(acioemu::MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
|
||||
};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "acioemu/acioemu.h"
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
class BI2XSerialHandle : public CustomHandle {
|
||||
private:
|
||||
acioemu::ACIOEmu acio_emu;
|
||||
|
||||
class BI2XDevice : public acioemu::ACIODeviceEmu {
|
||||
private:
|
||||
uint8_t coin_counter = 0;
|
||||
|
||||
public:
|
||||
BI2XDevice();
|
||||
|
||||
bool parse_msg(acioemu::MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
|
||||
};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
void bi2x_hook_init();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
void bi2x_hook_init();
|
||||
}
|
||||
|
||||
+277
-277
@@ -1,277 +1,277 @@
|
||||
#include "ezusb.h"
|
||||
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "iidx.h"
|
||||
#include "io.h"
|
||||
|
||||
bool games::iidx::EZUSBHandle::open(LPCWSTR lpFileName) {
|
||||
return wcscmp(lpFileName, L"\\\\.\\Ezusb-0") == 0;
|
||||
}
|
||||
|
||||
int games::iidx::EZUSBHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
log_warning("iidx", "EZUSB invalid read operation!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int games::iidx::EZUSBHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
log_warning("iidx", "EZUSB invalid write operation!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int games::iidx::EZUSBHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
|
||||
// initialize check
|
||||
if (!init) {
|
||||
// TODO: initialize input
|
||||
init = true;
|
||||
init_success = true;
|
||||
}
|
||||
|
||||
if (init_success) {
|
||||
switch (dwIoControlCode) {
|
||||
|
||||
// device descriptor
|
||||
case 0x222004:
|
||||
|
||||
// check output buffer size
|
||||
if (nOutBufferSize >= 18) {
|
||||
|
||||
// set descriptor data
|
||||
*((char *) lpOutBuffer + 8) = 0x47;
|
||||
*((char *) lpOutBuffer + 9) = 0x05;
|
||||
*((char *) lpOutBuffer + 10) = 0x35;
|
||||
*((char *) lpOutBuffer + 11) = 0x22;
|
||||
|
||||
// return output buffer size
|
||||
return 18;
|
||||
|
||||
} else // buffer too small
|
||||
return -1;
|
||||
|
||||
// vendor
|
||||
case 0x222014:
|
||||
|
||||
// check input buffer size
|
||||
if (nInBufferSize >= 10)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
// data read
|
||||
case 0x22204E:
|
||||
|
||||
// check input buffer size
|
||||
if (nInBufferSize < 4)
|
||||
return -1;
|
||||
|
||||
// read 0x01
|
||||
if (*(DWORD *) lpInBuffer == 0x01) {
|
||||
*((DWORD *) lpOutBuffer) = get_pad();
|
||||
*((char *) lpOutBuffer + 4) = FPGA_CMD_STATE;
|
||||
*((char *) lpOutBuffer + 7) = get_tt(1, false);
|
||||
*((char *) lpOutBuffer + 8) = get_tt(0, false);
|
||||
*((char *) lpOutBuffer + 9) = FPGA_COUNTER++;
|
||||
*((char *) lpOutBuffer + 11) = 1; // 1 success; 0 failed
|
||||
*((char *) lpOutBuffer + 13) = get_slider(1) << 4 | get_slider(0);
|
||||
*((char *) lpOutBuffer + 14) = get_slider(3) << 4 | get_slider(2);
|
||||
*((char *) lpOutBuffer + 15) = get_slider(4);
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// read 0x03
|
||||
if (*(DWORD *) lpInBuffer == 0x03) {
|
||||
|
||||
// check output buffer size
|
||||
if (nOutBufferSize < 64)
|
||||
return -1;
|
||||
|
||||
// null node read
|
||||
if (FPGA_CUR_NODE == 0) {
|
||||
*(int *) lpOutBuffer = 0;
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// check node size
|
||||
if (FPGA_CUR_NODE != 64)
|
||||
return -1;
|
||||
|
||||
// check command
|
||||
if (SRAM_CMD != 2)
|
||||
return -1;
|
||||
|
||||
// check if page exists
|
||||
if (SRAM_PAGE >= 12)
|
||||
return -1;
|
||||
|
||||
// write page
|
||||
*((char *) lpOutBuffer + 1) = (char) SRAM_PAGE;
|
||||
|
||||
// copy page
|
||||
memcpy((uint8_t*) lpOutBuffer + 2, SRAM_DATA + 62 * SRAM_PAGE, 62);
|
||||
SRAM_PAGE++;
|
||||
|
||||
// write node
|
||||
*((char *) lpOutBuffer) = (char) FPGA_CUR_NODE;
|
||||
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// unknown
|
||||
return -1;
|
||||
|
||||
// data write
|
||||
case 0x222051:
|
||||
|
||||
// check in buffer size
|
||||
if (nInBufferSize < 4)
|
||||
return -1;
|
||||
|
||||
// write 0x00
|
||||
if (*(DWORD *) lpInBuffer == 0x00) {
|
||||
|
||||
// check out buffer size
|
||||
if (nOutBufferSize < 10)
|
||||
return -1;
|
||||
|
||||
// get data
|
||||
uint16_t lamp = *((uint16_t *) lpOutBuffer + 0);
|
||||
uint8_t led = *((uint8_t *) lpOutBuffer + 6);
|
||||
uint8_t top_lamp = *((uint8_t *) lpOutBuffer + 8);
|
||||
uint8_t top_neon = *((uint8_t *) lpOutBuffer + 9);
|
||||
|
||||
// process data
|
||||
write_lamp(lamp);
|
||||
write_led(led);
|
||||
write_top_lamp(top_lamp);
|
||||
write_top_neon(top_neon);
|
||||
|
||||
// flush device output
|
||||
RI_MGR->devices_flush_output();
|
||||
|
||||
char write_node = *((char *) lpOutBuffer + 2);
|
||||
if (write_node != 0) {
|
||||
switch (write_node) {
|
||||
case 4:
|
||||
switch (*((char *) lpOutBuffer + 3)) {
|
||||
case 1: // init
|
||||
FPGA_CMD_STATE = 65;
|
||||
break;
|
||||
case 2: // check
|
||||
FPGA_CMD_STATE = 66;
|
||||
break;
|
||||
case 3: // write
|
||||
{
|
||||
//int write_data = *((short *) lpOutBuffer + 4);
|
||||
break;
|
||||
}
|
||||
case 4: // write done
|
||||
FPGA_CMD_STATE = 67;
|
||||
break;
|
||||
default: // unknown
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 9:
|
||||
break;
|
||||
case 64: // SRAM command
|
||||
SRAM_CMD = *((char *) lpOutBuffer + 3);
|
||||
switch (SRAM_CMD) {
|
||||
case 2: // read
|
||||
SRAM_PAGE = 0;
|
||||
break;
|
||||
case 3: // write
|
||||
SRAM_PAGE = 0;
|
||||
break;
|
||||
case 4: // done
|
||||
break;
|
||||
default: // unknown
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default: // unknown node
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// save node
|
||||
FPGA_CUR_NODE = write_node;
|
||||
|
||||
// return out buffer size
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// write 0x02
|
||||
if (*(DWORD *) lpInBuffer == 0x02) {
|
||||
|
||||
// check out buffer size
|
||||
if (nOutBufferSize < 64)
|
||||
return -1;
|
||||
|
||||
int cmd = *(char *) lpOutBuffer;
|
||||
switch (cmd) {
|
||||
case 0: // null write
|
||||
break;
|
||||
case 4: // unknown
|
||||
break;
|
||||
case 5: // 16seg
|
||||
{
|
||||
// write to status
|
||||
IIDX_LED_TICKER_LOCK.lock();
|
||||
if (!IIDXIO_LED_TICKER_READONLY)
|
||||
memcpy(IIDXIO_LED_TICKER, (char *) lpOutBuffer + 2, 9);
|
||||
IIDX_LED_TICKER_LOCK.unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
case 64: // SRAM write
|
||||
{
|
||||
// get page
|
||||
static char page = *((char *) lpOutBuffer + 1);
|
||||
page = (char) SRAM_PAGE++;
|
||||
|
||||
// check page
|
||||
if (page >= 12)
|
||||
return -1;
|
||||
|
||||
// copy data
|
||||
memcpy(SRAM_DATA + 62 * page, (uint8_t*) lpOutBuffer + 2, 62);
|
||||
|
||||
break;
|
||||
}
|
||||
default: // unknown node
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return out buffer size
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// unknown write
|
||||
return -1;
|
||||
|
||||
// firmware upload
|
||||
case 0x22206D:
|
||||
|
||||
// check buffer size
|
||||
if (nInBufferSize >= 2)
|
||||
return (int) nOutBufferSize;
|
||||
else
|
||||
return -1;
|
||||
|
||||
// unknown control code
|
||||
default:
|
||||
log_warning("iidx", "EZUSB unknown: {}", dwIoControlCode);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::iidx::EZUSBHandle::close() {
|
||||
return true;
|
||||
}
|
||||
#include "ezusb.h"
|
||||
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "iidx.h"
|
||||
#include "io.h"
|
||||
|
||||
bool games::iidx::EZUSBHandle::open(LPCWSTR lpFileName) {
|
||||
return wcscmp(lpFileName, L"\\\\.\\Ezusb-0") == 0;
|
||||
}
|
||||
|
||||
int games::iidx::EZUSBHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
log_warning("iidx", "EZUSB invalid read operation!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int games::iidx::EZUSBHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
log_warning("iidx", "EZUSB invalid write operation!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int games::iidx::EZUSBHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
|
||||
// initialize check
|
||||
if (!init) {
|
||||
// TODO: initialize input
|
||||
init = true;
|
||||
init_success = true;
|
||||
}
|
||||
|
||||
if (init_success) {
|
||||
switch (dwIoControlCode) {
|
||||
|
||||
// device descriptor
|
||||
case 0x222004:
|
||||
|
||||
// check output buffer size
|
||||
if (nOutBufferSize >= 18) {
|
||||
|
||||
// set descriptor data
|
||||
*((char *) lpOutBuffer + 8) = 0x47;
|
||||
*((char *) lpOutBuffer + 9) = 0x05;
|
||||
*((char *) lpOutBuffer + 10) = 0x35;
|
||||
*((char *) lpOutBuffer + 11) = 0x22;
|
||||
|
||||
// return output buffer size
|
||||
return 18;
|
||||
|
||||
} else // buffer too small
|
||||
return -1;
|
||||
|
||||
// vendor
|
||||
case 0x222014:
|
||||
|
||||
// check input buffer size
|
||||
if (nInBufferSize >= 10)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
// data read
|
||||
case 0x22204E:
|
||||
|
||||
// check input buffer size
|
||||
if (nInBufferSize < 4)
|
||||
return -1;
|
||||
|
||||
// read 0x01
|
||||
if (*(DWORD *) lpInBuffer == 0x01) {
|
||||
*((DWORD *) lpOutBuffer) = get_pad();
|
||||
*((char *) lpOutBuffer + 4) = FPGA_CMD_STATE;
|
||||
*((char *) lpOutBuffer + 7) = get_tt(1, false);
|
||||
*((char *) lpOutBuffer + 8) = get_tt(0, false);
|
||||
*((char *) lpOutBuffer + 9) = FPGA_COUNTER++;
|
||||
*((char *) lpOutBuffer + 11) = 1; // 1 success; 0 failed
|
||||
*((char *) lpOutBuffer + 13) = get_slider(1) << 4 | get_slider(0);
|
||||
*((char *) lpOutBuffer + 14) = get_slider(3) << 4 | get_slider(2);
|
||||
*((char *) lpOutBuffer + 15) = get_slider(4);
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// read 0x03
|
||||
if (*(DWORD *) lpInBuffer == 0x03) {
|
||||
|
||||
// check output buffer size
|
||||
if (nOutBufferSize < 64)
|
||||
return -1;
|
||||
|
||||
// null node read
|
||||
if (FPGA_CUR_NODE == 0) {
|
||||
*(int *) lpOutBuffer = 0;
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// check node size
|
||||
if (FPGA_CUR_NODE != 64)
|
||||
return -1;
|
||||
|
||||
// check command
|
||||
if (SRAM_CMD != 2)
|
||||
return -1;
|
||||
|
||||
// check if page exists
|
||||
if (SRAM_PAGE >= 12)
|
||||
return -1;
|
||||
|
||||
// write page
|
||||
*((char *) lpOutBuffer + 1) = (char) SRAM_PAGE;
|
||||
|
||||
// copy page
|
||||
memcpy((uint8_t*) lpOutBuffer + 2, SRAM_DATA + 62 * SRAM_PAGE, 62);
|
||||
SRAM_PAGE++;
|
||||
|
||||
// write node
|
||||
*((char *) lpOutBuffer) = (char) FPGA_CUR_NODE;
|
||||
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// unknown
|
||||
return -1;
|
||||
|
||||
// data write
|
||||
case 0x222051:
|
||||
|
||||
// check in buffer size
|
||||
if (nInBufferSize < 4)
|
||||
return -1;
|
||||
|
||||
// write 0x00
|
||||
if (*(DWORD *) lpInBuffer == 0x00) {
|
||||
|
||||
// check out buffer size
|
||||
if (nOutBufferSize < 10)
|
||||
return -1;
|
||||
|
||||
// get data
|
||||
uint16_t lamp = *((uint16_t *) lpOutBuffer + 0);
|
||||
uint8_t led = *((uint8_t *) lpOutBuffer + 6);
|
||||
uint8_t top_lamp = *((uint8_t *) lpOutBuffer + 8);
|
||||
uint8_t top_neon = *((uint8_t *) lpOutBuffer + 9);
|
||||
|
||||
// process data
|
||||
write_lamp(lamp);
|
||||
write_led(led);
|
||||
write_top_lamp(top_lamp);
|
||||
write_top_neon(top_neon);
|
||||
|
||||
// flush device output
|
||||
RI_MGR->devices_flush_output();
|
||||
|
||||
char write_node = *((char *) lpOutBuffer + 2);
|
||||
if (write_node != 0) {
|
||||
switch (write_node) {
|
||||
case 4:
|
||||
switch (*((char *) lpOutBuffer + 3)) {
|
||||
case 1: // init
|
||||
FPGA_CMD_STATE = 65;
|
||||
break;
|
||||
case 2: // check
|
||||
FPGA_CMD_STATE = 66;
|
||||
break;
|
||||
case 3: // write
|
||||
{
|
||||
//int write_data = *((short *) lpOutBuffer + 4);
|
||||
break;
|
||||
}
|
||||
case 4: // write done
|
||||
FPGA_CMD_STATE = 67;
|
||||
break;
|
||||
default: // unknown
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 9:
|
||||
break;
|
||||
case 64: // SRAM command
|
||||
SRAM_CMD = *((char *) lpOutBuffer + 3);
|
||||
switch (SRAM_CMD) {
|
||||
case 2: // read
|
||||
SRAM_PAGE = 0;
|
||||
break;
|
||||
case 3: // write
|
||||
SRAM_PAGE = 0;
|
||||
break;
|
||||
case 4: // done
|
||||
break;
|
||||
default: // unknown
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default: // unknown node
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// save node
|
||||
FPGA_CUR_NODE = write_node;
|
||||
|
||||
// return out buffer size
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// write 0x02
|
||||
if (*(DWORD *) lpInBuffer == 0x02) {
|
||||
|
||||
// check out buffer size
|
||||
if (nOutBufferSize < 64)
|
||||
return -1;
|
||||
|
||||
int cmd = *(char *) lpOutBuffer;
|
||||
switch (cmd) {
|
||||
case 0: // null write
|
||||
break;
|
||||
case 4: // unknown
|
||||
break;
|
||||
case 5: // 16seg
|
||||
{
|
||||
// write to status
|
||||
IIDX_LED_TICKER_LOCK.lock();
|
||||
if (!IIDXIO_LED_TICKER_READONLY)
|
||||
memcpy(IIDXIO_LED_TICKER, (char *) lpOutBuffer + 2, 9);
|
||||
IIDX_LED_TICKER_LOCK.unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
case 64: // SRAM write
|
||||
{
|
||||
// get page
|
||||
static char page = *((char *) lpOutBuffer + 1);
|
||||
page = (char) SRAM_PAGE++;
|
||||
|
||||
// check page
|
||||
if (page >= 12)
|
||||
return -1;
|
||||
|
||||
// copy data
|
||||
memcpy(SRAM_DATA + 62 * page, (uint8_t*) lpOutBuffer + 2, 62);
|
||||
|
||||
break;
|
||||
}
|
||||
default: // unknown node
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return out buffer size
|
||||
return (int) nOutBufferSize;
|
||||
}
|
||||
|
||||
// unknown write
|
||||
return -1;
|
||||
|
||||
// firmware upload
|
||||
case 0x22206D:
|
||||
|
||||
// check buffer size
|
||||
if (nInBufferSize >= 2)
|
||||
return (int) nOutBufferSize;
|
||||
else
|
||||
return -1;
|
||||
|
||||
// unknown control code
|
||||
default:
|
||||
log_warning("iidx", "EZUSB unknown: {}", dwIoControlCode);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::iidx::EZUSBHandle::close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
+32
-32
@@ -1,32 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
class EZUSBHandle : public CustomHandle {
|
||||
private:
|
||||
|
||||
// state
|
||||
bool init = false;
|
||||
bool init_success = false;
|
||||
char FPGA_CMD_STATE = 67;
|
||||
char FPGA_COUNTER = 0;
|
||||
int FPGA_CUR_NODE = 0;
|
||||
int SRAM_CMD = 0;
|
||||
int SRAM_PAGE = 0;
|
||||
char SRAM_DATA[62 * 12]{};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
class EZUSBHandle : public CustomHandle {
|
||||
private:
|
||||
|
||||
// state
|
||||
bool init = false;
|
||||
bool init_success = false;
|
||||
char FPGA_CMD_STATE = 67;
|
||||
char FPGA_COUNTER = 0;
|
||||
int FPGA_CUR_NODE = 0;
|
||||
int SRAM_CMD = 0;
|
||||
int SRAM_PAGE = 0;
|
||||
char SRAM_DATA[62 * 12]{};
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+161
-161
@@ -1,161 +1,161 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
P1_1,
|
||||
P1_2,
|
||||
P1_3,
|
||||
P1_4,
|
||||
P1_5,
|
||||
P1_6,
|
||||
P1_7,
|
||||
P1_TTPlus,
|
||||
P1_TTMinus,
|
||||
P1_TTPlusMinus,
|
||||
P1_Start,
|
||||
P2_1,
|
||||
P2_2,
|
||||
P2_3,
|
||||
P2_4,
|
||||
P2_5,
|
||||
P2_6,
|
||||
P2_7,
|
||||
P2_TTPlus,
|
||||
P2_TTMinus,
|
||||
P2_TTPlusMinus,
|
||||
P2_Start,
|
||||
Effect,
|
||||
VEFX,
|
||||
P1_Headphone,
|
||||
P2_Headphone,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
TT_P1,
|
||||
TT_P2,
|
||||
VEFX,
|
||||
LowEQ,
|
||||
HiEQ,
|
||||
Filter,
|
||||
PlayVolume
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
P1_1,
|
||||
P1_2,
|
||||
P1_3,
|
||||
P1_4,
|
||||
P1_5,
|
||||
P1_6,
|
||||
P1_7,
|
||||
P2_1,
|
||||
P2_2,
|
||||
P2_3,
|
||||
P2_4,
|
||||
P2_5,
|
||||
P2_6,
|
||||
P2_7,
|
||||
P1_Start,
|
||||
P2_Start,
|
||||
VEFX,
|
||||
Effect,
|
||||
SpotLight1,
|
||||
SpotLight2,
|
||||
SpotLight3,
|
||||
SpotLight4,
|
||||
SpotLight5,
|
||||
SpotLight6,
|
||||
SpotLight7,
|
||||
SpotLight8,
|
||||
NeonLamp,
|
||||
WooferR,
|
||||
WooferG,
|
||||
WooferB,
|
||||
ICCR_P1_R,
|
||||
ICCR_P1_G,
|
||||
ICCR_P1_B,
|
||||
ICCR_P2_R,
|
||||
ICCR_P2_G,
|
||||
ICCR_P2_B,
|
||||
TT_P1_R,
|
||||
TT_P1_G,
|
||||
TT_P1_B,
|
||||
TT_P2_R,
|
||||
TT_P2_G,
|
||||
TT_P2_B,
|
||||
TT_P1_Resistance,
|
||||
TT_P2_Resistance,
|
||||
StageLeftAvgR,
|
||||
StageLeftAvgG,
|
||||
StageLeftAvgB,
|
||||
StageRightAvgR,
|
||||
StageRightAvgG,
|
||||
StageRightAvgB,
|
||||
CabinetLeftAvgR,
|
||||
CabinetLeftAvgG,
|
||||
CabinetLeftAvgB,
|
||||
CabinetRightAvgR,
|
||||
CabinetRightAvgG,
|
||||
CabinetRightAvgB,
|
||||
ControlPanelUnderAvgR,
|
||||
ControlPanelUnderAvgG,
|
||||
ControlPanelUnderAvgB,
|
||||
CeilingLeftAvgR,
|
||||
CeilingLeftAvgG,
|
||||
CeilingLeftAvgB,
|
||||
TitleLeftAvgR,
|
||||
TitleLeftAvgG,
|
||||
TitleLeftAvgB,
|
||||
TitleRightAvgR,
|
||||
TitleRightAvgG,
|
||||
TitleRightAvgB,
|
||||
CeilingRightAvgR,
|
||||
CeilingRightAvgG,
|
||||
CeilingRightAvgB,
|
||||
TouchPanelLeftAvgR,
|
||||
TouchPanelLeftAvgG,
|
||||
TouchPanelLeftAvgB,
|
||||
TouchPanelRightAvgR,
|
||||
TouchPanelRightAvgG,
|
||||
TouchPanelRightAvgB,
|
||||
SidePanelLeftInnerAvgR,
|
||||
SidePanelLeftInnerAvgG,
|
||||
SidePanelLeftInnerAvgB,
|
||||
SidePanelLeftOuterAvgR,
|
||||
SidePanelLeftOuterAvgG,
|
||||
SidePanelLeftOuterAvgB,
|
||||
SidePanelLeftAvgR,
|
||||
SidePanelLeftAvgG,
|
||||
SidePanelLeftAvgB,
|
||||
SidePanelRightOuterAvgR,
|
||||
SidePanelRightOuterAvgG,
|
||||
SidePanelRightOuterAvgB,
|
||||
SidePanelRightInnerAvgR,
|
||||
SidePanelRightInnerAvgG,
|
||||
SidePanelRightInnerAvgB,
|
||||
SidePanelRightAvgR,
|
||||
SidePanelRightAvgG,
|
||||
SidePanelRightAvgB,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::iidx {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
P1_1,
|
||||
P1_2,
|
||||
P1_3,
|
||||
P1_4,
|
||||
P1_5,
|
||||
P1_6,
|
||||
P1_7,
|
||||
P1_TTPlus,
|
||||
P1_TTMinus,
|
||||
P1_TTPlusMinus,
|
||||
P1_Start,
|
||||
P2_1,
|
||||
P2_2,
|
||||
P2_3,
|
||||
P2_4,
|
||||
P2_5,
|
||||
P2_6,
|
||||
P2_7,
|
||||
P2_TTPlus,
|
||||
P2_TTMinus,
|
||||
P2_TTPlusMinus,
|
||||
P2_Start,
|
||||
Effect,
|
||||
VEFX,
|
||||
P1_Headphone,
|
||||
P2_Headphone,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
TT_P1,
|
||||
TT_P2,
|
||||
VEFX,
|
||||
LowEQ,
|
||||
HiEQ,
|
||||
Filter,
|
||||
PlayVolume
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
P1_1,
|
||||
P1_2,
|
||||
P1_3,
|
||||
P1_4,
|
||||
P1_5,
|
||||
P1_6,
|
||||
P1_7,
|
||||
P2_1,
|
||||
P2_2,
|
||||
P2_3,
|
||||
P2_4,
|
||||
P2_5,
|
||||
P2_6,
|
||||
P2_7,
|
||||
P1_Start,
|
||||
P2_Start,
|
||||
VEFX,
|
||||
Effect,
|
||||
SpotLight1,
|
||||
SpotLight2,
|
||||
SpotLight3,
|
||||
SpotLight4,
|
||||
SpotLight5,
|
||||
SpotLight6,
|
||||
SpotLight7,
|
||||
SpotLight8,
|
||||
NeonLamp,
|
||||
WooferR,
|
||||
WooferG,
|
||||
WooferB,
|
||||
ICCR_P1_R,
|
||||
ICCR_P1_G,
|
||||
ICCR_P1_B,
|
||||
ICCR_P2_R,
|
||||
ICCR_P2_G,
|
||||
ICCR_P2_B,
|
||||
TT_P1_R,
|
||||
TT_P1_G,
|
||||
TT_P1_B,
|
||||
TT_P2_R,
|
||||
TT_P2_G,
|
||||
TT_P2_B,
|
||||
TT_P1_Resistance,
|
||||
TT_P2_Resistance,
|
||||
StageLeftAvgR,
|
||||
StageLeftAvgG,
|
||||
StageLeftAvgB,
|
||||
StageRightAvgR,
|
||||
StageRightAvgG,
|
||||
StageRightAvgB,
|
||||
CabinetLeftAvgR,
|
||||
CabinetLeftAvgG,
|
||||
CabinetLeftAvgB,
|
||||
CabinetRightAvgR,
|
||||
CabinetRightAvgG,
|
||||
CabinetRightAvgB,
|
||||
ControlPanelUnderAvgR,
|
||||
ControlPanelUnderAvgG,
|
||||
ControlPanelUnderAvgB,
|
||||
CeilingLeftAvgR,
|
||||
CeilingLeftAvgG,
|
||||
CeilingLeftAvgB,
|
||||
TitleLeftAvgR,
|
||||
TitleLeftAvgG,
|
||||
TitleLeftAvgB,
|
||||
TitleRightAvgR,
|
||||
TitleRightAvgG,
|
||||
TitleRightAvgB,
|
||||
CeilingRightAvgR,
|
||||
CeilingRightAvgG,
|
||||
CeilingRightAvgB,
|
||||
TouchPanelLeftAvgR,
|
||||
TouchPanelLeftAvgG,
|
||||
TouchPanelLeftAvgB,
|
||||
TouchPanelRightAvgR,
|
||||
TouchPanelRightAvgG,
|
||||
TouchPanelRightAvgB,
|
||||
SidePanelLeftInnerAvgR,
|
||||
SidePanelLeftInnerAvgG,
|
||||
SidePanelLeftInnerAvgB,
|
||||
SidePanelLeftOuterAvgR,
|
||||
SidePanelLeftOuterAvgG,
|
||||
SidePanelLeftOuterAvgB,
|
||||
SidePanelLeftAvgR,
|
||||
SidePanelLeftAvgG,
|
||||
SidePanelLeftAvgB,
|
||||
SidePanelRightOuterAvgR,
|
||||
SidePanelRightOuterAvgG,
|
||||
SidePanelRightOuterAvgB,
|
||||
SidePanelRightInnerAvgR,
|
||||
SidePanelRightInnerAvgG,
|
||||
SidePanelRightInnerAvgB,
|
||||
SidePanelRightAvgR,
|
||||
SidePanelRightAvgG,
|
||||
SidePanelRightAvgB,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+63
-63
@@ -1,63 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games {
|
||||
|
||||
namespace OverlayButtons {
|
||||
enum {
|
||||
InsertCoin,
|
||||
ToggleConfig,
|
||||
ToggleVirtualKeypadP1,
|
||||
ToggleVirtualKeypadP2,
|
||||
ToggleCardManager,
|
||||
ToggleLog,
|
||||
ToggleControl,
|
||||
TogglePatchManager,
|
||||
ToggleSubScreen,
|
||||
ToggleVRControl,
|
||||
ToggleOverlay,
|
||||
NavigatorActivate,
|
||||
NavigatorCancel,
|
||||
NavigatorUp,
|
||||
NavigatorDown,
|
||||
NavigatorLeft,
|
||||
NavigatorRight,
|
||||
Screenshot,
|
||||
HotkeyEnable1,
|
||||
HotkeyEnable2,
|
||||
HotkeyToggle,
|
||||
ScreenResize,
|
||||
ToggleScreenResize,
|
||||
};
|
||||
}
|
||||
|
||||
namespace KeypadButtons {
|
||||
enum {
|
||||
Keypad0,
|
||||
Keypad1,
|
||||
Keypad2,
|
||||
Keypad3,
|
||||
Keypad4,
|
||||
Keypad5,
|
||||
Keypad6,
|
||||
Keypad7,
|
||||
Keypad8,
|
||||
Keypad9,
|
||||
Keypad00,
|
||||
KeypadDecimal,
|
||||
InsertCard,
|
||||
Size,
|
||||
};
|
||||
}
|
||||
|
||||
const std::vector<std::string> &get_games();
|
||||
std::vector<Button> *get_buttons(const std::string &game);
|
||||
std::vector<Button> *get_buttons_keypads(const std::string &game);
|
||||
std::vector<Button> *get_buttons_overlay(const std::string &game);
|
||||
std::vector<Analog> *get_analogs(const std::string &game);
|
||||
std::vector<Light> *get_lights(const std::string &game);
|
||||
std::vector<Option> *get_options(const std::string &game);
|
||||
std::vector<std::string> *get_game_file_hints(const std::string &game);
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games {
|
||||
|
||||
namespace OverlayButtons {
|
||||
enum {
|
||||
InsertCoin,
|
||||
ToggleConfig,
|
||||
ToggleVirtualKeypadP1,
|
||||
ToggleVirtualKeypadP2,
|
||||
ToggleCardManager,
|
||||
ToggleLog,
|
||||
ToggleControl,
|
||||
TogglePatchManager,
|
||||
ToggleSubScreen,
|
||||
ToggleVRControl,
|
||||
ToggleOverlay,
|
||||
NavigatorActivate,
|
||||
NavigatorCancel,
|
||||
NavigatorUp,
|
||||
NavigatorDown,
|
||||
NavigatorLeft,
|
||||
NavigatorRight,
|
||||
Screenshot,
|
||||
HotkeyEnable1,
|
||||
HotkeyEnable2,
|
||||
HotkeyToggle,
|
||||
ScreenResize,
|
||||
ToggleScreenResize,
|
||||
};
|
||||
}
|
||||
|
||||
namespace KeypadButtons {
|
||||
enum {
|
||||
Keypad0,
|
||||
Keypad1,
|
||||
Keypad2,
|
||||
Keypad3,
|
||||
Keypad4,
|
||||
Keypad5,
|
||||
Keypad6,
|
||||
Keypad7,
|
||||
Keypad8,
|
||||
Keypad9,
|
||||
Keypad00,
|
||||
KeypadDecimal,
|
||||
InsertCard,
|
||||
Size,
|
||||
};
|
||||
}
|
||||
|
||||
const std::vector<std::string> &get_games();
|
||||
std::vector<Button> *get_buttons(const std::string &game);
|
||||
std::vector<Button> *get_buttons_keypads(const std::string &game);
|
||||
std::vector<Button> *get_buttons_overlay(const std::string &game);
|
||||
std::vector<Analog> *get_analogs(const std::string &game);
|
||||
std::vector<Light> *get_lights(const std::string &game);
|
||||
std::vector<Option> *get_options(const std::string &game);
|
||||
std::vector<std::string> *get_game_file_hints(const std::string &game);
|
||||
}
|
||||
|
||||
+66
-66
@@ -1,66 +1,66 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::jb::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Jubeat");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Button 1",
|
||||
"Button 2",
|
||||
"Button 3",
|
||||
"Button 4",
|
||||
"Button 5",
|
||||
"Button 6",
|
||||
"Button 7",
|
||||
"Button 8",
|
||||
"Button 9",
|
||||
"Button 10",
|
||||
"Button 11",
|
||||
"Button 12",
|
||||
"Button 13",
|
||||
"Button 14",
|
||||
"Button 15",
|
||||
"Button 16"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::jb::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Jubeat");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Panel Front R",
|
||||
"Panel Front G",
|
||||
"Panel Front B",
|
||||
"Panel Title R",
|
||||
"Panel Title G",
|
||||
"Panel Title B",
|
||||
"Panel Top R",
|
||||
"Panel Top G",
|
||||
"Panel Top B",
|
||||
"Panel Left R",
|
||||
"Panel Left G",
|
||||
"Panel Left B",
|
||||
"Panel Right R",
|
||||
"Panel Right G",
|
||||
"Panel Right B",
|
||||
"Panel Woofer R",
|
||||
"Panel Woofer G",
|
||||
"Panel Woofer B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::jb::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Jubeat");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Button 1",
|
||||
"Button 2",
|
||||
"Button 3",
|
||||
"Button 4",
|
||||
"Button 5",
|
||||
"Button 6",
|
||||
"Button 7",
|
||||
"Button 8",
|
||||
"Button 9",
|
||||
"Button 10",
|
||||
"Button 11",
|
||||
"Button 12",
|
||||
"Button 13",
|
||||
"Button 14",
|
||||
"Button 15",
|
||||
"Button 16"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::jb::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Jubeat");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Panel Front R",
|
||||
"Panel Front G",
|
||||
"Panel Front B",
|
||||
"Panel Title R",
|
||||
"Panel Title G",
|
||||
"Panel Title B",
|
||||
"Panel Top R",
|
||||
"Panel Top G",
|
||||
"Panel Top B",
|
||||
"Panel Left R",
|
||||
"Panel Left G",
|
||||
"Panel Left B",
|
||||
"Panel Right R",
|
||||
"Panel Right G",
|
||||
"Panel Right B",
|
||||
"Panel Woofer R",
|
||||
"Panel Woofer G",
|
||||
"Panel Woofer B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+60
-60
@@ -1,60 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::jb {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
Button7,
|
||||
Button8,
|
||||
Button9,
|
||||
Button10,
|
||||
Button11,
|
||||
Button12,
|
||||
Button13,
|
||||
Button14,
|
||||
Button15,
|
||||
Button16,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
PANEL_FRONT_R,
|
||||
PANEL_FRONT_G,
|
||||
PANEL_FRONT_B,
|
||||
PANEL_TITLE_R,
|
||||
PANEL_TITLE_G,
|
||||
PANEL_TITLE_B,
|
||||
PANEL_TOP_R,
|
||||
PANEL_TOP_G,
|
||||
PANEL_TOP_B,
|
||||
PANEL_LEFT_R,
|
||||
PANEL_LEFT_G,
|
||||
PANEL_LEFT_B,
|
||||
PANEL_RIGHT_R,
|
||||
PANEL_RIGHT_G,
|
||||
PANEL_RIGHT_B,
|
||||
PANEL_WOOFER_R,
|
||||
PANEL_WOOFER_G,
|
||||
PANEL_WOOFER_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::jb {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
Button7,
|
||||
Button8,
|
||||
Button9,
|
||||
Button10,
|
||||
Button11,
|
||||
Button12,
|
||||
Button13,
|
||||
Button14,
|
||||
Button15,
|
||||
Button16,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
PANEL_FRONT_R,
|
||||
PANEL_FRONT_G,
|
||||
PANEL_FRONT_B,
|
||||
PANEL_TITLE_R,
|
||||
PANEL_TITLE_G,
|
||||
PANEL_TITLE_B,
|
||||
PANEL_TOP_R,
|
||||
PANEL_TOP_G,
|
||||
PANEL_TOP_B,
|
||||
PANEL_LEFT_R,
|
||||
PANEL_LEFT_G,
|
||||
PANEL_LEFT_B,
|
||||
PANEL_RIGHT_R,
|
||||
PANEL_RIGHT_G,
|
||||
PANEL_RIGHT_B,
|
||||
PANEL_WOOFER_R,
|
||||
PANEL_WOOFER_G,
|
||||
PANEL_WOOFER_B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+145
-145
@@ -1,145 +1,145 @@
|
||||
#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"
|
||||
|
||||
namespace games::jb {
|
||||
|
||||
// touch stuff
|
||||
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
|
||||
TOUCH_POINTS.clear();
|
||||
touch_get_points(TOUCH_POINTS);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
#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"
|
||||
|
||||
namespace games::jb {
|
||||
|
||||
// touch stuff
|
||||
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
|
||||
TOUCH_POINTS.clear();
|
||||
touch_get_points(TOUCH_POINTS);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-17
@@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::jb {
|
||||
|
||||
// touch stuff
|
||||
extern bool TOUCH_STATE[16];
|
||||
void touch_update();
|
||||
|
||||
class JBGame : public games::Game {
|
||||
public:
|
||||
JBGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::jb {
|
||||
|
||||
// touch stuff
|
||||
extern bool TOUCH_STATE[16];
|
||||
void touch_update();
|
||||
|
||||
class JBGame : public games::Game {
|
||||
public:
|
||||
JBGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+38
-38
@@ -1,38 +1,38 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::loveplus::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("LovePlus");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Left",
|
||||
"Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::loveplus::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("LovePlus");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue",
|
||||
"Left",
|
||||
"Right"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::loveplus::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("LovePlus");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Left",
|
||||
"Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::loveplus::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("LovePlus");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue",
|
||||
"Left",
|
||||
"Right"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+32
-32
@@ -1,32 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::loveplus {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::loveplus {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+171
-171
@@ -1,171 +1,171 @@
|
||||
#include "loveplus.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
namespace games::loveplus {
|
||||
|
||||
// touch stuff
|
||||
static bool TOUCH_ENABLE = false;
|
||||
static bool TOUCH_ATTACHED = false;
|
||||
|
||||
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(), "LovePlus")) {
|
||||
wnd = FindWindowBeginsWith(avs::game::MODEL);
|
||||
}
|
||||
|
||||
// attach touch hook
|
||||
if (wnd) {
|
||||
log_info("loveplus", "using window handle for touch: {}", fmt::ptr(wnd));
|
||||
touch_create_wnd(wnd);
|
||||
} else {
|
||||
log_info("loveplus", "falling back to the DirectX window handle for touch");
|
||||
touch_attach_dx_hook();
|
||||
}
|
||||
|
||||
// show cursor
|
||||
if (GRAPHICS_SHOW_CURSOR) {
|
||||
ShowCursor(1);
|
||||
}
|
||||
|
||||
// set attached
|
||||
TOUCH_ATTACHED = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_init() {
|
||||
touch_update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_calibrate(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: test this calling convention change!
|
||||
static int __cdecl lib_touchpanel_diagnostics(void *a1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_get_touch(DWORD *a1) {
|
||||
touch_update();
|
||||
|
||||
// get touch points
|
||||
std::vector<TouchPoint> touch_points;
|
||||
touch_get_points(touch_points);
|
||||
|
||||
// check first touch point
|
||||
if (!touch_points.empty()) {
|
||||
auto &tp = touch_points[0];
|
||||
|
||||
a1[0] = tp.y;
|
||||
a1[1] = tp.x;
|
||||
a1[2] = 0;
|
||||
a1[3] = 1;
|
||||
a1[4] = 0;
|
||||
} else {
|
||||
a1[0] = 0;
|
||||
a1[1] = 0;
|
||||
a1[2] = 0;
|
||||
a1[3] = 0;
|
||||
a1[4] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_get_touch_direct(DWORD *a1) {
|
||||
return lib_touchpanel_get_touch(a1);
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_update() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool __cdecl lib_touchpanel_term() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl lib_touchpanel_instance_term() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL __cdecl SetEqualizer(char *a1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static LPSTR __stdcall GetCommandLineA_hook() {
|
||||
static std::string lp_args = "-win -noCamera -noWatchDog -noIOError -noIrda -notarget";
|
||||
|
||||
return lp_args.data();
|
||||
}
|
||||
|
||||
LovePlusGame::LovePlusGame() : Game("LovePlus") {
|
||||
}
|
||||
|
||||
void LovePlusGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// init stuff
|
||||
devicehook_init();
|
||||
|
||||
// enable touch
|
||||
TOUCH_ENABLE = true;
|
||||
|
||||
// touchpanel emulation
|
||||
HMODULE lib_touchpanel = libutils::try_library("lib_touchpanel.dll");
|
||||
detour::inline_hook((void *) lib_touchpanel_init, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_init"));
|
||||
detour::inline_hook((void *) lib_touchpanel_calibrate, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_calibrate"));
|
||||
detour::inline_hook((void *) lib_touchpanel_diagnostics, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_diagnostics"));
|
||||
detour::inline_hook((void *) lib_touchpanel_get_touch, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_get_touch_direct"));
|
||||
detour::inline_hook((void *) lib_touchpanel_get_touch_direct, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_get_touch"));
|
||||
detour::inline_hook((void *) lib_touchpanel_update, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_update"));
|
||||
detour::inline_hook((void *) lib_touchpanel_term, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_term"));
|
||||
detour::inline_hook((void *) lib_touchpanel_instance_term, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_instance_term"));
|
||||
|
||||
// equalizer crash fix
|
||||
HMODULE seteq = libutils::try_library("ad_hd_seteq_dll.dll");
|
||||
detour::inline_hook((void *) SetEqualizer, libutils::try_proc(seteq, "SetEqualizer"));
|
||||
|
||||
// get command line hook
|
||||
HMODULE lpac = libutils::try_library("lpac.dll");
|
||||
detour::iat("GetCommandLineA", GetCommandLineA_hook, lpac);
|
||||
}
|
||||
|
||||
void LovePlusGame::detach() {
|
||||
Game::detach();
|
||||
|
||||
// disable touch
|
||||
TOUCH_ENABLE = false;
|
||||
}
|
||||
}
|
||||
#include "loveplus.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
namespace games::loveplus {
|
||||
|
||||
// touch stuff
|
||||
static bool TOUCH_ENABLE = false;
|
||||
static bool TOUCH_ATTACHED = false;
|
||||
|
||||
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(), "LovePlus")) {
|
||||
wnd = FindWindowBeginsWith(avs::game::MODEL);
|
||||
}
|
||||
|
||||
// attach touch hook
|
||||
if (wnd) {
|
||||
log_info("loveplus", "using window handle for touch: {}", fmt::ptr(wnd));
|
||||
touch_create_wnd(wnd);
|
||||
} else {
|
||||
log_info("loveplus", "falling back to the DirectX window handle for touch");
|
||||
touch_attach_dx_hook();
|
||||
}
|
||||
|
||||
// show cursor
|
||||
if (GRAPHICS_SHOW_CURSOR) {
|
||||
ShowCursor(1);
|
||||
}
|
||||
|
||||
// set attached
|
||||
TOUCH_ATTACHED = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_init() {
|
||||
touch_update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_calibrate(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: test this calling convention change!
|
||||
static int __cdecl lib_touchpanel_diagnostics(void *a1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_get_touch(DWORD *a1) {
|
||||
touch_update();
|
||||
|
||||
// get touch points
|
||||
std::vector<TouchPoint> touch_points;
|
||||
touch_get_points(touch_points);
|
||||
|
||||
// check first touch point
|
||||
if (!touch_points.empty()) {
|
||||
auto &tp = touch_points[0];
|
||||
|
||||
a1[0] = tp.y;
|
||||
a1[1] = tp.x;
|
||||
a1[2] = 0;
|
||||
a1[3] = 1;
|
||||
a1[4] = 0;
|
||||
} else {
|
||||
a1[0] = 0;
|
||||
a1[1] = 0;
|
||||
a1[2] = 0;
|
||||
a1[3] = 0;
|
||||
a1[4] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_get_touch_direct(DWORD *a1) {
|
||||
return lib_touchpanel_get_touch(a1);
|
||||
}
|
||||
|
||||
static int __cdecl lib_touchpanel_update() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool __cdecl lib_touchpanel_term() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl lib_touchpanel_instance_term() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL __cdecl SetEqualizer(char *a1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static LPSTR __stdcall GetCommandLineA_hook() {
|
||||
static std::string lp_args = "-win -noCamera -noWatchDog -noIOError -noIrda -notarget";
|
||||
|
||||
return lp_args.data();
|
||||
}
|
||||
|
||||
LovePlusGame::LovePlusGame() : Game("LovePlus") {
|
||||
}
|
||||
|
||||
void LovePlusGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// init stuff
|
||||
devicehook_init();
|
||||
|
||||
// enable touch
|
||||
TOUCH_ENABLE = true;
|
||||
|
||||
// touchpanel emulation
|
||||
HMODULE lib_touchpanel = libutils::try_library("lib_touchpanel.dll");
|
||||
detour::inline_hook((void *) lib_touchpanel_init, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_init"));
|
||||
detour::inline_hook((void *) lib_touchpanel_calibrate, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_calibrate"));
|
||||
detour::inline_hook((void *) lib_touchpanel_diagnostics, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_diagnostics"));
|
||||
detour::inline_hook((void *) lib_touchpanel_get_touch, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_get_touch_direct"));
|
||||
detour::inline_hook((void *) lib_touchpanel_get_touch_direct, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_get_touch"));
|
||||
detour::inline_hook((void *) lib_touchpanel_update, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_update"));
|
||||
detour::inline_hook((void *) lib_touchpanel_term, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_term"));
|
||||
detour::inline_hook((void *) lib_touchpanel_instance_term, libutils::try_proc(
|
||||
lib_touchpanel, "lib_touchpanel_instance_term"));
|
||||
|
||||
// equalizer crash fix
|
||||
HMODULE seteq = libutils::try_library("ad_hd_seteq_dll.dll");
|
||||
detour::inline_hook((void *) SetEqualizer, libutils::try_proc(seteq, "SetEqualizer"));
|
||||
|
||||
// get command line hook
|
||||
HMODULE lpac = libutils::try_library("lpac.dll");
|
||||
detour::iat("GetCommandLineA", GetCommandLineA_hook, lpac);
|
||||
}
|
||||
|
||||
void LovePlusGame::detach() {
|
||||
Game::detach();
|
||||
|
||||
// disable touch
|
||||
TOUCH_ENABLE = false;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::loveplus {
|
||||
|
||||
// touch stuff
|
||||
void touch_update();
|
||||
|
||||
class LovePlusGame : public games::Game {
|
||||
public:
|
||||
LovePlusGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::loveplus {
|
||||
|
||||
// touch stuff
|
||||
void touch_update();
|
||||
|
||||
class LovePlusGame : public games::Game {
|
||||
public:
|
||||
LovePlusGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+22
-22
@@ -1,22 +1,22 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::mfc::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Mahjong Fight Club");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Select",
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin",
|
||||
"Joystick Up",
|
||||
"Joystick Down",
|
||||
"Joystick Enter"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::mfc::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Mahjong Fight Club");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Select",
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin",
|
||||
"Joystick Up",
|
||||
"Joystick Down",
|
||||
"Joystick Enter"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
+21
-21
@@ -1,21 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::mfc {
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Select,
|
||||
Service,
|
||||
Test,
|
||||
Coin,
|
||||
JoystickUp,
|
||||
JoystickDown,
|
||||
JoystickStart,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::mfc {
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Select,
|
||||
Service,
|
||||
Test,
|
||||
Coin,
|
||||
JoystickUp,
|
||||
JoystickDown,
|
||||
JoystickStart,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
}
|
||||
|
||||
+382
-382
@@ -1,382 +1,382 @@
|
||||
#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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-20
@@ -1,20 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::mfc {
|
||||
|
||||
struct joystick_state {
|
||||
bool up = false;
|
||||
bool down = false;
|
||||
bool start = false;
|
||||
bool service = false;
|
||||
bool test = false;
|
||||
};
|
||||
|
||||
class MFCGame : public games::Game {
|
||||
public:
|
||||
MFCGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::mfc {
|
||||
|
||||
struct joystick_state {
|
||||
bool up = false;
|
||||
bool down = false;
|
||||
bool start = false;
|
||||
bool service = false;
|
||||
bool test = false;
|
||||
};
|
||||
|
||||
class MFCGame : public games::Game {
|
||||
public:
|
||||
MFCGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+158
-158
@@ -1,158 +1,158 @@
|
||||
#include "gunio.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
bool games::mga::SpiceGearGunHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("metalgear", "Opened gun device on COM1");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// minimum buffer size
|
||||
if ((command == 0u) || nNumberOfBytesToRead < 2)
|
||||
return 0;
|
||||
|
||||
// execute command
|
||||
int bytes_read = 0;
|
||||
switch (command) {
|
||||
case 0x04: // get version
|
||||
|
||||
// write version
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = version;
|
||||
|
||||
break;
|
||||
case 0x08: // get input state
|
||||
{
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 12)
|
||||
return 0;
|
||||
|
||||
// get cursor position
|
||||
POINT cursor_pos{};
|
||||
GetCursorPos(&cursor_pos);
|
||||
|
||||
// get screen size
|
||||
RECT screen_size{};
|
||||
GetWindowRect(GetDesktopWindow(), &screen_size);
|
||||
auto screen_width = (unsigned short) (screen_size.right - screen_size.left);
|
||||
auto screen_height = (unsigned short) (screen_size.bottom - screen_size.top);
|
||||
|
||||
// calculate cursor position
|
||||
p1_x = (unsigned short) (((cursor_pos.x * 1024) / screen_width) % 1024);
|
||||
p1_y = (unsigned short) (1024 - (((cursor_pos.y * 1024) / screen_height) % 1024));
|
||||
|
||||
// gun P1
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = HIBYTE(p1_x);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = LOBYTE(p1_x);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = HIBYTE(p1_y);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = LOBYTE(p1_y);
|
||||
bytes_read += 3;
|
||||
|
||||
// fill buffer
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0C: // not called in game - empty
|
||||
|
||||
// empty data
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x10: // get DIP switches
|
||||
|
||||
// clear bits
|
||||
*((unsigned char *) lpBuffer + bytes_read) = 0x00;
|
||||
|
||||
// set bits
|
||||
if (frequency == 1)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x80;
|
||||
if (frequency == 2)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x40;
|
||||
if (frequency == 3)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x20;
|
||||
if (frequency == 4)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x10;
|
||||
|
||||
break;
|
||||
case 0x14: // frequency 1
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 1;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x18: // frequency 2
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 2;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x19: // frequency 3
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 3;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x1A: // frequency 4
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 4;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x1C: // led board check
|
||||
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 11)
|
||||
return 0;
|
||||
|
||||
// set all bits
|
||||
memset(lpBuffer, 0xFF, 10);
|
||||
bytes_read += 10;
|
||||
|
||||
break;
|
||||
default:
|
||||
log_warning("metalgear", "unknown opcode: 0x{:02X}", command);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x01;
|
||||
}
|
||||
|
||||
// reset command
|
||||
command = 0;
|
||||
|
||||
// calculate checksum
|
||||
unsigned char checksum = 0xFF;
|
||||
for (int i = 0; i < bytes_read; i++)
|
||||
checksum -= *((unsigned char *) lpBuffer + i);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = checksum;
|
||||
|
||||
// return amount of bytes read
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// save command
|
||||
if (nNumberOfBytesToWrite > 0)
|
||||
command = *((unsigned char *) lpBuffer);
|
||||
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::mga::SpiceGearGunHandle::close() {
|
||||
log_info("metalgear", "Closed gun device on COM1");
|
||||
return true;
|
||||
}
|
||||
#include "gunio.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
bool games::mga::SpiceGearGunHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
log_info("metalgear", "Opened gun device on COM1");
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// minimum buffer size
|
||||
if ((command == 0u) || nNumberOfBytesToRead < 2)
|
||||
return 0;
|
||||
|
||||
// execute command
|
||||
int bytes_read = 0;
|
||||
switch (command) {
|
||||
case 0x04: // get version
|
||||
|
||||
// write version
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = version;
|
||||
|
||||
break;
|
||||
case 0x08: // get input state
|
||||
{
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 12)
|
||||
return 0;
|
||||
|
||||
// get cursor position
|
||||
POINT cursor_pos{};
|
||||
GetCursorPos(&cursor_pos);
|
||||
|
||||
// get screen size
|
||||
RECT screen_size{};
|
||||
GetWindowRect(GetDesktopWindow(), &screen_size);
|
||||
auto screen_width = (unsigned short) (screen_size.right - screen_size.left);
|
||||
auto screen_height = (unsigned short) (screen_size.bottom - screen_size.top);
|
||||
|
||||
// calculate cursor position
|
||||
p1_x = (unsigned short) (((cursor_pos.x * 1024) / screen_width) % 1024);
|
||||
p1_y = (unsigned short) (1024 - (((cursor_pos.y * 1024) / screen_height) % 1024));
|
||||
|
||||
// gun P1
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = HIBYTE(p1_x);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = LOBYTE(p1_x);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = HIBYTE(p1_y);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = LOBYTE(p1_y);
|
||||
bytes_read += 3;
|
||||
|
||||
// fill buffer
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x75;
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0C: // not called in game - empty
|
||||
|
||||
// empty data
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x10: // get DIP switches
|
||||
|
||||
// clear bits
|
||||
*((unsigned char *) lpBuffer + bytes_read) = 0x00;
|
||||
|
||||
// set bits
|
||||
if (frequency == 1)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x80;
|
||||
if (frequency == 2)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x40;
|
||||
if (frequency == 3)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x20;
|
||||
if (frequency == 4)
|
||||
*((unsigned char *) lpBuffer + bytes_read) |= 0x10;
|
||||
|
||||
break;
|
||||
case 0x14: // frequency 1
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 1;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x18: // frequency 2
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 2;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x19: // frequency 3
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 3;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x1A: // frequency 4
|
||||
|
||||
// set frequency and return empty data
|
||||
frequency = 4;
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x00;
|
||||
|
||||
break;
|
||||
case 0x1C: // led board check
|
||||
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 11)
|
||||
return 0;
|
||||
|
||||
// set all bits
|
||||
memset(lpBuffer, 0xFF, 10);
|
||||
bytes_read += 10;
|
||||
|
||||
break;
|
||||
default:
|
||||
log_warning("metalgear", "unknown opcode: 0x{:02X}", command);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = 0x01;
|
||||
}
|
||||
|
||||
// reset command
|
||||
command = 0;
|
||||
|
||||
// calculate checksum
|
||||
unsigned char checksum = 0xFF;
|
||||
for (int i = 0; i < bytes_read; i++)
|
||||
checksum -= *((unsigned char *) lpBuffer + i);
|
||||
*((unsigned char *) lpBuffer + bytes_read++) = checksum;
|
||||
|
||||
// return amount of bytes read
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
|
||||
// save command
|
||||
if (nNumberOfBytesToWrite > 0)
|
||||
command = *((unsigned char *) lpBuffer);
|
||||
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::mga::SpiceGearGunHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::mga::SpiceGearGunHandle::close() {
|
||||
log_info("metalgear", "Closed gun device on COM1");
|
||||
return true;
|
||||
}
|
||||
|
||||
+29
-29
@@ -1,29 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::mga {
|
||||
|
||||
// Team FrontLine GUN IO
|
||||
class SpiceGearGunHandle : public CustomHandle {
|
||||
private:
|
||||
|
||||
unsigned char version = 62;
|
||||
unsigned char command = 0x00;
|
||||
unsigned short p1_x = 0;
|
||||
unsigned short p1_y = 0;
|
||||
int frequency = 1;
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "hooks/devicehook.h"
|
||||
|
||||
namespace games::mga {
|
||||
|
||||
// Team FrontLine GUN IO
|
||||
class SpiceGearGunHandle : public CustomHandle {
|
||||
private:
|
||||
|
||||
unsigned char version = 62;
|
||||
unsigned char command = 0x00;
|
||||
unsigned short p1_x = 0;
|
||||
unsigned short p1_y = 0;
|
||||
int frequency = 1;
|
||||
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override;
|
||||
|
||||
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
|
||||
|
||||
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
|
||||
|
||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize) override;
|
||||
|
||||
bool close() override;
|
||||
};
|
||||
}
|
||||
|
||||
+73
-73
@@ -1,73 +1,73 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::mga::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Metal Gear");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Start",
|
||||
"Top",
|
||||
"Front Top",
|
||||
"Front Bottom",
|
||||
"Side Left",
|
||||
"Side Right",
|
||||
"Side Lever",
|
||||
"Trigger Button",
|
||||
"Switch Button",
|
||||
"Joy Forwards",
|
||||
"Joy Backwards",
|
||||
"Joy Left",
|
||||
"Joy Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::mga::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Metal Gear");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Joy X",
|
||||
"Joy Y"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Light> &games::mga::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Metal Gear");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Start",
|
||||
"Left R",
|
||||
"Left G",
|
||||
"Left B",
|
||||
"Right R",
|
||||
"Right G",
|
||||
"Right B",
|
||||
"Gun R",
|
||||
"Gun G",
|
||||
"Gun B",
|
||||
"Gun Vibration"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::mga::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Metal Gear");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Start",
|
||||
"Top",
|
||||
"Front Top",
|
||||
"Front Bottom",
|
||||
"Side Left",
|
||||
"Side Right",
|
||||
"Side Lever",
|
||||
"Trigger Button",
|
||||
"Switch Button",
|
||||
"Joy Forwards",
|
||||
"Joy Backwards",
|
||||
"Joy Left",
|
||||
"Joy Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::mga::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Metal Gear");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Joy X",
|
||||
"Joy Y"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Light> &games::mga::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Metal Gear");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Start",
|
||||
"Left R",
|
||||
"Left G",
|
||||
"Left B",
|
||||
"Right R",
|
||||
"Right G",
|
||||
"Right B",
|
||||
"Gun R",
|
||||
"Gun G",
|
||||
"Gun B",
|
||||
"Gun Vibration"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+59
-59
@@ -1,59 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::mga {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Start,
|
||||
Top,
|
||||
FrontTop,
|
||||
FrontBottom,
|
||||
SideLeft,
|
||||
SideRight,
|
||||
SideLever,
|
||||
TriggerButton,
|
||||
SwitchButton,
|
||||
JoyForwards,
|
||||
JoyBackwards,
|
||||
JoyLeft,
|
||||
JoyRight,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
JoyX,
|
||||
JoyY,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Start,
|
||||
LeftR,
|
||||
LeftG,
|
||||
LeftB,
|
||||
RightR,
|
||||
RightG,
|
||||
RightB,
|
||||
GunR,
|
||||
GunG,
|
||||
GunB,
|
||||
GunVibration,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::mga {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Start,
|
||||
Top,
|
||||
FrontTop,
|
||||
FrontBottom,
|
||||
SideLeft,
|
||||
SideRight,
|
||||
SideLever,
|
||||
TriggerButton,
|
||||
SwitchButton,
|
||||
JoyForwards,
|
||||
JoyBackwards,
|
||||
JoyLeft,
|
||||
JoyRight,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
JoyX,
|
||||
JoyY,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Start,
|
||||
LeftR,
|
||||
LeftG,
|
||||
LeftB,
|
||||
RightR,
|
||||
RightG,
|
||||
RightB,
|
||||
GunR,
|
||||
GunG,
|
||||
GunB,
|
||||
GunVibration,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+82
-82
@@ -1,82 +1,82 @@
|
||||
#include "mga.h"
|
||||
|
||||
#include "acio/icca/icca.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/sigscan.h"
|
||||
|
||||
#include "gunio.h"
|
||||
|
||||
namespace games::mga {
|
||||
void (__cdecl *ess_eventlog_request_error_orig)(const char *, unsigned int, int, int);
|
||||
|
||||
static int __cdecl log_change_level_hook(int level) {
|
||||
log_misc("mga", "ignoring log_change_level({})", level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uintptr_t __cdecl log_change_output_hook(uintptr_t target, uintptr_t a2) {
|
||||
log_misc("mga", "ignoring log_change_output(0x{:x}, 0x{:x})", target, a2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl setvolume_hook(uint8_t volume) {
|
||||
log_misc("mga", "ignoring setvolume {}", static_cast<int>(volume));
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __cdecl ess_eventlog_request_error_hook(const char *a1, unsigned int a2, int a3, int a4) {
|
||||
log_info("mga", "ess_eventlog_request_error({}, {}, {}, {})", a1, a2, a3, a4);
|
||||
|
||||
//ess_eventlog_request_error_orig(a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
MGAGame::MGAGame() : Game("Metal Gear Arcade") {
|
||||
}
|
||||
|
||||
void MGAGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// load system.dll (along with the serial functions)
|
||||
auto system = libutils::load_library("system.dll");
|
||||
|
||||
// add the gun
|
||||
devicehook_init();
|
||||
devicehook_add(new SpiceGearGunHandle());
|
||||
|
||||
// fix ICCA
|
||||
acio::ICCA_COMPAT_ACTIVE = true;
|
||||
|
||||
// ignore sound engine failure
|
||||
if (!replace_pattern(
|
||||
system,
|
||||
"E8????????84C0750A68F4010000E8????????E8????????E8????????3BF3750433C0EB0C",
|
||||
"??????????????????90909090909090909090????????????????????????????????????",
|
||||
0, 0))
|
||||
{
|
||||
log_warning("mga", "failed to patch sound engine");
|
||||
}
|
||||
|
||||
// hook setvolume
|
||||
if (!detour::iat_try("?setvolume@@YAHPAD@Z", setvolume_hook)) {
|
||||
log_warning("mga", "setvolume hook failed");
|
||||
}
|
||||
|
||||
// stop the game from redirecting AVS log calls
|
||||
detour::iat_try("log_change_level", log_change_level_hook);
|
||||
detour::iat_try("log_change_output", log_change_output_hook);
|
||||
|
||||
ess_eventlog_request_error_orig = detour::iat_try("ess_eventlog_request_error", ess_eventlog_request_error_hook);
|
||||
}
|
||||
|
||||
void MGAGame::detach() {
|
||||
Game::detach();
|
||||
|
||||
devicehook_dispose();
|
||||
}
|
||||
}
|
||||
#include "mga.h"
|
||||
|
||||
#include "acio/icca/icca.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/sigscan.h"
|
||||
|
||||
#include "gunio.h"
|
||||
|
||||
namespace games::mga {
|
||||
void (__cdecl *ess_eventlog_request_error_orig)(const char *, unsigned int, int, int);
|
||||
|
||||
static int __cdecl log_change_level_hook(int level) {
|
||||
log_misc("mga", "ignoring log_change_level({})", level);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uintptr_t __cdecl log_change_output_hook(uintptr_t target, uintptr_t a2) {
|
||||
log_misc("mga", "ignoring log_change_output(0x{:x}, 0x{:x})", target, a2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl setvolume_hook(uint8_t volume) {
|
||||
log_misc("mga", "ignoring setvolume {}", static_cast<int>(volume));
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __cdecl ess_eventlog_request_error_hook(const char *a1, unsigned int a2, int a3, int a4) {
|
||||
log_info("mga", "ess_eventlog_request_error({}, {}, {}, {})", a1, a2, a3, a4);
|
||||
|
||||
//ess_eventlog_request_error_orig(a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
MGAGame::MGAGame() : Game("Metal Gear Arcade") {
|
||||
}
|
||||
|
||||
void MGAGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// load system.dll (along with the serial functions)
|
||||
auto system = libutils::load_library("system.dll");
|
||||
|
||||
// add the gun
|
||||
devicehook_init();
|
||||
devicehook_add(new SpiceGearGunHandle());
|
||||
|
||||
// fix ICCA
|
||||
acio::ICCA_COMPAT_ACTIVE = true;
|
||||
|
||||
// ignore sound engine failure
|
||||
if (!replace_pattern(
|
||||
system,
|
||||
"E8????????84C0750A68F4010000E8????????E8????????E8????????3BF3750433C0EB0C",
|
||||
"??????????????????90909090909090909090????????????????????????????????????",
|
||||
0, 0))
|
||||
{
|
||||
log_warning("mga", "failed to patch sound engine");
|
||||
}
|
||||
|
||||
// hook setvolume
|
||||
if (!detour::iat_try("?setvolume@@YAHPAD@Z", setvolume_hook)) {
|
||||
log_warning("mga", "setvolume hook failed");
|
||||
}
|
||||
|
||||
// stop the game from redirecting AVS log calls
|
||||
detour::iat_try("log_change_level", log_change_level_hook);
|
||||
detour::iat_try("log_change_output", log_change_output_hook);
|
||||
|
||||
ess_eventlog_request_error_orig = detour::iat_try("ess_eventlog_request_error", ess_eventlog_request_error_hook);
|
||||
}
|
||||
|
||||
void MGAGame::detach() {
|
||||
Game::detach();
|
||||
|
||||
devicehook_dispose();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::mga {
|
||||
|
||||
class MGAGame : public games::Game {
|
||||
public:
|
||||
MGAGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::mga {
|
||||
|
||||
class MGAGame : public games::Game {
|
||||
public:
|
||||
MGAGame();
|
||||
virtual void attach() override;
|
||||
virtual void detach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+98
-98
@@ -1,98 +1,98 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::museca::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Museca");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Start",
|
||||
"Disk1-",
|
||||
"Disk1+",
|
||||
"Disk1 Press",
|
||||
"Disk2-",
|
||||
"Disk2+",
|
||||
"Disk2 Press",
|
||||
"Disk3-",
|
||||
"Disk3+",
|
||||
"Disk3 Press",
|
||||
"Disk4-",
|
||||
"Disk4+",
|
||||
"Disk4 Press",
|
||||
"Disk5-",
|
||||
"Disk5+",
|
||||
"Disk5 Press",
|
||||
"Foot Pedal",
|
||||
"Analog Slowdown"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::museca::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Museca");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Disk1",
|
||||
"Disk2",
|
||||
"Disk3",
|
||||
"Disk4",
|
||||
"Disk5"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::museca::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Museca");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Side R",
|
||||
"Side G",
|
||||
"Side B",
|
||||
"Spinner1 R",
|
||||
"Spinner1 G",
|
||||
"Spinner1 B",
|
||||
"Spinner2 R",
|
||||
"Spinner2 G",
|
||||
"Spinner2 B",
|
||||
"Spinner3 R",
|
||||
"Spinner3 G",
|
||||
"Spinner3 B",
|
||||
"Spinner4 R",
|
||||
"Spinner4 G",
|
||||
"Spinner4 B",
|
||||
"Spinner5 R",
|
||||
"Spinner5 G",
|
||||
"Spinner5 B",
|
||||
"Under-LED1 R",
|
||||
"Under-LED1 G",
|
||||
"Under-LED1 B",
|
||||
"Under-LED2 R",
|
||||
"Under-LED2 G",
|
||||
"Under-LED2 B",
|
||||
"Under-LED3 R",
|
||||
"Under-LED3 G",
|
||||
"Under-LED3 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::museca::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Museca");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Start",
|
||||
"Disk1-",
|
||||
"Disk1+",
|
||||
"Disk1 Press",
|
||||
"Disk2-",
|
||||
"Disk2+",
|
||||
"Disk2 Press",
|
||||
"Disk3-",
|
||||
"Disk3+",
|
||||
"Disk3 Press",
|
||||
"Disk4-",
|
||||
"Disk4+",
|
||||
"Disk4 Press",
|
||||
"Disk5-",
|
||||
"Disk5+",
|
||||
"Disk5 Press",
|
||||
"Foot Pedal",
|
||||
"Analog Slowdown"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::museca::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Museca");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Disk1",
|
||||
"Disk2",
|
||||
"Disk3",
|
||||
"Disk4",
|
||||
"Disk5"
|
||||
);
|
||||
}
|
||||
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::museca::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Museca");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Side R",
|
||||
"Side G",
|
||||
"Side B",
|
||||
"Spinner1 R",
|
||||
"Spinner1 G",
|
||||
"Spinner1 B",
|
||||
"Spinner2 R",
|
||||
"Spinner2 G",
|
||||
"Spinner2 B",
|
||||
"Spinner3 R",
|
||||
"Spinner3 G",
|
||||
"Spinner3 B",
|
||||
"Spinner4 R",
|
||||
"Spinner4 G",
|
||||
"Spinner4 B",
|
||||
"Spinner5 R",
|
||||
"Spinner5 G",
|
||||
"Spinner5 B",
|
||||
"Under-LED1 R",
|
||||
"Under-LED1 G",
|
||||
"Under-LED1 B",
|
||||
"Under-LED2 R",
|
||||
"Under-LED2 G",
|
||||
"Under-LED2 B",
|
||||
"Under-LED3 R",
|
||||
"Under-LED3 G",
|
||||
"Under-LED3 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+86
-86
@@ -1,86 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::museca {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Start,
|
||||
Disk1Minus,
|
||||
Disk1Plus,
|
||||
Disk1Press,
|
||||
Disk2Minus,
|
||||
Disk2Plus,
|
||||
Disk2Press,
|
||||
Disk3Minus,
|
||||
Disk3Plus,
|
||||
Disk3Press,
|
||||
Disk4Minus,
|
||||
Disk4Plus,
|
||||
Disk4Press,
|
||||
Disk5Minus,
|
||||
Disk5Plus,
|
||||
Disk5Press,
|
||||
FootPedal,
|
||||
AnalogSlowdown
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
Disk1,
|
||||
Disk2,
|
||||
Disk3,
|
||||
Disk4,
|
||||
Disk5
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
SideR,
|
||||
SideG,
|
||||
SideB,
|
||||
Spinner1R,
|
||||
Spinner1G,
|
||||
Spinner1B,
|
||||
Spinner2R,
|
||||
Spinner2G,
|
||||
Spinner2B,
|
||||
Spinner3R,
|
||||
Spinner3G,
|
||||
Spinner3B,
|
||||
Spinner4R,
|
||||
Spinner4G,
|
||||
Spinner4B,
|
||||
Spinner5R,
|
||||
Spinner5G,
|
||||
Spinner5B,
|
||||
UnderLED1R,
|
||||
UnderLED1G,
|
||||
UnderLED1B,
|
||||
UnderLED2R,
|
||||
UnderLED2G,
|
||||
UnderLED2B,
|
||||
UnderLED3R,
|
||||
UnderLED3G,
|
||||
UnderLED3B
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::museca {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Start,
|
||||
Disk1Minus,
|
||||
Disk1Plus,
|
||||
Disk1Press,
|
||||
Disk2Minus,
|
||||
Disk2Plus,
|
||||
Disk2Press,
|
||||
Disk3Minus,
|
||||
Disk3Plus,
|
||||
Disk3Press,
|
||||
Disk4Minus,
|
||||
Disk4Plus,
|
||||
Disk4Press,
|
||||
Disk5Minus,
|
||||
Disk5Plus,
|
||||
Disk5Press,
|
||||
FootPedal,
|
||||
AnalogSlowdown
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
Disk1,
|
||||
Disk2,
|
||||
Disk3,
|
||||
Disk4,
|
||||
Disk5
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
SideR,
|
||||
SideG,
|
||||
SideB,
|
||||
Spinner1R,
|
||||
Spinner1G,
|
||||
Spinner1B,
|
||||
Spinner2R,
|
||||
Spinner2G,
|
||||
Spinner2B,
|
||||
Spinner3R,
|
||||
Spinner3G,
|
||||
Spinner3B,
|
||||
Spinner4R,
|
||||
Spinner4G,
|
||||
Spinner4B,
|
||||
Spinner5R,
|
||||
Spinner5G,
|
||||
Spinner5B,
|
||||
UnderLED1R,
|
||||
UnderLED1G,
|
||||
UnderLED1B,
|
||||
UnderLED2R,
|
||||
UnderLED2G,
|
||||
UnderLED2B,
|
||||
UnderLED3R,
|
||||
UnderLED3G,
|
||||
UnderLED3B
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+191
-191
@@ -1,191 +1,191 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::nost::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Nostalgia");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Key 1",
|
||||
"Key 2",
|
||||
"Key 3",
|
||||
"Key 4",
|
||||
"Key 5",
|
||||
"Key 6",
|
||||
"Key 7",
|
||||
"Key 8",
|
||||
"Key 9",
|
||||
"Key 10",
|
||||
"Key 11",
|
||||
"Key 12",
|
||||
"Key 13",
|
||||
"Key 14",
|
||||
"Key 15",
|
||||
"Key 16",
|
||||
"Key 17",
|
||||
"Key 18",
|
||||
"Key 19",
|
||||
"Key 20",
|
||||
"Key 21",
|
||||
"Key 22",
|
||||
"Key 23",
|
||||
"Key 24",
|
||||
"Key 25",
|
||||
"Key 26",
|
||||
"Key 27",
|
||||
"Key 28"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::nost::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Nostalgia");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Key 1",
|
||||
"Key 2",
|
||||
"Key 3",
|
||||
"Key 4",
|
||||
"Key 5",
|
||||
"Key 6",
|
||||
"Key 7",
|
||||
"Key 8",
|
||||
"Key 9",
|
||||
"Key 10",
|
||||
"Key 11",
|
||||
"Key 12",
|
||||
"Key 13",
|
||||
"Key 14",
|
||||
"Key 15",
|
||||
"Key 16",
|
||||
"Key 17",
|
||||
"Key 18",
|
||||
"Key 19",
|
||||
"Key 20",
|
||||
"Key 21",
|
||||
"Key 22",
|
||||
"Key 23",
|
||||
"Key 24",
|
||||
"Key 25",
|
||||
"Key 26",
|
||||
"Key 27",
|
||||
"Key 28"
|
||||
);
|
||||
}
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::nost::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Nostalgia");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Bottom R",
|
||||
"Bottom G",
|
||||
"Bottom B",
|
||||
"Key 1 R",
|
||||
"Key 1 G",
|
||||
"Key 1 B",
|
||||
"Key 2 R",
|
||||
"Key 2 G",
|
||||
"Key 2 B",
|
||||
"Key 3 R",
|
||||
"Key 3 G",
|
||||
"Key 3 B",
|
||||
"Key 4 R",
|
||||
"Key 4 G",
|
||||
"Key 4 B",
|
||||
"Key 5 R",
|
||||
"Key 5 G",
|
||||
"Key 5 B",
|
||||
"Key 6 R",
|
||||
"Key 6 G",
|
||||
"Key 6 B",
|
||||
"Key 7 R",
|
||||
"Key 7 G",
|
||||
"Key 7 B",
|
||||
"Key 8 R",
|
||||
"Key 8 G",
|
||||
"Key 8 B",
|
||||
"Key 9 R",
|
||||
"Key 9 G",
|
||||
"Key 9 B",
|
||||
"Key 10 R",
|
||||
"Key 10 G",
|
||||
"Key 10 B",
|
||||
"Key 11 R",
|
||||
"Key 11 G",
|
||||
"Key 11 B",
|
||||
"Key 12 R",
|
||||
"Key 12 G",
|
||||
"Key 12 B",
|
||||
"Key 13 R",
|
||||
"Key 13 G",
|
||||
"Key 13 B",
|
||||
"Key 14 R",
|
||||
"Key 14 G",
|
||||
"Key 14 B",
|
||||
"Key 15 R",
|
||||
"Key 15 G",
|
||||
"Key 15 B",
|
||||
"Key 16 R",
|
||||
"Key 16 G",
|
||||
"Key 16 B",
|
||||
"Key 17 R",
|
||||
"Key 17 G",
|
||||
"Key 17 B",
|
||||
"Key 18 R",
|
||||
"Key 18 G",
|
||||
"Key 18 B",
|
||||
"Key 19 R",
|
||||
"Key 19 G",
|
||||
"Key 19 B",
|
||||
"Key 20 R",
|
||||
"Key 20 G",
|
||||
"Key 20 B",
|
||||
"Key 21 R",
|
||||
"Key 21 G",
|
||||
"Key 21 B",
|
||||
"Key 22 R",
|
||||
"Key 22 G",
|
||||
"Key 22 B",
|
||||
"Key 23 R",
|
||||
"Key 23 G",
|
||||
"Key 23 B",
|
||||
"Key 24 R",
|
||||
"Key 24 G",
|
||||
"Key 24 B",
|
||||
"Key 25 R",
|
||||
"Key 25 G",
|
||||
"Key 25 B",
|
||||
"Key 26 R",
|
||||
"Key 26 G",
|
||||
"Key 26 B",
|
||||
"Key 27 R",
|
||||
"Key 27 G",
|
||||
"Key 27 B",
|
||||
"Key 28 R",
|
||||
"Key 28 G",
|
||||
"Key 28 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::nost::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Nostalgia");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Key 1",
|
||||
"Key 2",
|
||||
"Key 3",
|
||||
"Key 4",
|
||||
"Key 5",
|
||||
"Key 6",
|
||||
"Key 7",
|
||||
"Key 8",
|
||||
"Key 9",
|
||||
"Key 10",
|
||||
"Key 11",
|
||||
"Key 12",
|
||||
"Key 13",
|
||||
"Key 14",
|
||||
"Key 15",
|
||||
"Key 16",
|
||||
"Key 17",
|
||||
"Key 18",
|
||||
"Key 19",
|
||||
"Key 20",
|
||||
"Key 21",
|
||||
"Key 22",
|
||||
"Key 23",
|
||||
"Key 24",
|
||||
"Key 25",
|
||||
"Key 26",
|
||||
"Key 27",
|
||||
"Key 28"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Analog> &games::nost::get_analogs() {
|
||||
static std::vector<Analog> analogs;
|
||||
|
||||
if (analogs.empty()) {
|
||||
analogs = GameAPI::Analogs::getAnalogs("Nostalgia");
|
||||
|
||||
GameAPI::Analogs::sortAnalogs(
|
||||
&analogs,
|
||||
"Key 1",
|
||||
"Key 2",
|
||||
"Key 3",
|
||||
"Key 4",
|
||||
"Key 5",
|
||||
"Key 6",
|
||||
"Key 7",
|
||||
"Key 8",
|
||||
"Key 9",
|
||||
"Key 10",
|
||||
"Key 11",
|
||||
"Key 12",
|
||||
"Key 13",
|
||||
"Key 14",
|
||||
"Key 15",
|
||||
"Key 16",
|
||||
"Key 17",
|
||||
"Key 18",
|
||||
"Key 19",
|
||||
"Key 20",
|
||||
"Key 21",
|
||||
"Key 22",
|
||||
"Key 23",
|
||||
"Key 24",
|
||||
"Key 25",
|
||||
"Key 26",
|
||||
"Key 27",
|
||||
"Key 28"
|
||||
);
|
||||
}
|
||||
return analogs;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::nost::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Nostalgia");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Bottom R",
|
||||
"Bottom G",
|
||||
"Bottom B",
|
||||
"Key 1 R",
|
||||
"Key 1 G",
|
||||
"Key 1 B",
|
||||
"Key 2 R",
|
||||
"Key 2 G",
|
||||
"Key 2 B",
|
||||
"Key 3 R",
|
||||
"Key 3 G",
|
||||
"Key 3 B",
|
||||
"Key 4 R",
|
||||
"Key 4 G",
|
||||
"Key 4 B",
|
||||
"Key 5 R",
|
||||
"Key 5 G",
|
||||
"Key 5 B",
|
||||
"Key 6 R",
|
||||
"Key 6 G",
|
||||
"Key 6 B",
|
||||
"Key 7 R",
|
||||
"Key 7 G",
|
||||
"Key 7 B",
|
||||
"Key 8 R",
|
||||
"Key 8 G",
|
||||
"Key 8 B",
|
||||
"Key 9 R",
|
||||
"Key 9 G",
|
||||
"Key 9 B",
|
||||
"Key 10 R",
|
||||
"Key 10 G",
|
||||
"Key 10 B",
|
||||
"Key 11 R",
|
||||
"Key 11 G",
|
||||
"Key 11 B",
|
||||
"Key 12 R",
|
||||
"Key 12 G",
|
||||
"Key 12 B",
|
||||
"Key 13 R",
|
||||
"Key 13 G",
|
||||
"Key 13 B",
|
||||
"Key 14 R",
|
||||
"Key 14 G",
|
||||
"Key 14 B",
|
||||
"Key 15 R",
|
||||
"Key 15 G",
|
||||
"Key 15 B",
|
||||
"Key 16 R",
|
||||
"Key 16 G",
|
||||
"Key 16 B",
|
||||
"Key 17 R",
|
||||
"Key 17 G",
|
||||
"Key 17 B",
|
||||
"Key 18 R",
|
||||
"Key 18 G",
|
||||
"Key 18 B",
|
||||
"Key 19 R",
|
||||
"Key 19 G",
|
||||
"Key 19 B",
|
||||
"Key 20 R",
|
||||
"Key 20 G",
|
||||
"Key 20 B",
|
||||
"Key 21 R",
|
||||
"Key 21 G",
|
||||
"Key 21 B",
|
||||
"Key 22 R",
|
||||
"Key 22 G",
|
||||
"Key 22 B",
|
||||
"Key 23 R",
|
||||
"Key 23 G",
|
||||
"Key 23 B",
|
||||
"Key 24 R",
|
||||
"Key 24 G",
|
||||
"Key 24 B",
|
||||
"Key 25 R",
|
||||
"Key 25 G",
|
||||
"Key 25 B",
|
||||
"Key 26 R",
|
||||
"Key 26 G",
|
||||
"Key 26 B",
|
||||
"Key 27 R",
|
||||
"Key 27 G",
|
||||
"Key 27 B",
|
||||
"Key 28 R",
|
||||
"Key 28 G",
|
||||
"Key 28 B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+179
-179
@@ -1,179 +1,179 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::nost {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
Key4,
|
||||
Key5,
|
||||
Key6,
|
||||
Key7,
|
||||
Key8,
|
||||
Key9,
|
||||
Key10,
|
||||
Key11,
|
||||
Key12,
|
||||
Key13,
|
||||
Key14,
|
||||
Key15,
|
||||
Key16,
|
||||
Key17,
|
||||
Key18,
|
||||
Key19,
|
||||
Key20,
|
||||
Key21,
|
||||
Key22,
|
||||
Key23,
|
||||
Key24,
|
||||
Key25,
|
||||
Key26,
|
||||
Key27,
|
||||
Key28,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
Key4,
|
||||
Key5,
|
||||
Key6,
|
||||
Key7,
|
||||
Key8,
|
||||
Key9,
|
||||
Key10,
|
||||
Key11,
|
||||
Key12,
|
||||
Key13,
|
||||
Key14,
|
||||
Key15,
|
||||
Key16,
|
||||
Key17,
|
||||
Key18,
|
||||
Key19,
|
||||
Key20,
|
||||
Key21,
|
||||
Key22,
|
||||
Key23,
|
||||
Key24,
|
||||
Key25,
|
||||
Key26,
|
||||
Key27,
|
||||
Key28,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
BottomR,
|
||||
BottomG,
|
||||
BottomB,
|
||||
Key1R,
|
||||
Key1G,
|
||||
Key1B,
|
||||
Key2R,
|
||||
Key2G,
|
||||
Key2B,
|
||||
Key3R,
|
||||
Key3G,
|
||||
Key3B,
|
||||
Key4R,
|
||||
Key4G,
|
||||
Key4B,
|
||||
Key5R,
|
||||
Key5G,
|
||||
Key5B,
|
||||
Key6R,
|
||||
Key6G,
|
||||
Key6B,
|
||||
Key7R,
|
||||
Key7G,
|
||||
Key7B,
|
||||
Key8R,
|
||||
Key8G,
|
||||
Key8B,
|
||||
Key9R,
|
||||
Key9G,
|
||||
Key9B,
|
||||
Key10R,
|
||||
Key10G,
|
||||
Key10B,
|
||||
Key11R,
|
||||
Key11G,
|
||||
Key11B,
|
||||
Key12R,
|
||||
Key12G,
|
||||
Key12B,
|
||||
Key13R,
|
||||
Key13G,
|
||||
Key13B,
|
||||
Key14R,
|
||||
Key14G,
|
||||
Key14B,
|
||||
Key15R,
|
||||
Key15G,
|
||||
Key15B,
|
||||
Key16R,
|
||||
Key16G,
|
||||
Key16B,
|
||||
Key17R,
|
||||
Key17G,
|
||||
Key17B,
|
||||
Key18R,
|
||||
Key18G,
|
||||
Key18B,
|
||||
Key19R,
|
||||
Key19G,
|
||||
Key19B,
|
||||
Key20R,
|
||||
Key20G,
|
||||
Key20B,
|
||||
Key21R,
|
||||
Key21G,
|
||||
Key21B,
|
||||
Key22R,
|
||||
Key22G,
|
||||
Key22B,
|
||||
Key23R,
|
||||
Key23G,
|
||||
Key23B,
|
||||
Key24R,
|
||||
Key24G,
|
||||
Key24B,
|
||||
Key25R,
|
||||
Key25G,
|
||||
Key25B,
|
||||
Key26R,
|
||||
Key26G,
|
||||
Key26B,
|
||||
Key27R,
|
||||
Key27G,
|
||||
Key27B,
|
||||
Key28R,
|
||||
Key28G,
|
||||
Key28B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::nost {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
Key4,
|
||||
Key5,
|
||||
Key6,
|
||||
Key7,
|
||||
Key8,
|
||||
Key9,
|
||||
Key10,
|
||||
Key11,
|
||||
Key12,
|
||||
Key13,
|
||||
Key14,
|
||||
Key15,
|
||||
Key16,
|
||||
Key17,
|
||||
Key18,
|
||||
Key19,
|
||||
Key20,
|
||||
Key21,
|
||||
Key22,
|
||||
Key23,
|
||||
Key24,
|
||||
Key25,
|
||||
Key26,
|
||||
Key27,
|
||||
Key28,
|
||||
};
|
||||
}
|
||||
|
||||
// all analogs in correct order
|
||||
namespace Analogs {
|
||||
enum {
|
||||
Key1,
|
||||
Key2,
|
||||
Key3,
|
||||
Key4,
|
||||
Key5,
|
||||
Key6,
|
||||
Key7,
|
||||
Key8,
|
||||
Key9,
|
||||
Key10,
|
||||
Key11,
|
||||
Key12,
|
||||
Key13,
|
||||
Key14,
|
||||
Key15,
|
||||
Key16,
|
||||
Key17,
|
||||
Key18,
|
||||
Key19,
|
||||
Key20,
|
||||
Key21,
|
||||
Key22,
|
||||
Key23,
|
||||
Key24,
|
||||
Key25,
|
||||
Key26,
|
||||
Key27,
|
||||
Key28,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
BottomR,
|
||||
BottomG,
|
||||
BottomB,
|
||||
Key1R,
|
||||
Key1G,
|
||||
Key1B,
|
||||
Key2R,
|
||||
Key2G,
|
||||
Key2B,
|
||||
Key3R,
|
||||
Key3G,
|
||||
Key3B,
|
||||
Key4R,
|
||||
Key4G,
|
||||
Key4B,
|
||||
Key5R,
|
||||
Key5G,
|
||||
Key5B,
|
||||
Key6R,
|
||||
Key6G,
|
||||
Key6B,
|
||||
Key7R,
|
||||
Key7G,
|
||||
Key7B,
|
||||
Key8R,
|
||||
Key8G,
|
||||
Key8B,
|
||||
Key9R,
|
||||
Key9G,
|
||||
Key9B,
|
||||
Key10R,
|
||||
Key10G,
|
||||
Key10B,
|
||||
Key11R,
|
||||
Key11G,
|
||||
Key11B,
|
||||
Key12R,
|
||||
Key12G,
|
||||
Key12B,
|
||||
Key13R,
|
||||
Key13G,
|
||||
Key13B,
|
||||
Key14R,
|
||||
Key14G,
|
||||
Key14B,
|
||||
Key15R,
|
||||
Key15G,
|
||||
Key15B,
|
||||
Key16R,
|
||||
Key16G,
|
||||
Key16B,
|
||||
Key17R,
|
||||
Key17G,
|
||||
Key17B,
|
||||
Key18R,
|
||||
Key18G,
|
||||
Key18B,
|
||||
Key19R,
|
||||
Key19G,
|
||||
Key19B,
|
||||
Key20R,
|
||||
Key20G,
|
||||
Key20B,
|
||||
Key21R,
|
||||
Key21G,
|
||||
Key21B,
|
||||
Key22R,
|
||||
Key22G,
|
||||
Key22B,
|
||||
Key23R,
|
||||
Key23G,
|
||||
Key23B,
|
||||
Key24R,
|
||||
Key24G,
|
||||
Key24B,
|
||||
Key25R,
|
||||
Key25G,
|
||||
Key25B,
|
||||
Key26R,
|
||||
Key26G,
|
||||
Key26B,
|
||||
Key27R,
|
||||
Key27G,
|
||||
Key27B,
|
||||
Key28R,
|
||||
Key28G,
|
||||
Key28B,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Analog> &get_analogs();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+46
-46
@@ -1,46 +1,46 @@
|
||||
// enable touch functions - set version to windows 7
|
||||
// mingw otherwise doesn't load touch stuff
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include "nost.h"
|
||||
#include "hooks/setupapihook.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
#include "avs/game.h"
|
||||
|
||||
namespace games::nost {
|
||||
|
||||
NostGame::NostGame() : Game("Nostalgia") {
|
||||
}
|
||||
|
||||
void NostGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// fake touchscreen
|
||||
///////////////////
|
||||
|
||||
SETUPAPI_SETTINGS touch_settings{};
|
||||
|
||||
// GUID must be set to 0 to make SETUPAPI hook working
|
||||
touch_settings.class_guid[0] = 0x00000000;
|
||||
touch_settings.class_guid[1] = 0x00000000;
|
||||
touch_settings.class_guid[2] = 0x00000000;
|
||||
touch_settings.class_guid[3] = 0x00000000;
|
||||
|
||||
/*
|
||||
* set hardware ID containing VID and PID
|
||||
* there is 3 known VID/PID combinations known to the game:
|
||||
* VID_04DD&PID_97CB
|
||||
* VID_0EEF&PID_C000
|
||||
* VID_29BD&PID_4101
|
||||
*/
|
||||
const char touch_hardwareid[] = "VID_29BD&PID_4101";
|
||||
memcpy(touch_settings.property_hardwareid, touch_hardwareid, sizeof(touch_hardwareid));
|
||||
|
||||
// apply settings
|
||||
setupapihook_init(avs::game::DLL_INSTANCE);
|
||||
setupapihook_add(touch_settings);
|
||||
|
||||
// custom touch
|
||||
wintouchemu::hook("nostalgia", avs::game::DLL_INSTANCE);
|
||||
}
|
||||
}
|
||||
// enable touch functions - set version to windows 7
|
||||
// mingw otherwise doesn't load touch stuff
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include "nost.h"
|
||||
#include "hooks/setupapihook.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
#include "avs/game.h"
|
||||
|
||||
namespace games::nost {
|
||||
|
||||
NostGame::NostGame() : Game("Nostalgia") {
|
||||
}
|
||||
|
||||
void NostGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// fake touchscreen
|
||||
///////////////////
|
||||
|
||||
SETUPAPI_SETTINGS touch_settings{};
|
||||
|
||||
// GUID must be set to 0 to make SETUPAPI hook working
|
||||
touch_settings.class_guid[0] = 0x00000000;
|
||||
touch_settings.class_guid[1] = 0x00000000;
|
||||
touch_settings.class_guid[2] = 0x00000000;
|
||||
touch_settings.class_guid[3] = 0x00000000;
|
||||
|
||||
/*
|
||||
* set hardware ID containing VID and PID
|
||||
* there is 3 known VID/PID combinations known to the game:
|
||||
* VID_04DD&PID_97CB
|
||||
* VID_0EEF&PID_C000
|
||||
* VID_29BD&PID_4101
|
||||
*/
|
||||
const char touch_hardwareid[] = "VID_29BD&PID_4101";
|
||||
memcpy(touch_settings.property_hardwareid, touch_hardwareid, sizeof(touch_hardwareid));
|
||||
|
||||
// apply settings
|
||||
setupapihook_init(avs::game::DLL_INSTANCE);
|
||||
setupapihook_add(touch_settings);
|
||||
|
||||
// custom touch
|
||||
wintouchemu::hook("nostalgia", avs::game::DLL_INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::nost {
|
||||
|
||||
class NostGame : public games::Game {
|
||||
public:
|
||||
NostGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::nost {
|
||||
|
||||
class NostGame : public games::Game {
|
||||
public:
|
||||
NostGame();
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+40
-40
@@ -1,40 +1,40 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::otoca::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Otoca D'or");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Button Left",
|
||||
"Button Right",
|
||||
"Lever Up",
|
||||
"Lever Down",
|
||||
"Lever Left",
|
||||
"Lever Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::otoca::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Otoca D'or");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Left Button",
|
||||
"Right Button"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::otoca::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Otoca D'or");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Button Left",
|
||||
"Button Right",
|
||||
"Lever Up",
|
||||
"Lever Down",
|
||||
"Lever Left",
|
||||
"Lever Right"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::otoca::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Otoca D'or");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Left Button",
|
||||
"Right Button"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+34
-34
@@ -1,34 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
ButtonLeft,
|
||||
ButtonRight,
|
||||
LeverUp,
|
||||
LeverDown,
|
||||
LeverLeft,
|
||||
LeverRight,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
LeftButton,
|
||||
RightButton,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
ButtonLeft,
|
||||
ButtonRight,
|
||||
LeverUp,
|
||||
LeverDown,
|
||||
LeverLeft,
|
||||
LeverRight,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
LeftButton,
|
||||
RightButton,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+27
-27
@@ -1,27 +1,27 @@
|
||||
#include "otoca.h"
|
||||
#include "p4io.h"
|
||||
#include "games/shared/printer.h"
|
||||
#include "util/libutils.h"
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
OtocaGame::OtocaGame() : Game("Otoca D'or") {
|
||||
}
|
||||
|
||||
OtocaGame::~OtocaGame() {
|
||||
}
|
||||
|
||||
void OtocaGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
/*
|
||||
* arkkep.dll uses LoadLibrary to access game.dll
|
||||
* we preload it so that hooks (e.g. for graphics) will work
|
||||
*/
|
||||
libutils::try_library("game.dll");
|
||||
|
||||
// initialize IO hooks
|
||||
p4io_hook();
|
||||
games::shared::printer_attach();
|
||||
}
|
||||
}
|
||||
#include "otoca.h"
|
||||
#include "p4io.h"
|
||||
#include "games/shared/printer.h"
|
||||
#include "util/libutils.h"
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
OtocaGame::OtocaGame() : Game("Otoca D'or") {
|
||||
}
|
||||
|
||||
OtocaGame::~OtocaGame() {
|
||||
}
|
||||
|
||||
void OtocaGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
/*
|
||||
* arkkep.dll uses LoadLibrary to access game.dll
|
||||
* we preload it so that hooks (e.g. for graphics) will work
|
||||
*/
|
||||
libutils::try_library("game.dll");
|
||||
|
||||
// initialize IO hooks
|
||||
p4io_hook();
|
||||
games::shared::printer_attach();
|
||||
}
|
||||
}
|
||||
|
||||
+14
-14
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
class OtocaGame : public games::Game {
|
||||
public:
|
||||
OtocaGame();
|
||||
~OtocaGame() override;
|
||||
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
class OtocaGame : public games::Game {
|
||||
public:
|
||||
OtocaGame();
|
||||
~OtocaGame() override;
|
||||
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+133
-133
@@ -1,133 +1,133 @@
|
||||
#include "p4io.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/detour.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "acio/icca/icca.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
// button mapping
|
||||
static size_t MAPPING[] {
|
||||
~0u,
|
||||
Buttons::Test,
|
||||
Buttons::Service,
|
||||
Buttons::CoinMech,
|
||||
~0u,
|
||||
Buttons::LeverUp,
|
||||
Buttons::LeverDown,
|
||||
Buttons::LeverLeft,
|
||||
Buttons::LeverRight,
|
||||
Buttons::ButtonLeft,
|
||||
Buttons::ButtonRight,
|
||||
~0u,
|
||||
~0u,
|
||||
};
|
||||
static uint8_t INPUT_STATE[std::size(MAPPING)] {};
|
||||
static uint8_t *CARD_DATA = nullptr;
|
||||
|
||||
static int __cdecl P4io_Boot_step() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __cdecl P4ioInputIsOn(int input_no) {
|
||||
if (input_no < (int) std::size(MAPPING)) {
|
||||
return INPUT_STATE[input_no] > 0 && INPUT_STATE[input_no] < 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl P4ioInputIsOnTrg(int input_no) {
|
||||
if (input_no < (int) std::size(MAPPING)) {
|
||||
return INPUT_STATE[input_no] == 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl P4ioInputIsOffTrg(int input_no) {
|
||||
if (input_no < (int) std::size(MAPPING)) {
|
||||
return INPUT_STATE[input_no] == 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __cdecl P4ioInput_Polling() {
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
for (size_t i = 0; i < std::size(MAPPING); i++) {
|
||||
if (MAPPING[i] != ~0u) {
|
||||
|
||||
// reset release event
|
||||
if (INPUT_STATE[i] == 3) {
|
||||
INPUT_STATE[i] = 0;
|
||||
}
|
||||
|
||||
// apply new button state
|
||||
auto state = GameAPI::Buttons::getState(RI_MGR, buttons.at(MAPPING[i]));
|
||||
if (state && INPUT_STATE[i] < 2) {
|
||||
INPUT_STATE[i]++;
|
||||
} else if (!state && INPUT_STATE[i] > 0 && INPUT_STATE[i] < 3) {
|
||||
INPUT_STATE[i] = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __cdecl P4ioOutputPolling(uint32_t data) {
|
||||
auto &lights = get_lights();
|
||||
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(Lights::LeftButton), (data & 1) ? 1.f : 0.f);
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(Lights::RightButton), (data & 2) ? 1.f : 0.f);
|
||||
|
||||
RI_MGR->devices_flush_output();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl P4ioCoinCount() {
|
||||
return eamuse_coin_get_stock();
|
||||
}
|
||||
|
||||
static bool __cdecl P4ioInputIsICCardHold() {
|
||||
bool kb_insert_press = false;
|
||||
|
||||
// eamio keypress
|
||||
kb_insert_press |= eamuse_get_keypad_state(0) & (1 << EAM_IO_INSERT);
|
||||
|
||||
// check for card
|
||||
if (CARD_DATA == nullptr && (eamuse_card_insert_consume(1, 0) || kb_insert_press)) {
|
||||
auto card = new uint8_t[8];
|
||||
if (!eamuse_get_card(1, 0, card)) {
|
||||
|
||||
// invalid card found
|
||||
delete[] card;
|
||||
|
||||
} else {
|
||||
CARD_DATA = card;
|
||||
}
|
||||
}
|
||||
|
||||
// check if hold
|
||||
return CARD_DATA != nullptr;
|
||||
}
|
||||
|
||||
static void __cdecl P4ioInputIsICCardRead(uint8_t *data) {
|
||||
if (CARD_DATA != nullptr) {
|
||||
memcpy(data, CARD_DATA, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void p4io_hook() {
|
||||
detour::iat_try("?P4io_Boot_step@@YA?AW4P4IO_STATUS@@XZ", P4io_Boot_step);
|
||||
detour::iat_try("?P4ioInputIsOn@@YAHH@Z", P4ioInputIsOn);
|
||||
detour::iat_try("?P4ioInputIsOnTrg@@YAHH@Z", P4ioInputIsOnTrg);
|
||||
detour::iat_try("?P4ioInputIsOffTrg@@YAHH@Z", P4ioInputIsOffTrg);
|
||||
detour::iat_try("?P4ioInput_Polling@@YAXXZ", P4ioInput_Polling);
|
||||
detour::iat_try("?P4ioOutputPolling@@YAHU_P4IO_POLLING_DATA_t@@@Z", P4ioOutputPolling);
|
||||
detour::iat_try("?P4ioCoinCount@@YAHXZ", P4ioCoinCount);
|
||||
detour::iat_try("?P4ioInputIsICCardHold@@YA_NXZ", (void*) P4ioInputIsICCardHold);
|
||||
detour::iat_try("?P4ioInputIsICCardRead@@YAXPAU_P4IO_ICCARDDATA@@@Z", P4ioInputIsICCardRead);
|
||||
}
|
||||
}
|
||||
#include "p4io.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/detour.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "acio/icca/icca.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
// button mapping
|
||||
static size_t MAPPING[] {
|
||||
~0u,
|
||||
Buttons::Test,
|
||||
Buttons::Service,
|
||||
Buttons::CoinMech,
|
||||
~0u,
|
||||
Buttons::LeverUp,
|
||||
Buttons::LeverDown,
|
||||
Buttons::LeverLeft,
|
||||
Buttons::LeverRight,
|
||||
Buttons::ButtonLeft,
|
||||
Buttons::ButtonRight,
|
||||
~0u,
|
||||
~0u,
|
||||
};
|
||||
static uint8_t INPUT_STATE[std::size(MAPPING)] {};
|
||||
static uint8_t *CARD_DATA = nullptr;
|
||||
|
||||
static int __cdecl P4io_Boot_step() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __cdecl P4ioInputIsOn(int input_no) {
|
||||
if (input_no < (int) std::size(MAPPING)) {
|
||||
return INPUT_STATE[input_no] > 0 && INPUT_STATE[input_no] < 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl P4ioInputIsOnTrg(int input_no) {
|
||||
if (input_no < (int) std::size(MAPPING)) {
|
||||
return INPUT_STATE[input_no] == 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool __cdecl P4ioInputIsOffTrg(int input_no) {
|
||||
if (input_no < (int) std::size(MAPPING)) {
|
||||
return INPUT_STATE[input_no] == 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __cdecl P4ioInput_Polling() {
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
for (size_t i = 0; i < std::size(MAPPING); i++) {
|
||||
if (MAPPING[i] != ~0u) {
|
||||
|
||||
// reset release event
|
||||
if (INPUT_STATE[i] == 3) {
|
||||
INPUT_STATE[i] = 0;
|
||||
}
|
||||
|
||||
// apply new button state
|
||||
auto state = GameAPI::Buttons::getState(RI_MGR, buttons.at(MAPPING[i]));
|
||||
if (state && INPUT_STATE[i] < 2) {
|
||||
INPUT_STATE[i]++;
|
||||
} else if (!state && INPUT_STATE[i] > 0 && INPUT_STATE[i] < 3) {
|
||||
INPUT_STATE[i] = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __cdecl P4ioOutputPolling(uint32_t data) {
|
||||
auto &lights = get_lights();
|
||||
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(Lights::LeftButton), (data & 1) ? 1.f : 0.f);
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(Lights::RightButton), (data & 2) ? 1.f : 0.f);
|
||||
|
||||
RI_MGR->devices_flush_output();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl P4ioCoinCount() {
|
||||
return eamuse_coin_get_stock();
|
||||
}
|
||||
|
||||
static bool __cdecl P4ioInputIsICCardHold() {
|
||||
bool kb_insert_press = false;
|
||||
|
||||
// eamio keypress
|
||||
kb_insert_press |= eamuse_get_keypad_state(0) & (1 << EAM_IO_INSERT);
|
||||
|
||||
// check for card
|
||||
if (CARD_DATA == nullptr && (eamuse_card_insert_consume(1, 0) || kb_insert_press)) {
|
||||
auto card = new uint8_t[8];
|
||||
if (!eamuse_get_card(1, 0, card)) {
|
||||
|
||||
// invalid card found
|
||||
delete[] card;
|
||||
|
||||
} else {
|
||||
CARD_DATA = card;
|
||||
}
|
||||
}
|
||||
|
||||
// check if hold
|
||||
return CARD_DATA != nullptr;
|
||||
}
|
||||
|
||||
static void __cdecl P4ioInputIsICCardRead(uint8_t *data) {
|
||||
if (CARD_DATA != nullptr) {
|
||||
memcpy(data, CARD_DATA, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void p4io_hook() {
|
||||
detour::iat_try("?P4io_Boot_step@@YA?AW4P4IO_STATUS@@XZ", P4io_Boot_step);
|
||||
detour::iat_try("?P4ioInputIsOn@@YAHH@Z", P4ioInputIsOn);
|
||||
detour::iat_try("?P4ioInputIsOnTrg@@YAHH@Z", P4ioInputIsOnTrg);
|
||||
detour::iat_try("?P4ioInputIsOffTrg@@YAHH@Z", P4ioInputIsOffTrg);
|
||||
detour::iat_try("?P4ioInput_Polling@@YAXXZ", P4ioInput_Polling);
|
||||
detour::iat_try("?P4ioOutputPolling@@YAHU_P4IO_POLLING_DATA_t@@@Z", P4ioOutputPolling);
|
||||
detour::iat_try("?P4ioCoinCount@@YAHXZ", P4ioCoinCount);
|
||||
detour::iat_try("?P4ioInputIsICCardHold@@YA_NXZ", (void*) P4ioInputIsICCardHold);
|
||||
detour::iat_try("?P4ioInputIsICCardRead@@YAXPAU_P4IO_ICCARDDATA@@@Z", P4ioInputIsICCardRead);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
void p4io_hook();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
namespace games::otoca {
|
||||
|
||||
void p4io_hook();
|
||||
}
|
||||
|
||||
+22
-22
@@ -1,22 +1,22 @@
|
||||
#include "io.h"
|
||||
|
||||
namespace games::pcm {
|
||||
std::vector <Button> &get_buttons() {
|
||||
static std::vector <Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Charge Machine");
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Insert 1000 Yen Bill",
|
||||
"Insert 2000 Yen Bill",
|
||||
"Insert 5000 Yen Bill",
|
||||
"Insert 10000 Yen Bill"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
namespace games::pcm {
|
||||
std::vector <Button> &get_buttons() {
|
||||
static std::vector <Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Charge Machine");
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Insert 1000 Yen Bill",
|
||||
"Insert 2000 Yen Bill",
|
||||
"Insert 5000 Yen Bill",
|
||||
"Insert 10000 Yen Bill"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
|
||||
+20
-20
@@ -1,20 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::pcm {
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Insert1000YenBill,
|
||||
Insert2000YenBill,
|
||||
Insert5000YenBill,
|
||||
Insert10000YenBill,
|
||||
};
|
||||
}
|
||||
|
||||
std::vector <Button> &get_buttons();
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::pcm {
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Insert1000YenBill,
|
||||
Insert2000YenBill,
|
||||
Insert5000YenBill,
|
||||
Insert10000YenBill,
|
||||
};
|
||||
}
|
||||
|
||||
std::vector <Button> &get_buttons();
|
||||
};
|
||||
|
||||
+118
-118
@@ -1,118 +1,118 @@
|
||||
#include "pcm.h"
|
||||
|
||||
#include "io.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/utils.h"
|
||||
#include "util/libutils.h"
|
||||
|
||||
namespace games::pcm {
|
||||
uint32_t *(__cdecl *GsIo_GetState_orig)(uint32_t *state);
|
||||
|
||||
static int BillKind = 0;
|
||||
|
||||
static int __cdecl BillVali_GetEscrowBillKind() {
|
||||
return BillKind;
|
||||
}
|
||||
|
||||
static int __cdecl BillVali_GetCurrentStep() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl BillVali_GetError() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char __cdecl BillVali_IsEscrowNow() {
|
||||
auto &buttons = games::pcm::get_buttons();
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert1000YenBill])) {
|
||||
log_misc("pcm", "1000 yen bill inserted");
|
||||
BillKind = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert2000YenBill])) {
|
||||
log_misc("pcm", "2000 yen bill inserted");
|
||||
BillKind = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert5000YenBill])) {
|
||||
log_misc("pcm", "5000 yen bill inserted");
|
||||
BillKind = 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert10000YenBill])) {
|
||||
log_misc("pcm", "10000 yen bill inserted");
|
||||
BillKind = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_IsIdling() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_IsReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_IsWaiting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int __cdecl BillVali_GetReceivedBill() {
|
||||
static int bills_received = 0;
|
||||
|
||||
return ++bills_received;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_ReceiveBill(int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t* __cdecl GsIo_GetState_hook(uint32_t *state) {
|
||||
GsIo_GetState_orig(state);
|
||||
|
||||
// "bill validator is happy" flag :]
|
||||
*state |= 4;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PCMGame::PCMGame() : Game("Charge Machine") {}
|
||||
|
||||
void PCMGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// system.dll doesn't get loaded until later so load it now for hooking.
|
||||
HMODULE system = libutils::try_library("system.dll");
|
||||
|
||||
// apply hooks
|
||||
detour::trampoline("system.dll", "?GetState@GsIo@@SA?BVSTATE@1@XZ",
|
||||
GsIo_GetState_hook, &GsIo_GetState_orig);
|
||||
|
||||
detour::inline_hook(BillVali_GetCurrentStep, libutils::try_proc(
|
||||
system, "?GetCurrentStep@GsBillVali@@SAHXZ"));
|
||||
detour::inline_hook(BillVali_GetError, libutils::try_proc(
|
||||
system, "?GetError@GsBillVali@@SAHXZ"));
|
||||
detour::inline_hook(BillVali_GetReceivedBill, libutils::try_proc(
|
||||
system, "?GetReceivedBill@GsBillVali@@SAHXZ"));
|
||||
detour::inline_hook(BillVali_IsEscrowNow, libutils::try_proc(
|
||||
system, "?IsEscrowNow@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_IsIdling, libutils::try_proc(
|
||||
system, "?IsIdling@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_IsWaiting, libutils::try_proc(
|
||||
system, "?IsWaiting@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_IsReady, libutils::try_proc(
|
||||
system, "?IsReady@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_ReceiveBill, libutils::try_proc(
|
||||
system, "?ReceiveBill@GsBillVali@@SA_NH@Z"));
|
||||
detour::inline_hook(BillVali_GetEscrowBillKind, libutils::try_proc(
|
||||
system, "?GetEscrowBillKind@GsBillVali@@SAHXZ"));
|
||||
}
|
||||
}
|
||||
#include "pcm.h"
|
||||
|
||||
#include "io.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/utils.h"
|
||||
#include "util/libutils.h"
|
||||
|
||||
namespace games::pcm {
|
||||
uint32_t *(__cdecl *GsIo_GetState_orig)(uint32_t *state);
|
||||
|
||||
static int BillKind = 0;
|
||||
|
||||
static int __cdecl BillVali_GetEscrowBillKind() {
|
||||
return BillKind;
|
||||
}
|
||||
|
||||
static int __cdecl BillVali_GetCurrentStep() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl BillVali_GetError() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char __cdecl BillVali_IsEscrowNow() {
|
||||
auto &buttons = games::pcm::get_buttons();
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert1000YenBill])) {
|
||||
log_misc("pcm", "1000 yen bill inserted");
|
||||
BillKind = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert2000YenBill])) {
|
||||
log_misc("pcm", "2000 yen bill inserted");
|
||||
BillKind = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert5000YenBill])) {
|
||||
log_misc("pcm", "5000 yen bill inserted");
|
||||
BillKind = 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::pcm::Buttons::Insert10000YenBill])) {
|
||||
log_misc("pcm", "10000 yen bill inserted");
|
||||
BillKind = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_IsIdling() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_IsReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_IsWaiting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int __cdecl BillVali_GetReceivedBill() {
|
||||
static int bills_received = 0;
|
||||
|
||||
return ++bills_received;
|
||||
}
|
||||
|
||||
static bool __cdecl BillVali_ReceiveBill(int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t* __cdecl GsIo_GetState_hook(uint32_t *state) {
|
||||
GsIo_GetState_orig(state);
|
||||
|
||||
// "bill validator is happy" flag :]
|
||||
*state |= 4;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PCMGame::PCMGame() : Game("Charge Machine") {}
|
||||
|
||||
void PCMGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// system.dll doesn't get loaded until later so load it now for hooking.
|
||||
HMODULE system = libutils::try_library("system.dll");
|
||||
|
||||
// apply hooks
|
||||
detour::trampoline("system.dll", "?GetState@GsIo@@SA?BVSTATE@1@XZ",
|
||||
GsIo_GetState_hook, &GsIo_GetState_orig);
|
||||
|
||||
detour::inline_hook(BillVali_GetCurrentStep, libutils::try_proc(
|
||||
system, "?GetCurrentStep@GsBillVali@@SAHXZ"));
|
||||
detour::inline_hook(BillVali_GetError, libutils::try_proc(
|
||||
system, "?GetError@GsBillVali@@SAHXZ"));
|
||||
detour::inline_hook(BillVali_GetReceivedBill, libutils::try_proc(
|
||||
system, "?GetReceivedBill@GsBillVali@@SAHXZ"));
|
||||
detour::inline_hook(BillVali_IsEscrowNow, libutils::try_proc(
|
||||
system, "?IsEscrowNow@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_IsIdling, libutils::try_proc(
|
||||
system, "?IsIdling@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_IsWaiting, libutils::try_proc(
|
||||
system, "?IsWaiting@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_IsReady, libutils::try_proc(
|
||||
system, "?IsReady@GsBillVali@@SA_NXZ"));
|
||||
detour::inline_hook(BillVali_ReceiveBill, libutils::try_proc(
|
||||
system, "?ReceiveBill@GsBillVali@@SA_NH@Z"));
|
||||
detour::inline_hook(BillVali_GetEscrowBillKind, libutils::try_proc(
|
||||
system, "?GetEscrowBillKind@GsBillVali@@SAHXZ"));
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::pcm {
|
||||
class PCMGame : public Game {
|
||||
public:
|
||||
PCMGame();
|
||||
|
||||
void attach() override;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::pcm {
|
||||
class PCMGame : public Game {
|
||||
public:
|
||||
PCMGame();
|
||||
|
||||
void attach() override;
|
||||
};
|
||||
}
|
||||
+94
-94
@@ -1,94 +1,94 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::popn::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Pop'n Music");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Button 1",
|
||||
"Button 2",
|
||||
"Button 3",
|
||||
"Button 4",
|
||||
"Button 5",
|
||||
"Button 6",
|
||||
"Button 7",
|
||||
"Button 8",
|
||||
"Button 9"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::popn::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Pop'n Music");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Button 1",
|
||||
"Button 2",
|
||||
"Button 3",
|
||||
"Button 4",
|
||||
"Button 5",
|
||||
"Button 6",
|
||||
"Button 7",
|
||||
"Button 8",
|
||||
"Button 9",
|
||||
"Top LED 1",
|
||||
"Top LED 2",
|
||||
"Top LED 3",
|
||||
"Top LED 4",
|
||||
"Top LED 5",
|
||||
"Top LED 6",
|
||||
"Top LED 7",
|
||||
"Top LED 8",
|
||||
"Top LED 9",
|
||||
"Top LED 10",
|
||||
"Top LED 11",
|
||||
"Top LED 12",
|
||||
"Top LED 13",
|
||||
"Top LED 14",
|
||||
"Top LED 15",
|
||||
"Top LED 16",
|
||||
"Top LED 17",
|
||||
"Top LED 18",
|
||||
"Top LED 19",
|
||||
"Top LED 20",
|
||||
"Top LED 21",
|
||||
"Top LED 22",
|
||||
"Top LED 23",
|
||||
"Top LED 24",
|
||||
"Top LED 25",
|
||||
"Top LED 26",
|
||||
"Top LED 27",
|
||||
"Top LED 28",
|
||||
"Top LED 29",
|
||||
"Top LED 30",
|
||||
"Top LED 31",
|
||||
"Top LED 32",
|
||||
"Top LED R",
|
||||
"Top LED G",
|
||||
"Top LED B",
|
||||
"Hi Lamp 1",
|
||||
"Hi Lamp 2",
|
||||
"Hi Lamp 3",
|
||||
"Hi Lamp 4",
|
||||
"Hi Lamp 5",
|
||||
"Left Lamp 1",
|
||||
"Left Lamp 2",
|
||||
"Right Lamp 1",
|
||||
"Right Lamp 2"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::popn::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Pop'n Music");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Coin Mech",
|
||||
"Button 1",
|
||||
"Button 2",
|
||||
"Button 3",
|
||||
"Button 4",
|
||||
"Button 5",
|
||||
"Button 6",
|
||||
"Button 7",
|
||||
"Button 8",
|
||||
"Button 9"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::popn::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Pop'n Music");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Button 1",
|
||||
"Button 2",
|
||||
"Button 3",
|
||||
"Button 4",
|
||||
"Button 5",
|
||||
"Button 6",
|
||||
"Button 7",
|
||||
"Button 8",
|
||||
"Button 9",
|
||||
"Top LED 1",
|
||||
"Top LED 2",
|
||||
"Top LED 3",
|
||||
"Top LED 4",
|
||||
"Top LED 5",
|
||||
"Top LED 6",
|
||||
"Top LED 7",
|
||||
"Top LED 8",
|
||||
"Top LED 9",
|
||||
"Top LED 10",
|
||||
"Top LED 11",
|
||||
"Top LED 12",
|
||||
"Top LED 13",
|
||||
"Top LED 14",
|
||||
"Top LED 15",
|
||||
"Top LED 16",
|
||||
"Top LED 17",
|
||||
"Top LED 18",
|
||||
"Top LED 19",
|
||||
"Top LED 20",
|
||||
"Top LED 21",
|
||||
"Top LED 22",
|
||||
"Top LED 23",
|
||||
"Top LED 24",
|
||||
"Top LED 25",
|
||||
"Top LED 26",
|
||||
"Top LED 27",
|
||||
"Top LED 28",
|
||||
"Top LED 29",
|
||||
"Top LED 30",
|
||||
"Top LED 31",
|
||||
"Top LED 32",
|
||||
"Top LED R",
|
||||
"Top LED G",
|
||||
"Top LED B",
|
||||
"Hi Lamp 1",
|
||||
"Hi Lamp 2",
|
||||
"Hi Lamp 3",
|
||||
"Hi Lamp 4",
|
||||
"Hi Lamp 5",
|
||||
"Left Lamp 1",
|
||||
"Left Lamp 2",
|
||||
"Right Lamp 1",
|
||||
"Right Lamp 2"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+88
-88
@@ -1,88 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
Button7,
|
||||
Button8,
|
||||
Button9,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
Button7,
|
||||
Button8,
|
||||
Button9,
|
||||
TopLED1,
|
||||
TopLED2,
|
||||
TopLED3,
|
||||
TopLED4,
|
||||
TopLED5,
|
||||
TopLED6,
|
||||
TopLED7,
|
||||
TopLED8,
|
||||
TopLED9,
|
||||
TopLED10,
|
||||
TopLED11,
|
||||
TopLED12,
|
||||
TopLED13,
|
||||
TopLED14,
|
||||
TopLED15,
|
||||
TopLED16,
|
||||
TopLED17,
|
||||
TopLED18,
|
||||
TopLED19,
|
||||
TopLED20,
|
||||
TopLED21,
|
||||
TopLED22,
|
||||
TopLED23,
|
||||
TopLED24,
|
||||
TopLED25,
|
||||
TopLED26,
|
||||
TopLED27,
|
||||
TopLED28,
|
||||
TopLED29,
|
||||
TopLED30,
|
||||
TopLED31,
|
||||
TopLED32,
|
||||
TopLED_R,
|
||||
TopLED_G,
|
||||
TopLED_B,
|
||||
HiLamp1,
|
||||
HiLamp2,
|
||||
HiLamp3,
|
||||
HiLamp4,
|
||||
HiLamp5,
|
||||
LeftLamp1,
|
||||
LeftLamp2,
|
||||
RightLamp1,
|
||||
RightLamp2,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
CoinMech,
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
Button7,
|
||||
Button8,
|
||||
Button9,
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
Button7,
|
||||
Button8,
|
||||
Button9,
|
||||
TopLED1,
|
||||
TopLED2,
|
||||
TopLED3,
|
||||
TopLED4,
|
||||
TopLED5,
|
||||
TopLED6,
|
||||
TopLED7,
|
||||
TopLED8,
|
||||
TopLED9,
|
||||
TopLED10,
|
||||
TopLED11,
|
||||
TopLED12,
|
||||
TopLED13,
|
||||
TopLED14,
|
||||
TopLED15,
|
||||
TopLED16,
|
||||
TopLED17,
|
||||
TopLED18,
|
||||
TopLED19,
|
||||
TopLED20,
|
||||
TopLED21,
|
||||
TopLED22,
|
||||
TopLED23,
|
||||
TopLED24,
|
||||
TopLED25,
|
||||
TopLED26,
|
||||
TopLED27,
|
||||
TopLED28,
|
||||
TopLED29,
|
||||
TopLED30,
|
||||
TopLED31,
|
||||
TopLED32,
|
||||
TopLED_R,
|
||||
TopLED_G,
|
||||
TopLED_B,
|
||||
HiLamp1,
|
||||
HiLamp2,
|
||||
HiLamp3,
|
||||
HiLamp4,
|
||||
HiLamp5,
|
||||
LeftLamp1,
|
||||
LeftLamp2,
|
||||
RightLamp1,
|
||||
RightLamp2,
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+299
-299
@@ -1,299 +1,299 @@
|
||||
#include "avs/game.h"
|
||||
#include "popn.h"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/utils.h"
|
||||
#include "cfg/button.h"
|
||||
#include "cfg/api.h"
|
||||
#include "hooks/sleephook.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "launcher/logger.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "io.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
static int __cdecl usbCheckAlive() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __cdecl usbCheckSecurityNew() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinGet() {
|
||||
return eamuse_coin_get_stock();
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinMode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbFirmResult() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetKEYID() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetSecurity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbLamp(uint32_t lamp_bits) {
|
||||
|
||||
// get lights
|
||||
auto &lights = get_lights();
|
||||
|
||||
// bit scan
|
||||
static const size_t mapping[] = {
|
||||
Lights::Button1,
|
||||
Lights::Button2,
|
||||
Lights::Button3,
|
||||
Lights::Button4,
|
||||
Lights::Button5,
|
||||
Lights::Button6,
|
||||
Lights::Button7,
|
||||
Lights::Button8,
|
||||
Lights::Button9,
|
||||
Lights::HiLamp1,
|
||||
Lights::HiLamp2,
|
||||
Lights::HiLamp3,
|
||||
Lights::HiLamp4,
|
||||
Lights::HiLamp5,
|
||||
Lights::LeftLamp1,
|
||||
Lights::LeftLamp2,
|
||||
Lights::RightLamp1,
|
||||
Lights::RightLamp2,
|
||||
};
|
||||
|
||||
// sw lamps
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
float value = (lamp_bits & (1 << (i + 23))) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
|
||||
}
|
||||
// neon lamps
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
float value = (lamp_bits & (1 << i)) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i + 9]), value);
|
||||
}
|
||||
// screen lamps
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
float value = (lamp_bits & (1 << (i + 8))) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i + 14]), value);
|
||||
}
|
||||
|
||||
// flush output
|
||||
RI_MGR->devices_flush_output();
|
||||
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadRead(unsigned int *pad_bits) {
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// reset
|
||||
*pad_bits = 0;
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service))) {
|
||||
*pad_bits |= 1 << 6;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test))) {
|
||||
*pad_bits |= 1 << 7;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::CoinMech))) {
|
||||
*pad_bits |= 1 << 22;
|
||||
}
|
||||
|
||||
// buttons
|
||||
static const size_t mapping[] = {
|
||||
Buttons::Button1,
|
||||
Buttons::Button2,
|
||||
Buttons::Button3,
|
||||
Buttons::Button4,
|
||||
Buttons::Button5,
|
||||
Buttons::Button6,
|
||||
Buttons::Button7,
|
||||
Buttons::Button8,
|
||||
Buttons::Button9,
|
||||
};
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(mapping[i]))) {
|
||||
*pad_bits |= 1 << (8 + i);
|
||||
}
|
||||
}
|
||||
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadReadLast(uint8_t *a1) {
|
||||
memset(a1, 0, 40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInitDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearch() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearchDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelect() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelectDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSetExtIo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtReset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStartDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static decltype(DeleteFileA)* DeleteFileA_real = nullptr;
|
||||
|
||||
static BOOL WINAPI DeleteFileA_hook(LPCSTR lpFileName) {
|
||||
|
||||
// fantasia deletes a bunch of drmfs files in dll_entry_init
|
||||
if (string_begins_with(lpFileName, "D:\\L39\\contents")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return DeleteFileA_real(lpFileName);
|
||||
}
|
||||
|
||||
static decltype(mixerSetControlDetails)* mixerSetControlDetails_real = nullptr;
|
||||
|
||||
static MMRESULT WINAPI mixerSetControlDetails_hook(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
|
||||
|
||||
mixerSetControlDetails_real(hmxobj, pmxcd, fdwDetails);
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
static bool log_hook(void *user, const std::string &data, logger::Style style, std::string &out) {
|
||||
|
||||
// get rid of the log spam
|
||||
if (data.find(" I:CabinetSettingFile: label:") != std::string::npos) {
|
||||
out.clear();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
POPNGame::POPNGame() : Game("Pop'n Music") {
|
||||
logger::hook_add(log_hook, this);
|
||||
}
|
||||
|
||||
POPNGame::~POPNGame() {
|
||||
logger::hook_remove(log_hook, this);
|
||||
}
|
||||
|
||||
void POPNGame::pre_attach() {
|
||||
Game::pre_attach();
|
||||
|
||||
// load without resolving references
|
||||
// makes game not trigger DLLMain which results in an error due to missing EZUSB device
|
||||
LoadLibraryExW((MODULE_PATH / "ezusb.dll").c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
|
||||
}
|
||||
|
||||
void POPNGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
/*
|
||||
* Fast Boot (TM) Patch
|
||||
* Game tries to create some directories and if it fails it will sleep for 1 second
|
||||
* We make it sleep 1ms each time instead
|
||||
*/
|
||||
hooks::sleep::init(999, 1);
|
||||
|
||||
DeleteFileA_real = detour::iat_try("DeleteFileA", DeleteFileA_hook, avs::game::DLL_INSTANCE);
|
||||
mixerSetControlDetails_real = detour::iat_try("mixerSetControlDetails", mixerSetControlDetails_hook, avs::game::DLL_INSTANCE);
|
||||
|
||||
// EZUSB hooks
|
||||
HINSTANCE ezusb = libutils::try_library("ezusb.dll");
|
||||
if (ezusb) {
|
||||
detour::inline_hook((void *) usbCheckAlive,
|
||||
libutils::try_proc(ezusb, "?usbCheckAlive@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbCheckSecurityNew,
|
||||
libutils::try_proc(ezusb, "?usbCheckSecurityNew@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinGet,
|
||||
libutils::try_proc(ezusb, "?usbCoinGet@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinMode,
|
||||
libutils::try_proc(ezusb, "?usbCoinMode@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbEnd,
|
||||
libutils::try_proc(ezusb, "?usbEnd@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbFirmResult,
|
||||
libutils::try_proc(ezusb, "?usbFirmResult@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbGetKEYID,
|
||||
libutils::try_proc(ezusb, "?usbGetKEYID@@YAHPAEH@Z"));
|
||||
detour::inline_hook((void *) usbGetSecurity,
|
||||
libutils::try_proc(ezusb, "?usbGetSecurity@@YAHHPAE@Z"));
|
||||
detour::inline_hook((void *) usbLamp,
|
||||
libutils::try_proc(ezusb, "?usbLamp@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbPadRead,
|
||||
libutils::try_proc(ezusb, "?usbPadRead@@YAHPAK@Z"));
|
||||
detour::inline_hook((void *) usbPadReadLast,
|
||||
libutils::try_proc(ezusb, "?usbPadReadLast@@YAHPAE@Z"));
|
||||
detour::inline_hook((void *) usbSecurityInit,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInit@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecurityInitDone,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInitDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearch,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearch@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearchDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearchDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySelect,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelect@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbSecuritySelectDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelectDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSetExtIo,
|
||||
libutils::try_proc(ezusb, "?usbSetExtIo@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbStart,
|
||||
libutils::try_proc(ezusb, "?usbStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtReset,
|
||||
libutils::try_proc(ezusb, "?usbWdtReset@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbWdtStart,
|
||||
libutils::try_proc(ezusb, "?usbWdtStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtStartDone,
|
||||
libutils::try_proc(ezusb, "?usbWdtStartDone@@YAHXZ"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "avs/game.h"
|
||||
#include "popn.h"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/utils.h"
|
||||
#include "cfg/button.h"
|
||||
#include "cfg/api.h"
|
||||
#include "hooks/sleephook.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "launcher/logger.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "io.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
static int __cdecl usbCheckAlive() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __cdecl usbCheckSecurityNew() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinGet() {
|
||||
return eamuse_coin_get_stock();
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinMode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbFirmResult() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetKEYID() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetSecurity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbLamp(uint32_t lamp_bits) {
|
||||
|
||||
// get lights
|
||||
auto &lights = get_lights();
|
||||
|
||||
// bit scan
|
||||
static const size_t mapping[] = {
|
||||
Lights::Button1,
|
||||
Lights::Button2,
|
||||
Lights::Button3,
|
||||
Lights::Button4,
|
||||
Lights::Button5,
|
||||
Lights::Button6,
|
||||
Lights::Button7,
|
||||
Lights::Button8,
|
||||
Lights::Button9,
|
||||
Lights::HiLamp1,
|
||||
Lights::HiLamp2,
|
||||
Lights::HiLamp3,
|
||||
Lights::HiLamp4,
|
||||
Lights::HiLamp5,
|
||||
Lights::LeftLamp1,
|
||||
Lights::LeftLamp2,
|
||||
Lights::RightLamp1,
|
||||
Lights::RightLamp2,
|
||||
};
|
||||
|
||||
// sw lamps
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
float value = (lamp_bits & (1 << (i + 23))) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
|
||||
}
|
||||
// neon lamps
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
float value = (lamp_bits & (1 << i)) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i + 9]), value);
|
||||
}
|
||||
// screen lamps
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
float value = (lamp_bits & (1 << (i + 8))) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(mapping[i + 14]), value);
|
||||
}
|
||||
|
||||
// flush output
|
||||
RI_MGR->devices_flush_output();
|
||||
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadRead(unsigned int *pad_bits) {
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// reset
|
||||
*pad_bits = 0;
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Service))) {
|
||||
*pad_bits |= 1 << 6;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::Test))) {
|
||||
*pad_bits |= 1 << 7;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(Buttons::CoinMech))) {
|
||||
*pad_bits |= 1 << 22;
|
||||
}
|
||||
|
||||
// buttons
|
||||
static const size_t mapping[] = {
|
||||
Buttons::Button1,
|
||||
Buttons::Button2,
|
||||
Buttons::Button3,
|
||||
Buttons::Button4,
|
||||
Buttons::Button5,
|
||||
Buttons::Button6,
|
||||
Buttons::Button7,
|
||||
Buttons::Button8,
|
||||
Buttons::Button9,
|
||||
};
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(mapping[i]))) {
|
||||
*pad_bits |= 1 << (8 + i);
|
||||
}
|
||||
}
|
||||
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadReadLast(uint8_t *a1) {
|
||||
memset(a1, 0, 40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInitDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearch() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearchDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelect() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelectDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSetExtIo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtReset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStartDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static decltype(DeleteFileA)* DeleteFileA_real = nullptr;
|
||||
|
||||
static BOOL WINAPI DeleteFileA_hook(LPCSTR lpFileName) {
|
||||
|
||||
// fantasia deletes a bunch of drmfs files in dll_entry_init
|
||||
if (string_begins_with(lpFileName, "D:\\L39\\contents")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return DeleteFileA_real(lpFileName);
|
||||
}
|
||||
|
||||
static decltype(mixerSetControlDetails)* mixerSetControlDetails_real = nullptr;
|
||||
|
||||
static MMRESULT WINAPI mixerSetControlDetails_hook(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails) {
|
||||
|
||||
mixerSetControlDetails_real(hmxobj, pmxcd, fdwDetails);
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
static bool log_hook(void *user, const std::string &data, logger::Style style, std::string &out) {
|
||||
|
||||
// get rid of the log spam
|
||||
if (data.find(" I:CabinetSettingFile: label:") != std::string::npos) {
|
||||
out.clear();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
POPNGame::POPNGame() : Game("Pop'n Music") {
|
||||
logger::hook_add(log_hook, this);
|
||||
}
|
||||
|
||||
POPNGame::~POPNGame() {
|
||||
logger::hook_remove(log_hook, this);
|
||||
}
|
||||
|
||||
void POPNGame::pre_attach() {
|
||||
Game::pre_attach();
|
||||
|
||||
// load without resolving references
|
||||
// makes game not trigger DLLMain which results in an error due to missing EZUSB device
|
||||
LoadLibraryExW((MODULE_PATH / "ezusb.dll").c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
|
||||
}
|
||||
|
||||
void POPNGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
/*
|
||||
* Fast Boot (TM) Patch
|
||||
* Game tries to create some directories and if it fails it will sleep for 1 second
|
||||
* We make it sleep 1ms each time instead
|
||||
*/
|
||||
hooks::sleep::init(999, 1);
|
||||
|
||||
DeleteFileA_real = detour::iat_try("DeleteFileA", DeleteFileA_hook, avs::game::DLL_INSTANCE);
|
||||
mixerSetControlDetails_real = detour::iat_try("mixerSetControlDetails", mixerSetControlDetails_hook, avs::game::DLL_INSTANCE);
|
||||
|
||||
// EZUSB hooks
|
||||
HINSTANCE ezusb = libutils::try_library("ezusb.dll");
|
||||
if (ezusb) {
|
||||
detour::inline_hook((void *) usbCheckAlive,
|
||||
libutils::try_proc(ezusb, "?usbCheckAlive@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbCheckSecurityNew,
|
||||
libutils::try_proc(ezusb, "?usbCheckSecurityNew@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinGet,
|
||||
libutils::try_proc(ezusb, "?usbCoinGet@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinMode,
|
||||
libutils::try_proc(ezusb, "?usbCoinMode@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbEnd,
|
||||
libutils::try_proc(ezusb, "?usbEnd@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbFirmResult,
|
||||
libutils::try_proc(ezusb, "?usbFirmResult@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbGetKEYID,
|
||||
libutils::try_proc(ezusb, "?usbGetKEYID@@YAHPAEH@Z"));
|
||||
detour::inline_hook((void *) usbGetSecurity,
|
||||
libutils::try_proc(ezusb, "?usbGetSecurity@@YAHHPAE@Z"));
|
||||
detour::inline_hook((void *) usbLamp,
|
||||
libutils::try_proc(ezusb, "?usbLamp@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbPadRead,
|
||||
libutils::try_proc(ezusb, "?usbPadRead@@YAHPAK@Z"));
|
||||
detour::inline_hook((void *) usbPadReadLast,
|
||||
libutils::try_proc(ezusb, "?usbPadReadLast@@YAHPAE@Z"));
|
||||
detour::inline_hook((void *) usbSecurityInit,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInit@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecurityInitDone,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInitDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearch,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearch@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearchDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearchDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySelect,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelect@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbSecuritySelectDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelectDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSetExtIo,
|
||||
libutils::try_proc(ezusb, "?usbSetExtIo@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbStart,
|
||||
libutils::try_proc(ezusb, "?usbStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtReset,
|
||||
libutils::try_proc(ezusb, "?usbWdtReset@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbWdtStart,
|
||||
libutils::try_proc(ezusb, "?usbWdtStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtStartDone,
|
||||
libutils::try_proc(ezusb, "?usbWdtStartDone@@YAHXZ"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-14
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
class POPNGame : public games::Game {
|
||||
public:
|
||||
POPNGame();
|
||||
~POPNGame() override;
|
||||
virtual void pre_attach() override;
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
class POPNGame : public games::Game {
|
||||
public:
|
||||
POPNGame();
|
||||
~POPNGame() override;
|
||||
virtual void pre_attach() override;
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+301
-301
@@ -1,301 +1,301 @@
|
||||
#include "ezusb.h"
|
||||
|
||||
#include "cfg/api.h"
|
||||
#include "cfg/button.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "io.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
static long DISPLAY_SIZE_X = 1360L;
|
||||
static long DISPLAY_SIZE_Y = 768L;
|
||||
|
||||
std::array<bool, 39> TOUCH_STATUS = {};
|
||||
std::array<int, 39> TOUCH_X_COORD = {230, 277, 323, 369, 417, 463, 510, 555, 601, 647, 695, 250, 296, 344, 389, 435, 483, 528, 575, 621, 667, 259, 308, 353, 398, 444, 491, 537, 582, 638, 280, 324, 370, 422, 465, 510, 557, 760, 759};
|
||||
std::array<int, 39> TOUCH_Y_COORD = {642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 813, 813, 813, 813, 813, 813, 813, 813, 813, 894, 894, 894, 894, 894, 894, 894, 771, 886};
|
||||
|
||||
static int __cdecl usbCheckAlive() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __cdecl usbCheckSecurityNew() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinGet() {
|
||||
return eamuse_coin_get_stock();
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinMode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbFirmResult() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetKEYID() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetSecurity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbLamp(uint32_t lamp_bits) {
|
||||
|
||||
// get lights
|
||||
auto &lights = get_lights();
|
||||
|
||||
// mapping
|
||||
static const size_t bits[] = {
|
||||
0x20, 0x40, 0x80,
|
||||
0x08, 0x10, 0x20
|
||||
};
|
||||
static const size_t vals[] = {
|
||||
Lights::LampRed, Lights::LampGreen, Lights::LampBlue,
|
||||
Lights::ButtonLeft, Lights::ButtonRight, Lights::ButtonOK
|
||||
};
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
float value = (lamp_bits & bits[i]) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(vals[i]), value);
|
||||
}
|
||||
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadRead(unsigned int *pad_bits) {
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// reset
|
||||
*pad_bits = 0;
|
||||
|
||||
// mappings
|
||||
static const struct {
|
||||
size_t button, shift;
|
||||
} mappings[] = {
|
||||
{ Buttons::Service, 19 },
|
||||
{ Buttons::Test, 18 },
|
||||
{ Buttons::Select, 17 },
|
||||
{ Buttons::CoinMech, 16 },
|
||||
{ Buttons::Select1, 0 },
|
||||
{ Buttons::Select2, 1 },
|
||||
{ Buttons::OK, 2 },
|
||||
{ Buttons::Left, 6 },
|
||||
{ Buttons::Right, 7 },
|
||||
{ Buttons::TouchKey1, 100 },
|
||||
{ Buttons::TouchKey2, 101 },
|
||||
{ Buttons::TouchKey3, 102 },
|
||||
{ Buttons::TouchKey4, 103 },
|
||||
{ Buttons::TouchKey5, 104 },
|
||||
{ Buttons::TouchKey6, 105 },
|
||||
{ Buttons::TouchKey7, 106 },
|
||||
{ Buttons::TouchKey8, 107 },
|
||||
{ Buttons::TouchKey9, 108 },
|
||||
{ Buttons::TouchKey0, 109 },
|
||||
{ Buttons::TouchKeyDash, 110 },
|
||||
{ Buttons::TouchKeyQ, 111 },
|
||||
{ Buttons::TouchKeyW, 112 },
|
||||
{ Buttons::TouchKeyE, 113 },
|
||||
{ Buttons::TouchKeyR, 114 },
|
||||
{ Buttons::TouchKeyT, 115 },
|
||||
{ Buttons::TouchKeyY, 116 },
|
||||
{ Buttons::TouchKeyU, 117 },
|
||||
{ Buttons::TouchKeyI, 118 },
|
||||
{ Buttons::TouchKeyO, 119 },
|
||||
{ Buttons::TouchKeyP, 120 },
|
||||
{ Buttons::TouchKeyA, 121 },
|
||||
{ Buttons::TouchKeyS, 122 },
|
||||
{ Buttons::TouchKeyD, 123 },
|
||||
{ Buttons::TouchKeyF, 124 },
|
||||
{ Buttons::TouchKeyG, 125 },
|
||||
{ Buttons::TouchKeyH, 126 },
|
||||
{ Buttons::TouchKeyJ, 127 },
|
||||
{ Buttons::TouchKeyK, 128 },
|
||||
{ Buttons::TouchKeyL, 129 },
|
||||
{ Buttons::TouchKeyZ, 130 },
|
||||
{ Buttons::TouchKeyX, 131 },
|
||||
{ Buttons::TouchKeyC, 132 },
|
||||
{ Buttons::TouchKeyV, 133 },
|
||||
{ Buttons::TouchKeyB, 134 },
|
||||
{ Buttons::TouchKeyN, 135 },
|
||||
{ Buttons::TouchKeyM, 136 },
|
||||
{ Buttons::TouchKeyBackspace, 137 },
|
||||
{ Buttons::TouchKeyEnter, 138 }
|
||||
};
|
||||
|
||||
// set buttons
|
||||
for (auto &mapping : mappings) {
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(mapping.button))) {
|
||||
if (mapping.shift > 99) {
|
||||
if (!TOUCH_STATUS[mapping.shift - 100]) {
|
||||
|
||||
static RECT display_rect;
|
||||
GetWindowRect(GetDesktopWindow(), &display_rect);
|
||||
DISPLAY_SIZE_X = display_rect.right - display_rect.left;
|
||||
DISPLAY_SIZE_Y = display_rect.bottom - display_rect.top;
|
||||
|
||||
std::vector<TouchPoint> touch_write;
|
||||
std::vector<DWORD> touch_point_ids;
|
||||
TouchPoint tp {
|
||||
.id = 0,
|
||||
.x = (long)(TOUCH_X_COORD[mapping.shift - 100] * DISPLAY_SIZE_X / 1000),
|
||||
.y = (long)(TOUCH_Y_COORD[mapping.shift - 100] * DISPLAY_SIZE_Y / 1000),
|
||||
.mouse = false,
|
||||
};
|
||||
TOUCH_STATUS[mapping.shift - 100] = true;
|
||||
touch_write.emplace_back(tp);
|
||||
touch_write_points(&touch_write);
|
||||
|
||||
touch_point_ids.emplace_back(0);
|
||||
touch_remove_points(&touch_point_ids);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
*pad_bits |= 1 << mapping.shift;
|
||||
}
|
||||
} else {
|
||||
if (mapping.shift > 99) {
|
||||
TOUCH_STATUS[mapping.shift - 100] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadReadLast(uint8_t *a1) {
|
||||
memset(a1, 0, 40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInitDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearch() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearchDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelect() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelectDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSetExtIo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtReset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStartDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinBlocker(int a1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbMute(int a1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbIsHiSpeed() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ezusb_init() {
|
||||
|
||||
TOUCH_STATUS.fill(false);
|
||||
// load the library
|
||||
HINSTANCE ezusb = libutils::try_library("ezusb.dll");
|
||||
|
||||
// insert hooks
|
||||
if (ezusb) {
|
||||
detour::inline_hook((void *) usbCheckAlive,
|
||||
libutils::try_proc(ezusb, "?usbCheckAlive@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbCheckSecurityNew,
|
||||
libutils::try_proc(ezusb, "?usbCheckSecurityNew@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinGet,
|
||||
libutils::try_proc(ezusb, "?usbCoinGet@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinMode,
|
||||
libutils::try_proc(ezusb, "?usbCoinMode@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbEnd,
|
||||
libutils::try_proc(ezusb, "?usbEnd@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbFirmResult,
|
||||
libutils::try_proc(ezusb, "?usbFirmResult@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbGetKEYID,
|
||||
libutils::try_proc(ezusb, "?usbGetKEYID@@YAHPAEH@Z"));
|
||||
detour::inline_hook((void *) usbGetSecurity,
|
||||
libutils::try_proc(ezusb, "?usbGetSecurity@@YAHHPAE@Z"));
|
||||
detour::inline_hook((void *) usbLamp,
|
||||
libutils::try_proc(ezusb, "?usbLamp@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbPadRead,
|
||||
libutils::try_proc(ezusb, "?usbPadRead@@YAHPAK@Z"));
|
||||
detour::inline_hook((void *) usbPadReadLast,
|
||||
libutils::try_proc(ezusb, "?usbPadReadLast@@YAHPAE@Z"));
|
||||
detour::inline_hook((void *) usbSecurityInit,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInit@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecurityInitDone,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInitDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearch,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearch@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearchDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearchDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySelect,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelect@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbSecuritySelectDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelectDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSetExtIo,
|
||||
libutils::try_proc(ezusb, "?usbSetExtIo@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbStart,
|
||||
libutils::try_proc(ezusb, "?usbStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtReset,
|
||||
libutils::try_proc(ezusb, "?usbWdtReset@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbWdtStart,
|
||||
libutils::try_proc(ezusb, "?usbWdtStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtStartDone,
|
||||
libutils::try_proc(ezusb, "?usbWdtStartDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbCoinBlocker,
|
||||
libutils::try_proc(ezusb, "?usbCoinBlocker@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbMute,
|
||||
libutils::try_proc(ezusb, "?usbMute@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbIsHiSpeed,
|
||||
libutils::try_proc(ezusb, "?usbIsHiSpeed@@YAHXZ"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "ezusb.h"
|
||||
|
||||
#include "cfg/api.h"
|
||||
#include "cfg/button.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "rawinput/rawinput.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/libutils.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
#include "io.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
static long DISPLAY_SIZE_X = 1360L;
|
||||
static long DISPLAY_SIZE_Y = 768L;
|
||||
|
||||
std::array<bool, 39> TOUCH_STATUS = {};
|
||||
std::array<int, 39> TOUCH_X_COORD = {230, 277, 323, 369, 417, 463, 510, 555, 601, 647, 695, 250, 296, 344, 389, 435, 483, 528, 575, 621, 667, 259, 308, 353, 398, 444, 491, 537, 582, 638, 280, 324, 370, 422, 465, 510, 557, 760, 759};
|
||||
std::array<int, 39> TOUCH_Y_COORD = {642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 813, 813, 813, 813, 813, 813, 813, 813, 813, 894, 894, 894, 894, 894, 894, 894, 771, 886};
|
||||
|
||||
static int __cdecl usbCheckAlive() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __cdecl usbCheckSecurityNew() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinGet() {
|
||||
return eamuse_coin_get_stock();
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinMode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbEnd() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbFirmResult() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetKEYID() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbGetSecurity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbLamp(uint32_t lamp_bits) {
|
||||
|
||||
// get lights
|
||||
auto &lights = get_lights();
|
||||
|
||||
// mapping
|
||||
static const size_t bits[] = {
|
||||
0x20, 0x40, 0x80,
|
||||
0x08, 0x10, 0x20
|
||||
};
|
||||
static const size_t vals[] = {
|
||||
Lights::LampRed, Lights::LampGreen, Lights::LampBlue,
|
||||
Lights::ButtonLeft, Lights::ButtonRight, Lights::ButtonOK
|
||||
};
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
float value = (lamp_bits & bits[i]) ? 1.f : 0.f;
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights.at(vals[i]), value);
|
||||
}
|
||||
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadRead(unsigned int *pad_bits) {
|
||||
|
||||
// get buttons
|
||||
auto &buttons = get_buttons();
|
||||
|
||||
// reset
|
||||
*pad_bits = 0;
|
||||
|
||||
// mappings
|
||||
static const struct {
|
||||
size_t button, shift;
|
||||
} mappings[] = {
|
||||
{ Buttons::Service, 19 },
|
||||
{ Buttons::Test, 18 },
|
||||
{ Buttons::Select, 17 },
|
||||
{ Buttons::CoinMech, 16 },
|
||||
{ Buttons::Select1, 0 },
|
||||
{ Buttons::Select2, 1 },
|
||||
{ Buttons::OK, 2 },
|
||||
{ Buttons::Left, 6 },
|
||||
{ Buttons::Right, 7 },
|
||||
{ Buttons::TouchKey1, 100 },
|
||||
{ Buttons::TouchKey2, 101 },
|
||||
{ Buttons::TouchKey3, 102 },
|
||||
{ Buttons::TouchKey4, 103 },
|
||||
{ Buttons::TouchKey5, 104 },
|
||||
{ Buttons::TouchKey6, 105 },
|
||||
{ Buttons::TouchKey7, 106 },
|
||||
{ Buttons::TouchKey8, 107 },
|
||||
{ Buttons::TouchKey9, 108 },
|
||||
{ Buttons::TouchKey0, 109 },
|
||||
{ Buttons::TouchKeyDash, 110 },
|
||||
{ Buttons::TouchKeyQ, 111 },
|
||||
{ Buttons::TouchKeyW, 112 },
|
||||
{ Buttons::TouchKeyE, 113 },
|
||||
{ Buttons::TouchKeyR, 114 },
|
||||
{ Buttons::TouchKeyT, 115 },
|
||||
{ Buttons::TouchKeyY, 116 },
|
||||
{ Buttons::TouchKeyU, 117 },
|
||||
{ Buttons::TouchKeyI, 118 },
|
||||
{ Buttons::TouchKeyO, 119 },
|
||||
{ Buttons::TouchKeyP, 120 },
|
||||
{ Buttons::TouchKeyA, 121 },
|
||||
{ Buttons::TouchKeyS, 122 },
|
||||
{ Buttons::TouchKeyD, 123 },
|
||||
{ Buttons::TouchKeyF, 124 },
|
||||
{ Buttons::TouchKeyG, 125 },
|
||||
{ Buttons::TouchKeyH, 126 },
|
||||
{ Buttons::TouchKeyJ, 127 },
|
||||
{ Buttons::TouchKeyK, 128 },
|
||||
{ Buttons::TouchKeyL, 129 },
|
||||
{ Buttons::TouchKeyZ, 130 },
|
||||
{ Buttons::TouchKeyX, 131 },
|
||||
{ Buttons::TouchKeyC, 132 },
|
||||
{ Buttons::TouchKeyV, 133 },
|
||||
{ Buttons::TouchKeyB, 134 },
|
||||
{ Buttons::TouchKeyN, 135 },
|
||||
{ Buttons::TouchKeyM, 136 },
|
||||
{ Buttons::TouchKeyBackspace, 137 },
|
||||
{ Buttons::TouchKeyEnter, 138 }
|
||||
};
|
||||
|
||||
// set buttons
|
||||
for (auto &mapping : mappings) {
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(mapping.button))) {
|
||||
if (mapping.shift > 99) {
|
||||
if (!TOUCH_STATUS[mapping.shift - 100]) {
|
||||
|
||||
static RECT display_rect;
|
||||
GetWindowRect(GetDesktopWindow(), &display_rect);
|
||||
DISPLAY_SIZE_X = display_rect.right - display_rect.left;
|
||||
DISPLAY_SIZE_Y = display_rect.bottom - display_rect.top;
|
||||
|
||||
std::vector<TouchPoint> touch_write;
|
||||
std::vector<DWORD> touch_point_ids;
|
||||
TouchPoint tp {
|
||||
.id = 0,
|
||||
.x = (long)(TOUCH_X_COORD[mapping.shift - 100] * DISPLAY_SIZE_X / 1000),
|
||||
.y = (long)(TOUCH_Y_COORD[mapping.shift - 100] * DISPLAY_SIZE_Y / 1000),
|
||||
.mouse = false,
|
||||
};
|
||||
TOUCH_STATUS[mapping.shift - 100] = true;
|
||||
touch_write.emplace_back(tp);
|
||||
touch_write_points(&touch_write);
|
||||
|
||||
touch_point_ids.emplace_back(0);
|
||||
touch_remove_points(&touch_point_ids);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
*pad_bits |= 1 << mapping.shift;
|
||||
}
|
||||
} else {
|
||||
if (mapping.shift > 99) {
|
||||
TOUCH_STATUS[mapping.shift - 100] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// return no error
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbPadReadLast(uint8_t *a1) {
|
||||
memset(a1, 0, 40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecurityInitDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearch() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySearchDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelect() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSecuritySelectDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbSetExtIo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtReset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbWdtStartDone() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbCoinBlocker(int a1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbMute(int a1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl usbIsHiSpeed() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ezusb_init() {
|
||||
|
||||
TOUCH_STATUS.fill(false);
|
||||
// load the library
|
||||
HINSTANCE ezusb = libutils::try_library("ezusb.dll");
|
||||
|
||||
// insert hooks
|
||||
if (ezusb) {
|
||||
detour::inline_hook((void *) usbCheckAlive,
|
||||
libutils::try_proc(ezusb, "?usbCheckAlive@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbCheckSecurityNew,
|
||||
libutils::try_proc(ezusb, "?usbCheckSecurityNew@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinGet,
|
||||
libutils::try_proc(ezusb, "?usbCoinGet@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbCoinMode,
|
||||
libutils::try_proc(ezusb, "?usbCoinMode@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbEnd,
|
||||
libutils::try_proc(ezusb, "?usbEnd@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbFirmResult,
|
||||
libutils::try_proc(ezusb, "?usbFirmResult@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbGetKEYID,
|
||||
libutils::try_proc(ezusb, "?usbGetKEYID@@YAHPAEH@Z"));
|
||||
detour::inline_hook((void *) usbGetSecurity,
|
||||
libutils::try_proc(ezusb, "?usbGetSecurity@@YAHHPAE@Z"));
|
||||
detour::inline_hook((void *) usbLamp,
|
||||
libutils::try_proc(ezusb, "?usbLamp@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbPadRead,
|
||||
libutils::try_proc(ezusb, "?usbPadRead@@YAHPAK@Z"));
|
||||
detour::inline_hook((void *) usbPadReadLast,
|
||||
libutils::try_proc(ezusb, "?usbPadReadLast@@YAHPAE@Z"));
|
||||
detour::inline_hook((void *) usbSecurityInit,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInit@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecurityInitDone,
|
||||
libutils::try_proc(ezusb, "?usbSecurityInitDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearch,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearch@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySearchDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySearchDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSecuritySelect,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelect@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbSecuritySelectDone,
|
||||
libutils::try_proc(ezusb, "?usbSecuritySelectDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbSetExtIo,
|
||||
libutils::try_proc(ezusb, "?usbSetExtIo@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbStart,
|
||||
libutils::try_proc(ezusb, "?usbStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtReset,
|
||||
libutils::try_proc(ezusb, "?usbWdtReset@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbWdtStart,
|
||||
libutils::try_proc(ezusb, "?usbWdtStart@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbWdtStartDone,
|
||||
libutils::try_proc(ezusb, "?usbWdtStartDone@@YAHXZ"));
|
||||
detour::inline_hook((void *) usbCoinBlocker,
|
||||
libutils::try_proc(ezusb, "?usbCoinBlocker@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbMute,
|
||||
libutils::try_proc(ezusb, "?usbMute@@YAHH@Z"));
|
||||
detour::inline_hook((void *) usbIsHiSpeed,
|
||||
libutils::try_proc(ezusb, "?usbIsHiSpeed@@YAHXZ"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
void ezusb_init();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
void ezusb_init();
|
||||
}
|
||||
|
||||
+83
-83
@@ -1,83 +1,83 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::qma::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Quiz Magic Academy");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Select",
|
||||
"Coin Mech",
|
||||
"Select 1",
|
||||
"Select 2",
|
||||
"Left",
|
||||
"Right",
|
||||
"OK",
|
||||
"Touch Keyboard - 1",
|
||||
"Touch Keyboard - 2",
|
||||
"Touch Keyboard - 3",
|
||||
"Touch Keyboard - 4",
|
||||
"Touch Keyboard - 5",
|
||||
"Touch Keyboard - 6",
|
||||
"Touch Keyboard - 7",
|
||||
"Touch Keyboard - 8",
|
||||
"Touch Keyboard - 9",
|
||||
"Touch Keyboard - 0",
|
||||
"Touch Keyboard - -",
|
||||
"Touch Keyboard - Q",
|
||||
"Touch Keyboard - W",
|
||||
"Touch Keyboard - E",
|
||||
"Touch Keyboard - R",
|
||||
"Touch Keyboard - T",
|
||||
"Touch Keyboard - Y",
|
||||
"Touch Keyboard - U",
|
||||
"Touch Keyboard - I",
|
||||
"Touch Keyboard - O",
|
||||
"Touch Keyboard - P",
|
||||
"Touch Keyboard - A",
|
||||
"Touch Keyboard - S",
|
||||
"Touch Keyboard - D",
|
||||
"Touch Keyboard - F",
|
||||
"Touch Keyboard - G",
|
||||
"Touch Keyboard - H",
|
||||
"Touch Keyboard - J",
|
||||
"Touch Keyboard - K",
|
||||
"Touch Keyboard - L",
|
||||
"Touch Keyboard - Z",
|
||||
"Touch Keyboard - X",
|
||||
"Touch Keyboard - C",
|
||||
"Touch Keyboard - V",
|
||||
"Touch Keyboard - B",
|
||||
"Touch Keyboard - N",
|
||||
"Touch Keyboard - M",
|
||||
"Touch Keyboard - Backspace",
|
||||
"Touch Keyboard - Enter"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::qma::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Quiz Magic Academy");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Lamp Red",
|
||||
"Lamp Green",
|
||||
"Lamp Blue",
|
||||
"Button Left",
|
||||
"Button Right",
|
||||
"Button OK"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::qma::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Quiz Magic Academy");
|
||||
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test",
|
||||
"Select",
|
||||
"Coin Mech",
|
||||
"Select 1",
|
||||
"Select 2",
|
||||
"Left",
|
||||
"Right",
|
||||
"OK",
|
||||
"Touch Keyboard - 1",
|
||||
"Touch Keyboard - 2",
|
||||
"Touch Keyboard - 3",
|
||||
"Touch Keyboard - 4",
|
||||
"Touch Keyboard - 5",
|
||||
"Touch Keyboard - 6",
|
||||
"Touch Keyboard - 7",
|
||||
"Touch Keyboard - 8",
|
||||
"Touch Keyboard - 9",
|
||||
"Touch Keyboard - 0",
|
||||
"Touch Keyboard - -",
|
||||
"Touch Keyboard - Q",
|
||||
"Touch Keyboard - W",
|
||||
"Touch Keyboard - E",
|
||||
"Touch Keyboard - R",
|
||||
"Touch Keyboard - T",
|
||||
"Touch Keyboard - Y",
|
||||
"Touch Keyboard - U",
|
||||
"Touch Keyboard - I",
|
||||
"Touch Keyboard - O",
|
||||
"Touch Keyboard - P",
|
||||
"Touch Keyboard - A",
|
||||
"Touch Keyboard - S",
|
||||
"Touch Keyboard - D",
|
||||
"Touch Keyboard - F",
|
||||
"Touch Keyboard - G",
|
||||
"Touch Keyboard - H",
|
||||
"Touch Keyboard - J",
|
||||
"Touch Keyboard - K",
|
||||
"Touch Keyboard - L",
|
||||
"Touch Keyboard - Z",
|
||||
"Touch Keyboard - X",
|
||||
"Touch Keyboard - C",
|
||||
"Touch Keyboard - V",
|
||||
"Touch Keyboard - B",
|
||||
"Touch Keyboard - N",
|
||||
"Touch Keyboard - M",
|
||||
"Touch Keyboard - Backspace",
|
||||
"Touch Keyboard - Enter"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::qma::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Quiz Magic Academy");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Lamp Red",
|
||||
"Lamp Green",
|
||||
"Lamp Blue",
|
||||
"Button Left",
|
||||
"Button Right",
|
||||
"Button OK"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+77
-77
@@ -1,77 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Select,
|
||||
CoinMech,
|
||||
Select1,
|
||||
Select2,
|
||||
Left,
|
||||
Right,
|
||||
OK,
|
||||
TouchKey1,
|
||||
TouchKey2,
|
||||
TouchKey3,
|
||||
TouchKey4,
|
||||
TouchKey5,
|
||||
TouchKey6,
|
||||
TouchKey7,
|
||||
TouchKey8,
|
||||
TouchKey9,
|
||||
TouchKey0,
|
||||
TouchKeyDash,
|
||||
TouchKeyQ,
|
||||
TouchKeyW,
|
||||
TouchKeyE,
|
||||
TouchKeyR,
|
||||
TouchKeyT,
|
||||
TouchKeyY,
|
||||
TouchKeyU,
|
||||
TouchKeyI,
|
||||
TouchKeyO,
|
||||
TouchKeyP,
|
||||
TouchKeyA,
|
||||
TouchKeyS,
|
||||
TouchKeyD,
|
||||
TouchKeyF,
|
||||
TouchKeyG,
|
||||
TouchKeyH,
|
||||
TouchKeyJ,
|
||||
TouchKeyK,
|
||||
TouchKeyL,
|
||||
TouchKeyZ,
|
||||
TouchKeyX,
|
||||
TouchKeyC,
|
||||
TouchKeyV,
|
||||
TouchKeyB,
|
||||
TouchKeyN,
|
||||
TouchKeyM,
|
||||
TouchKeyBackspace,
|
||||
TouchKeyEnter
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
LampRed,
|
||||
LampGreen,
|
||||
LampBlue,
|
||||
ButtonLeft,
|
||||
ButtonRight,
|
||||
ButtonOK
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test,
|
||||
Select,
|
||||
CoinMech,
|
||||
Select1,
|
||||
Select2,
|
||||
Left,
|
||||
Right,
|
||||
OK,
|
||||
TouchKey1,
|
||||
TouchKey2,
|
||||
TouchKey3,
|
||||
TouchKey4,
|
||||
TouchKey5,
|
||||
TouchKey6,
|
||||
TouchKey7,
|
||||
TouchKey8,
|
||||
TouchKey9,
|
||||
TouchKey0,
|
||||
TouchKeyDash,
|
||||
TouchKeyQ,
|
||||
TouchKeyW,
|
||||
TouchKeyE,
|
||||
TouchKeyR,
|
||||
TouchKeyT,
|
||||
TouchKeyY,
|
||||
TouchKeyU,
|
||||
TouchKeyI,
|
||||
TouchKeyO,
|
||||
TouchKeyP,
|
||||
TouchKeyA,
|
||||
TouchKeyS,
|
||||
TouchKeyD,
|
||||
TouchKeyF,
|
||||
TouchKeyG,
|
||||
TouchKeyH,
|
||||
TouchKeyJ,
|
||||
TouchKeyK,
|
||||
TouchKeyL,
|
||||
TouchKeyZ,
|
||||
TouchKeyX,
|
||||
TouchKeyC,
|
||||
TouchKeyV,
|
||||
TouchKeyB,
|
||||
TouchKeyN,
|
||||
TouchKeyM,
|
||||
TouchKeyBackspace,
|
||||
TouchKeyEnter
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
LampRed,
|
||||
LampGreen,
|
||||
LampBlue,
|
||||
ButtonLeft,
|
||||
ButtonRight,
|
||||
ButtonOK
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+135
-135
@@ -1,135 +1,135 @@
|
||||
#include "qma.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "games/shared/lcdhandle.h"
|
||||
#include "games/shared/twtouch.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#include "ezusb.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
/**
|
||||
* Overridden touchscreen for attaching the touch hooks to the window.
|
||||
*/
|
||||
class QMATouchDevice : public games::shared::TwTouchDevice {
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override {
|
||||
|
||||
// check if device was opened
|
||||
auto result = TwTouchDevice::open(lpFileName);
|
||||
if (result) {
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
|
||||
// get game window
|
||||
HWND wnd = GetForegroundWindow();
|
||||
if (!string_begins_with(GetActiveWindowTitle(), "QMA")) {
|
||||
wnd = FindWindowBeginsWith("QMA");
|
||||
}
|
||||
|
||||
if (wnd != nullptr) {
|
||||
|
||||
// get client area
|
||||
RECT rect {};
|
||||
GetClientRect(wnd, &rect);
|
||||
|
||||
// remove style borders
|
||||
LONG lStyle = GetWindowLong(wnd, GWL_STYLE);
|
||||
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
|
||||
SetWindowLongPtr(wnd, GWL_STYLE, lStyle);
|
||||
|
||||
// remove ex style borders
|
||||
LONG lExStyle = GetWindowLong(wnd, GWL_EXSTYLE);
|
||||
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
SetWindowLongPtr(wnd, GWL_EXSTYLE, lExStyle);
|
||||
|
||||
// update window
|
||||
AdjustWindowRect(&rect, lStyle, FALSE);
|
||||
SetWindowPos(wnd, nullptr,
|
||||
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
||||
SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
}
|
||||
}
|
||||
|
||||
// attach touch
|
||||
touch_attach_dx_hook();
|
||||
|
||||
// cursor
|
||||
if (!is_touch_available()) {
|
||||
ShowCursor(true);
|
||||
}
|
||||
}
|
||||
|
||||
// return result
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The game likes to crash if E:\LMA\quiz13 does not exist.
|
||||
* Therefore we create it when the game tries to access E:\LMA the first time.
|
||||
*/
|
||||
namespace dirfix {
|
||||
|
||||
static decltype(CreateFileW) *CreateFileW_real = nullptr;
|
||||
|
||||
static HANDLE WINAPI CreateFileW_Hook(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
|
||||
// create quiz directory
|
||||
static bool dirs_created = false;
|
||||
if (!dirs_created && _wcsnicmp(lpFileName, L"E:\\LMA", 6) == 0) {
|
||||
fileutils::dir_create_recursive("E:\\LMA\\quiz11");
|
||||
fileutils::dir_create_recursive("E:\\LMA\\quiz13");
|
||||
fileutils::dir_create_recursive("E:\\LMA\\quiz15");
|
||||
dirs_created = true;
|
||||
}
|
||||
|
||||
// return result
|
||||
return CreateFileW_real(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
}
|
||||
|
||||
void apply() {
|
||||
CreateFileW_real = detour::iat_try("CreateFileW", CreateFileW_Hook);
|
||||
}
|
||||
}
|
||||
|
||||
QMAGame::QMAGame() : Game("Quiz Magic Academy") {
|
||||
}
|
||||
|
||||
void QMAGame::pre_attach() {
|
||||
Game::pre_attach();
|
||||
|
||||
// load without resolving references
|
||||
// makes game not trigger DLLMain since that does some EZUSB device stuff
|
||||
LoadLibraryExW((MODULE_PATH / "ezusb.dll").c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
|
||||
}
|
||||
|
||||
void QMAGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// init device hooks
|
||||
devicehook_init();
|
||||
devicehook_add(new games::shared::LCDHandle());
|
||||
devicehook_add(new games::qma::QMATouchDevice());
|
||||
|
||||
// EZUSB for button input
|
||||
ezusb_init();
|
||||
|
||||
// disable multi-head mode
|
||||
D3D9_BEHAVIOR_DISABLE = D3DCREATE_ADAPTERGROUP_DEVICE;
|
||||
|
||||
// directory fix
|
||||
dirfix::apply();
|
||||
}
|
||||
}
|
||||
#include "qma.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "games/shared/lcdhandle.h"
|
||||
#include "games/shared/twtouch.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "hooks/devicehook.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#include "ezusb.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
/**
|
||||
* Overridden touchscreen for attaching the touch hooks to the window.
|
||||
*/
|
||||
class QMATouchDevice : public games::shared::TwTouchDevice {
|
||||
public:
|
||||
bool open(LPCWSTR lpFileName) override {
|
||||
|
||||
// check if device was opened
|
||||
auto result = TwTouchDevice::open(lpFileName);
|
||||
if (result) {
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
|
||||
// get game window
|
||||
HWND wnd = GetForegroundWindow();
|
||||
if (!string_begins_with(GetActiveWindowTitle(), "QMA")) {
|
||||
wnd = FindWindowBeginsWith("QMA");
|
||||
}
|
||||
|
||||
if (wnd != nullptr) {
|
||||
|
||||
// get client area
|
||||
RECT rect {};
|
||||
GetClientRect(wnd, &rect);
|
||||
|
||||
// remove style borders
|
||||
LONG lStyle = GetWindowLong(wnd, GWL_STYLE);
|
||||
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
|
||||
SetWindowLongPtr(wnd, GWL_STYLE, lStyle);
|
||||
|
||||
// remove ex style borders
|
||||
LONG lExStyle = GetWindowLong(wnd, GWL_EXSTYLE);
|
||||
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
SetWindowLongPtr(wnd, GWL_EXSTYLE, lExStyle);
|
||||
|
||||
// update window
|
||||
AdjustWindowRect(&rect, lStyle, FALSE);
|
||||
SetWindowPos(wnd, nullptr,
|
||||
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
||||
SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
}
|
||||
}
|
||||
|
||||
// attach touch
|
||||
touch_attach_dx_hook();
|
||||
|
||||
// cursor
|
||||
if (!is_touch_available()) {
|
||||
ShowCursor(true);
|
||||
}
|
||||
}
|
||||
|
||||
// return result
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The game likes to crash if E:\LMA\quiz13 does not exist.
|
||||
* Therefore we create it when the game tries to access E:\LMA the first time.
|
||||
*/
|
||||
namespace dirfix {
|
||||
|
||||
static decltype(CreateFileW) *CreateFileW_real = nullptr;
|
||||
|
||||
static HANDLE WINAPI CreateFileW_Hook(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
|
||||
// create quiz directory
|
||||
static bool dirs_created = false;
|
||||
if (!dirs_created && _wcsnicmp(lpFileName, L"E:\\LMA", 6) == 0) {
|
||||
fileutils::dir_create_recursive("E:\\LMA\\quiz11");
|
||||
fileutils::dir_create_recursive("E:\\LMA\\quiz13");
|
||||
fileutils::dir_create_recursive("E:\\LMA\\quiz15");
|
||||
dirs_created = true;
|
||||
}
|
||||
|
||||
// return result
|
||||
return CreateFileW_real(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
}
|
||||
|
||||
void apply() {
|
||||
CreateFileW_real = detour::iat_try("CreateFileW", CreateFileW_Hook);
|
||||
}
|
||||
}
|
||||
|
||||
QMAGame::QMAGame() : Game("Quiz Magic Academy") {
|
||||
}
|
||||
|
||||
void QMAGame::pre_attach() {
|
||||
Game::pre_attach();
|
||||
|
||||
// load without resolving references
|
||||
// makes game not trigger DLLMain since that does some EZUSB device stuff
|
||||
LoadLibraryExW((MODULE_PATH / "ezusb.dll").c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
|
||||
}
|
||||
|
||||
void QMAGame::attach() {
|
||||
Game::attach();
|
||||
|
||||
// init device hooks
|
||||
devicehook_init();
|
||||
devicehook_add(new games::shared::LCDHandle());
|
||||
devicehook_add(new games::qma::QMATouchDevice());
|
||||
|
||||
// EZUSB for button input
|
||||
ezusb_init();
|
||||
|
||||
// disable multi-head mode
|
||||
D3D9_BEHAVIOR_DISABLE = D3DCREATE_ADAPTERGROUP_DEVICE;
|
||||
|
||||
// directory fix
|
||||
dirfix::apply();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
class QMAGame : public games::Game {
|
||||
public:
|
||||
QMAGame();
|
||||
virtual void pre_attach() override;
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::qma {
|
||||
|
||||
class QMAGame : public games::Game {
|
||||
public:
|
||||
QMAGame();
|
||||
virtual void pre_attach() override;
|
||||
virtual void attach() override;
|
||||
};
|
||||
}
|
||||
|
||||
+45
-45
@@ -1,45 +1,45 @@
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::rb::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Reflec Beat");
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::rb::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Reflec Beat");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Pole R",
|
||||
"Pole G",
|
||||
"Pole B",
|
||||
"Escutcheon R",
|
||||
"Escutcheon G",
|
||||
"Escutcheon B",
|
||||
"Woofer R",
|
||||
"Woofer G",
|
||||
"Woofer B",
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Title Up R",
|
||||
"Title Up G",
|
||||
"Title Up B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
#include "io.h"
|
||||
|
||||
std::vector<Button> &games::rb::get_buttons() {
|
||||
static std::vector<Button> buttons;
|
||||
|
||||
if (buttons.empty()) {
|
||||
buttons = GameAPI::Buttons::getButtons("Reflec Beat");
|
||||
GameAPI::Buttons::sortButtons(
|
||||
&buttons,
|
||||
"Service",
|
||||
"Test"
|
||||
);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
std::vector<Light> &games::rb::get_lights() {
|
||||
static std::vector<Light> lights;
|
||||
|
||||
if (lights.empty()) {
|
||||
lights = GameAPI::Lights::getLights("Reflec Beat");
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Pole R",
|
||||
"Pole G",
|
||||
"Pole B",
|
||||
"Escutcheon R",
|
||||
"Escutcheon G",
|
||||
"Escutcheon B",
|
||||
"Woofer R",
|
||||
"Woofer G",
|
||||
"Woofer B",
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
"Title Up R",
|
||||
"Title Up G",
|
||||
"Title Up B"
|
||||
);
|
||||
}
|
||||
|
||||
return lights;
|
||||
}
|
||||
|
||||
+40
-40
@@ -1,40 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::rb {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
PoleR,
|
||||
PoleG,
|
||||
PoleB,
|
||||
EscutcheonR,
|
||||
EscutcheonG,
|
||||
EscutcheonB,
|
||||
WooferR,
|
||||
WooferG,
|
||||
WooferB,
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
TitleUpR,
|
||||
TitleUpG,
|
||||
TitleUpB
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "cfg/api.h"
|
||||
|
||||
namespace games::rb {
|
||||
|
||||
// all buttons in correct order
|
||||
namespace Buttons {
|
||||
enum {
|
||||
Service,
|
||||
Test
|
||||
};
|
||||
}
|
||||
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
PoleR,
|
||||
PoleG,
|
||||
PoleB,
|
||||
EscutcheonR,
|
||||
EscutcheonG,
|
||||
EscutcheonB,
|
||||
WooferR,
|
||||
WooferG,
|
||||
WooferB,
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
TitleUpR,
|
||||
TitleUpG,
|
||||
TitleUpB
|
||||
};
|
||||
}
|
||||
|
||||
// getters
|
||||
std::vector<Button> &get_buttons();
|
||||
std::vector<Light> &get_lights();
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::rb {
|
||||
|
||||
class RBGame : public games::Game {
|
||||
public:
|
||||
RBGame();
|
||||
virtual void attach();
|
||||
virtual void detach();
|
||||
};
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "games/game.h"
|
||||
|
||||
namespace games::rb {
|
||||
|
||||
class RBGame : public games::Game {
|
||||
public:
|
||||
RBGame();
|
||||
virtual void attach();
|
||||
virtual void detach();
|
||||
};
|
||||
}
|
||||
|
||||
+192
-192
@@ -1,192 +1,192 @@
|
||||
#include "touch.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/time.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
static std::string WINDOW_TITLE = "REFLEC BEAT";
|
||||
|
||||
games::rb::ReflecBeatTouchDeviceHandle::ReflecBeatTouchDeviceHandle(bool log_fps) {
|
||||
this->log_fps = log_fps;
|
||||
}
|
||||
|
||||
void games::rb::ReflecBeatTouchDeviceHandle::grid_insert(unsigned char *data, int cursor_x, int cursor_y) {
|
||||
|
||||
// scale to grid position
|
||||
int grid_x = CLAMP((cursor_x * 48) / window_width, 0, 47);
|
||||
int grid_y = CLAMP((cursor_y * 76) / window_height, 0, 75);
|
||||
|
||||
// get bit positions
|
||||
int bit_x = 88 + grid_x;
|
||||
int bit_y = 74 - grid_y;
|
||||
|
||||
// insert bits
|
||||
data[3 + bit_x / 8] |= (char) 1 << (bit_x % 8);
|
||||
data[3 + bit_y / 8] |= (char) 1 << (bit_y % 8);
|
||||
}
|
||||
|
||||
bool games::rb::ReflecBeatTouchDeviceHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// attach touch module
|
||||
HWND wnd = GetForegroundWindow();
|
||||
if (!string_begins_with(GetActiveWindowTitle(), WINDOW_TITLE)) {
|
||||
wnd = FindWindowBeginsWith(WINDOW_TITLE);
|
||||
}
|
||||
|
||||
if (wnd != nullptr) {
|
||||
|
||||
// reset window process to make the game not crash
|
||||
SetWindowLongPtr(wnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(DefWindowProc));
|
||||
|
||||
// check if windowed
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
|
||||
// remove style borders
|
||||
LONG lStyle = GetWindowLong(wnd, GWL_STYLE);
|
||||
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
|
||||
SetWindowLongPtr(wnd, GWL_STYLE, lStyle);
|
||||
|
||||
// remove ex style borders
|
||||
LONG lExStyle = GetWindowLong(wnd, GWL_EXSTYLE);
|
||||
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
SetWindowLongPtr(wnd, GWL_EXSTYLE, lExStyle);
|
||||
|
||||
// update window
|
||||
SetWindowPos(wnd, nullptr, 0, 0, 0, 0,
|
||||
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
|
||||
// create touch window
|
||||
touch_create_wnd(wnd);
|
||||
|
||||
} else {
|
||||
|
||||
// create touch window
|
||||
touch_create_wnd(wnd);
|
||||
|
||||
// show game window because it lost focus
|
||||
ShowWindow(wnd, SW_SHOW);
|
||||
}
|
||||
} else {
|
||||
|
||||
// fallback to dx hook
|
||||
touch_attach_dx_hook();
|
||||
}
|
||||
|
||||
// show cursor on window if mouse is used
|
||||
if (!is_touch_available()) {
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::rb::ReflecBeatTouchDeviceHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 20) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get window
|
||||
HWND window = GetForegroundWindow();
|
||||
if (window == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// update width and height
|
||||
RECT rect {};
|
||||
GetWindowRect(window, &rect);
|
||||
|
||||
// check for landscape (KBR)
|
||||
bool is_landscape = (rect.right - rect.left) > (rect.bottom - rect.top);
|
||||
if (is_landscape) {
|
||||
window_height = rect.right - rect.left;
|
||||
window_width = rect.bottom - rect.top;
|
||||
} else {
|
||||
window_width = rect.right - rect.left;
|
||||
window_height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
// create data
|
||||
unsigned char data[20] {};
|
||||
|
||||
// data header
|
||||
data[0] = 0x55;
|
||||
data[2] = 0x4C;
|
||||
|
||||
// iterate all touch points
|
||||
auto offset_x = (int) (window_width / 48.0 / 3.0);
|
||||
auto offset_y = (int) (window_height / 76.0 / 3.0);
|
||||
std::vector<TouchPoint> touch_points;
|
||||
touch_get_points(touch_points);
|
||||
for (auto &point : touch_points) {
|
||||
|
||||
// get touch point coordinates
|
||||
auto x = point.x;
|
||||
auto y = point.y;
|
||||
|
||||
// rotate touch points for KBR as it runs in landscape
|
||||
if (is_landscape) {
|
||||
x = point.y;
|
||||
y = window_height - point.x;
|
||||
}
|
||||
|
||||
// point scaling
|
||||
auto point_x = (int) ((x - window_width / 2.0) * 48.0 / 54.0 + window_width / 2.0);
|
||||
auto point_y = (int) (y - window_height / 76);
|
||||
|
||||
// insert 9 times with offset to double the precision
|
||||
grid_insert(data, point_x, point_y);
|
||||
grid_insert(data, point_x - offset_x, point_y);
|
||||
grid_insert(data, point_x - offset_x, point_y - offset_y);
|
||||
grid_insert(data, point_x - offset_x, point_y + offset_y);
|
||||
grid_insert(data, point_x + offset_x, point_y);
|
||||
grid_insert(data, point_x + offset_x, point_y + offset_y);
|
||||
grid_insert(data, point_x + offset_x, point_y - offset_y);
|
||||
grid_insert(data, point_x, point_y - offset_y);
|
||||
grid_insert(data, point_x, point_y + offset_y);
|
||||
}
|
||||
|
||||
// copy data to buffer
|
||||
memcpy(lpBuffer, data, 20);
|
||||
|
||||
// update frame logging
|
||||
if (log_fps) {
|
||||
log_frames++;
|
||||
if (log_time < get_system_seconds()) {
|
||||
if (log_time > 0) {
|
||||
log_info("reflecbeat", "polling at {} touch frames per second", log_frames);
|
||||
}
|
||||
log_frames = 0;
|
||||
log_time = get_system_seconds();
|
||||
}
|
||||
}
|
||||
|
||||
// return amount of bytes written
|
||||
return 20;
|
||||
}
|
||||
|
||||
int games::rb::ReflecBeatTouchDeviceHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::rb::ReflecBeatTouchDeviceHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::rb::ReflecBeatTouchDeviceHandle::close() {
|
||||
|
||||
// detach touch module
|
||||
touch_detach();
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "touch.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/time.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
static std::string WINDOW_TITLE = "REFLEC BEAT";
|
||||
|
||||
games::rb::ReflecBeatTouchDeviceHandle::ReflecBeatTouchDeviceHandle(bool log_fps) {
|
||||
this->log_fps = log_fps;
|
||||
}
|
||||
|
||||
void games::rb::ReflecBeatTouchDeviceHandle::grid_insert(unsigned char *data, int cursor_x, int cursor_y) {
|
||||
|
||||
// scale to grid position
|
||||
int grid_x = CLAMP((cursor_x * 48) / window_width, 0, 47);
|
||||
int grid_y = CLAMP((cursor_y * 76) / window_height, 0, 75);
|
||||
|
||||
// get bit positions
|
||||
int bit_x = 88 + grid_x;
|
||||
int bit_y = 74 - grid_y;
|
||||
|
||||
// insert bits
|
||||
data[3 + bit_x / 8] |= (char) 1 << (bit_x % 8);
|
||||
data[3 + bit_y / 8] |= (char) 1 << (bit_y % 8);
|
||||
}
|
||||
|
||||
bool games::rb::ReflecBeatTouchDeviceHandle::open(LPCWSTR lpFileName) {
|
||||
if (wcscmp(lpFileName, L"COM1") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// attach touch module
|
||||
HWND wnd = GetForegroundWindow();
|
||||
if (!string_begins_with(GetActiveWindowTitle(), WINDOW_TITLE)) {
|
||||
wnd = FindWindowBeginsWith(WINDOW_TITLE);
|
||||
}
|
||||
|
||||
if (wnd != nullptr) {
|
||||
|
||||
// reset window process to make the game not crash
|
||||
SetWindowLongPtr(wnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(DefWindowProc));
|
||||
|
||||
// check if windowed
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
|
||||
// remove style borders
|
||||
LONG lStyle = GetWindowLong(wnd, GWL_STYLE);
|
||||
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
|
||||
SetWindowLongPtr(wnd, GWL_STYLE, lStyle);
|
||||
|
||||
// remove ex style borders
|
||||
LONG lExStyle = GetWindowLong(wnd, GWL_EXSTYLE);
|
||||
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
SetWindowLongPtr(wnd, GWL_EXSTYLE, lExStyle);
|
||||
|
||||
// update window
|
||||
SetWindowPos(wnd, nullptr, 0, 0, 0, 0,
|
||||
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
|
||||
// create touch window
|
||||
touch_create_wnd(wnd);
|
||||
|
||||
} else {
|
||||
|
||||
// create touch window
|
||||
touch_create_wnd(wnd);
|
||||
|
||||
// show game window because it lost focus
|
||||
ShowWindow(wnd, SW_SHOW);
|
||||
}
|
||||
} else {
|
||||
|
||||
// fallback to dx hook
|
||||
touch_attach_dx_hook();
|
||||
}
|
||||
|
||||
// show cursor on window if mouse is used
|
||||
if (!is_touch_available()) {
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int games::rb::ReflecBeatTouchDeviceHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
|
||||
|
||||
// check buffer size
|
||||
if (nNumberOfBytesToRead < 20) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get window
|
||||
HWND window = GetForegroundWindow();
|
||||
if (window == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// update width and height
|
||||
RECT rect {};
|
||||
GetWindowRect(window, &rect);
|
||||
|
||||
// check for landscape (KBR)
|
||||
bool is_landscape = (rect.right - rect.left) > (rect.bottom - rect.top);
|
||||
if (is_landscape) {
|
||||
window_height = rect.right - rect.left;
|
||||
window_width = rect.bottom - rect.top;
|
||||
} else {
|
||||
window_width = rect.right - rect.left;
|
||||
window_height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
// create data
|
||||
unsigned char data[20] {};
|
||||
|
||||
// data header
|
||||
data[0] = 0x55;
|
||||
data[2] = 0x4C;
|
||||
|
||||
// iterate all touch points
|
||||
auto offset_x = (int) (window_width / 48.0 / 3.0);
|
||||
auto offset_y = (int) (window_height / 76.0 / 3.0);
|
||||
std::vector<TouchPoint> touch_points;
|
||||
touch_get_points(touch_points);
|
||||
for (auto &point : touch_points) {
|
||||
|
||||
// get touch point coordinates
|
||||
auto x = point.x;
|
||||
auto y = point.y;
|
||||
|
||||
// rotate touch points for KBR as it runs in landscape
|
||||
if (is_landscape) {
|
||||
x = point.y;
|
||||
y = window_height - point.x;
|
||||
}
|
||||
|
||||
// point scaling
|
||||
auto point_x = (int) ((x - window_width / 2.0) * 48.0 / 54.0 + window_width / 2.0);
|
||||
auto point_y = (int) (y - window_height / 76);
|
||||
|
||||
// insert 9 times with offset to double the precision
|
||||
grid_insert(data, point_x, point_y);
|
||||
grid_insert(data, point_x - offset_x, point_y);
|
||||
grid_insert(data, point_x - offset_x, point_y - offset_y);
|
||||
grid_insert(data, point_x - offset_x, point_y + offset_y);
|
||||
grid_insert(data, point_x + offset_x, point_y);
|
||||
grid_insert(data, point_x + offset_x, point_y + offset_y);
|
||||
grid_insert(data, point_x + offset_x, point_y - offset_y);
|
||||
grid_insert(data, point_x, point_y - offset_y);
|
||||
grid_insert(data, point_x, point_y + offset_y);
|
||||
}
|
||||
|
||||
// copy data to buffer
|
||||
memcpy(lpBuffer, data, 20);
|
||||
|
||||
// update frame logging
|
||||
if (log_fps) {
|
||||
log_frames++;
|
||||
if (log_time < get_system_seconds()) {
|
||||
if (log_time > 0) {
|
||||
log_info("reflecbeat", "polling at {} touch frames per second", log_frames);
|
||||
}
|
||||
log_frames = 0;
|
||||
log_time = get_system_seconds();
|
||||
}
|
||||
}
|
||||
|
||||
// return amount of bytes written
|
||||
return 20;
|
||||
}
|
||||
|
||||
int games::rb::ReflecBeatTouchDeviceHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
|
||||
return (int) nNumberOfBytesToWrite;
|
||||
}
|
||||
|
||||
int games::rb::ReflecBeatTouchDeviceHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool games::rb::ReflecBeatTouchDeviceHandle::close() {
|
||||
|
||||
// detach touch module
|
||||
touch_detach();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user