Initial re-upload of spice2x-24-08-24

This commit is contained in:
2024-08-28 11:10:34 -04:00
commit caa9e02285
1181 changed files with 380065 additions and 0 deletions

466
games/drs/drs.cpp Normal file
View File

@@ -0,0 +1,466 @@
#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;
bool DISABLE_TOUCH = false;
bool TRANSPOSE_TOUCH = 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},
};
std::vector<TouchEvent> TOUCH_EVENTS;
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();
}
}
void start_touch() {
std::thread t([] {
log_info("drs", "starting touch input thread");
// main loop
while (TRUE) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
TOUCH_EVENTS.clear();
touch_get_events(TOUCH_EVENTS);
for (auto &te : TOUCH_EVENTS) {
drs_touch_t drs_event;
switch (te.type) {
case TOUCH_DOWN:
drs_event.type = DRS_DOWN;
break;
case TOUCH_UP:
drs_event.type = DRS_UP;
break;
case TOUCH_MOVE:
drs_event.type = DRS_MOVE;
break;
}
drs_event.id = te.id;
// DRS uses 100x100 (px) as default foot size, so use that
const float w = 100.1/1920.f;
const float h = 100.1/1080.f;
drs_event.width = w;
drs_event.height = h;
const float x = te.x / 1920.f;
const float y = te.y / 1080.f;
// note that only x-y are transposed, not w-h
if (TRANSPOSE_TOUCH) {
drs_event.x = y;
drs_event.y = x;
} else {
drs_event.x = x;
drs_event.y = y;
}
drs::fire_touches(&drs_event, 1);
}
}
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);
if (vrutil::STATUS == vrutil::VRStatus::Running) {
start_vr();
} else if (!DISABLE_TOUCH) {
start_touch();
} else {
log_info("drs", "no native input method detected");
}
}
void DRSGame::detach() {
Game::detach();
}
}

56
games/drs/drs.h Normal file
View File

@@ -0,0 +1,56 @@
#pragma once
#include "games/game.h"
#include "external/linalg.h"
#include "touch/touch.h"
namespace games::drs {
enum DRS_TOUCH_TYPE {
DRS_DOWN = 0,
DRS_UP = 1,
DRS_MOVE = 2,
};
typedef struct drs_touch {
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];
extern std::vector<TouchEvent> TOUCH_EVENTS;
extern bool DISABLE_TOUCH;
extern bool TRANSPOSE_TOUCH;
void fire_touches(drs_touch_t *events, size_t event_count);
void start_vr();
void start_touch();
class DRSGame : public games::Game {
public:
DRSGame();
virtual void attach() override;
virtual void detach() override;
};
}

57
games/drs/io.cpp Normal file
View File

@@ -0,0 +1,57 @@
#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,
"P1 Start",
"P1 Menu Up",
"P1 Menu Down",
"P1 Menu Left",
"P1 Menu Right",
"P2 Start",
"P2 Menu Up",
"P2 Menu Down",
"P2 Menu Left",
"P2 Menu Right",
"Card Reader R",
"Card Reader G",
"Card Reader B",
"Title Panel R",
"Title Panel G",
"Title Panel B"
);
}
return lights;
}

52
games/drs/io.h Normal file
View File

@@ -0,0 +1,52 @@
#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 {
P1_START,
P1_MENU_UP,
P1_MENU_DOWN,
P1_MENU_LEFT,
P1_MENU_RIGHT,
P2_START,
P2_MENU_UP,
P2_MENU_DOWN,
P2_MENU_LEFT,
P2_MENU_RIGHT,
CARD_READER_R,
CARD_READER_G,
CARD_READER_B,
TITLE_PANEL_R,
TITLE_PANEL_G,
TITLE_PANEL_B,
};
}
// getters
std::vector<Button> &get_buttons();
std::vector<Light> &get_lights();
}