172 lines
6.5 KiB
C++
172 lines
6.5 KiB
C++
#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 "cfg/configurator.h"
|
|
|
|
#include "io.h"
|
|
|
|
#include "p3io/foot.h"
|
|
#include "p3io/p3io.h"
|
|
#include "p3io/sate.h"
|
|
#include "p3io/usbmem.h"
|
|
|
|
#include "p4io/p4io.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::pre_attach() {
|
|
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::is_model("TDX")) {
|
|
log_fatal(
|
|
"ddr",
|
|
"BAD MODEL NAME ERROR\n\n\n"
|
|
"!!! model name set to TDX, this is WRONG and will break your game !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! spice2x does not yet support TDX, use MDX instead. !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! model name set to TDX, this is WRONG and will break your game !!!\n\n\n"
|
|
);
|
|
}
|
|
|
|
if (!cfg::CONFIGURATOR_STANDALONE && avs::game::DEST[0] == 'U') {
|
|
log_warning(
|
|
"ddr",
|
|
"U-REGION WARNING\n\n\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! <dest> is set to U region !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! While this is legal, unless you have compatible data, this !!!\n"
|
|
"!!! will most likely crash your game or fail to boot. !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! It is recommended that you stick with J region. !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n"
|
|
"!!! !!!\n\n\n"
|
|
);
|
|
}
|
|
}
|
|
|
|
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 if(avs::game::DLL_NAME == "arkmdxp4.dll") {
|
|
devicehook_add(new DDRP4IOHandle());
|
|
} 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));
|
|
|
|
const char settings_detail_p4io[] = R"(\\.\P4IO)";
|
|
|
|
// settings p4io
|
|
SETUPAPI_SETTINGS settingsp4io {};
|
|
settingsp4io.class_guid[0] = 0x8B7250A5;
|
|
settingsp4io.class_guid[1] = 0x46C94F61;
|
|
settingsp4io.class_guid[2] = 0x68E63A84;
|
|
settingsp4io.class_guid[3] = 0x206A4706;
|
|
memcpy(settingsp4io.property_devicedesc, settings_property, strlen(settings_property) + 1);
|
|
memcpy(settingsp4io.interface_detail, settings_detail_p4io, sizeof(settings_detail_p4io));
|
|
|
|
// 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);
|
|
setupapihook_add(settingsp4io);
|
|
|
|
// 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();
|
|
}
|
|
}
|