This commit is contained in:
bicarus-dev
2026-04-18 23:07:10 -07:00
22 changed files with 412 additions and 118 deletions
+122 -20
View File
@@ -35,24 +35,33 @@ struct ICCA_STATUS_LA9 {
static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes"); static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes");
enum ICCA_WORKFLOW { enum ICCA_WORKFLOW {
STEP, STEP = 0,
SLEEP, SLEEP = 1,
START, START = 2,
INIT, INIT = 3,
READY, READY = 4,
GET_USERID, GET_USERID = 5,
ACTIVE, ACTIVE = 6,
EJECT, EJECT = 7,
EJECT_CHECK, EJECT_CHECK = 8,
END, END = 9,
CLOSE_EJECT, CLOSE_EJECT = 10,
CLOSE_E_CHK, CLOSE_E_CHK = 11,
CLOSE_END, CLOSE_END = 12,
ERR_GETUID = -2 ERR_GETUID = -2,
ERR_REMOVED = -11
}; };
// used by RA as the status_code
enum ICCA_STATUS_CODE {
EMPTY = 1,
ENGAGED = 2
};
struct ICCA_UNIT { struct ICCA_UNIT {
struct ICCA_STATUS status {}; struct ICCA_STATUS status {};
enum ICCA_WORKFLOW state = STEP; enum ICCA_WORKFLOW state = STEP;
enum ICCA_WORKFLOW state_jdz = SLEEP;
bool card_cmd_pressed = false; bool card_cmd_pressed = false;
bool card_in = false; bool card_in = false;
double card_in_time = 0.0; double card_in_time = 0.0;
@@ -75,6 +84,11 @@ static inline int icca_get_active_count() {
} }
static inline int icca_get_unit_id(int unit_id) { static inline int icca_get_unit_id(int unit_id) {
// on RA the unit_id is zero-indexed
if (avs::game::is_model("JDZ")) {
return unit_id;
}
if (icca_get_active_count() < 2) if (icca_get_active_count() < 2)
return 1; return 1;
else { else {
@@ -122,9 +136,15 @@ static inline void update_card(int unit_id) {
IS_LAST_CARD_FELICA = is_card_uid_felica(unit->status.uid); IS_LAST_CARD_FELICA = is_card_uid_felica(unit->status.uid);
unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE; unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE;
unit->state_jdz = ACTIVE;
unit->status.error = 0; unit->status.error = 0;
unit->status.front_sensor = 1;
unit->status.rear_sensor = 1;
} else { } else {
unit->state = ERR_GETUID; unit->state = ERR_GETUID;
unit->state_jdz = ERR_GETUID;
unit->status.front_sensor = 1;
unit->status.rear_sensor = 1;
memset(unit->status.uid, 0, 8); memset(unit->status.uid, 0, 8);
} }
unit->card_in = true; unit->card_in = true;
@@ -132,10 +152,25 @@ static inline void update_card(int unit_id) {
} else if (unit->state == EJECT_CHECK) { } else if (unit->state == EJECT_CHECK) {
unit->state = SLEEP; unit->state = SLEEP;
unit->card_in = false; unit->card_in = false;
unit->status.front_sensor = 0;
unit->status.rear_sensor = 0;
} else if (unit->state_jdz == READY) {
unit->state = GET_USERID;
unit->state_jdz = GET_USERID;
unit->status.error = 0;
unit->status.front_sensor = 1;
unit->status.rear_sensor = 1;
unit->card_in = true;
unit->card_in_time = get_performance_seconds();
} }
} else { } else {
unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE; unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE;
if (unit->state_jdz == READY) {
unit->state_jdz = GET_USERID;
}
unit->status.error = 0; unit->status.error = 0;
unit->status.front_sensor = 1;
unit->status.rear_sensor = 1;
unit->card_in = true; unit->card_in = true;
unit->card_in_time = get_performance_seconds(); unit->card_in_time = get_performance_seconds();
} }
@@ -144,6 +179,12 @@ static inline void update_card(int unit_id) {
unit->state = CLOSE_EJECT; unit->state = CLOSE_EJECT;
if (fabs(get_performance_seconds() - unit->card_in_time) > CARD_TIMEOUT) { if (fabs(get_performance_seconds() - unit->card_in_time) > CARD_TIMEOUT) {
unit->card_in = false; unit->card_in = false;
memset(unit->status.uid, 0, 8);
if (unit->state_jdz == ACTIVE || unit->state_jdz == GET_USERID) {
unit->state_jdz = ERR_REMOVED;
}
unit->status.front_sensor = 0;
unit->status.rear_sensor = 0;
} }
} }
@@ -302,7 +343,11 @@ static char __cdecl ac_io_icca_get_status(void *a1, void *a2) {
// copy state to output buffer // copy state to output buffer
ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
unit->status.status_code = unit->state; if (avs::game::is_model("JDZ")) {
unit->status.status_code = unit->card_in ? ENGAGED : EMPTY;
} else {
unit->status.status_code = unit->state;
}
memcpy(status, &unit->status, sizeof(struct ICCA_STATUS)); memcpy(status, &unit->status, sizeof(struct ICCA_STATUS));
// funny workaround // funny workaround
@@ -387,6 +432,11 @@ static char __cdecl ac_io_icca_req_uid(int unit_id) {
static int __cdecl ac_io_icca_req_uid_isfinished(int unit_id, DWORD *read_state) { static int __cdecl ac_io_icca_req_uid_isfinished(int unit_id, DWORD *read_state) {
unit_id = icca_get_unit_id(unit_id); unit_id = icca_get_unit_id(unit_id);
ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
if (avs::game::is_model("JDZ")) {
// hack for RA - only ever seen it as this
*read_state = 8;
return 1;
}
if (unit->card_in) { if (unit->card_in) {
if (fabs(get_performance_seconds() - unit->card_in_time) < CARD_TIMEOUT) { if (fabs(get_performance_seconds() - unit->card_in_time) < CARD_TIMEOUT) {
unit->state = END; unit->state = END;
@@ -403,16 +453,61 @@ static int __cdecl ac_io_icca_send_keep_alive_packet(int a1, int a2, int a3) {
return 0; return 0;
} }
static int __cdecl ac_io_icca_workflow_jdz(int workflow, int unit_id) {
unit_id = icca_get_unit_id(unit_id);
ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
switch (workflow) {
// RA uses "STEP" as more of a polling thing it seems
case STEP:
switch (unit->state_jdz) {
case CLOSE_EJECT:
unit->state_jdz = CLOSE_E_CHK;
break;
case CLOSE_E_CHK:
unit->state_jdz = CLOSE_END;
break;
case CLOSE_END:
unit->state_jdz = SLEEP;
break;
default:
break;
}
break;
case SLEEP:
unit->state = SLEEP;
break;
case START:
unit->state_jdz = INIT;
break;
case INIT:
case READY:
unit->state_jdz = READY;
break;
case CLOSE_EJECT:
unit->state_jdz = CLOSE_EJECT;
return CLOSE_E_CHK;
case CLOSE_END:
unit->state_jdz = SLEEP;
break;
default:
// should probably log a warning here
break;
}
return unit->state_jdz;
}
static int __cdecl ac_io_icca_workflow(int workflow, int unit_id) { static int __cdecl ac_io_icca_workflow(int workflow, int unit_id) {
// RA uses a different workflow process for the slotted readers; treat it differently
if (avs::game::is_model("JDZ")) {
return ac_io_icca_workflow_jdz(workflow, unit_id);
}
unit_id = icca_get_unit_id(unit_id); unit_id = icca_get_unit_id(unit_id);
ICCA_UNIT *unit = &ICCA_UNITS[unit_id]; ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
switch (workflow) { switch (workflow) {
case STEP: case STEP:
if (avs::game::is_model("JDZ")) unit->state = STEP;
unit->state = SLEEP;
else
unit->state = STEP;
break; break;
case SLEEP: case SLEEP:
unit->state = SLEEP; unit->state = SLEEP;
@@ -441,7 +536,6 @@ static int __cdecl ac_io_icca_workflow(int workflow, int unit_id) {
default: default:
break; break;
} }
return unit->state; return unit->state;
} }
@@ -467,6 +561,14 @@ acio::ICCAModule::ICCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModu
void acio::ICCAModule::attach() { void acio::ICCAModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// workaround for RA; ac_io_icca_cardunit_init is never called so treat like both are initialized
if (avs::game::is_model("JDZ")) {
ICCA_UNITS[0].initialized = true;
ICCA_UNITS[1].initialized = true;
CARD_TIMEOUT = 10.0; // keep the card in the slot for longer
}
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_icca_cardunit_init); ACIO_MODULE_HOOK(ac_io_icca_cardunit_init);
ACIO_MODULE_HOOK(ac_io_icca_cardunit_init_isfinished); ACIO_MODULE_HOOK(ac_io_icca_cardunit_init_isfinished);
+1
View File
@@ -60,6 +60,7 @@ namespace cfg {
// window = rectangle including the frame // window = rectangle including the frame
// client = just the content area without frames. // client = just the content area without frames.
bool window_always_on_top = false; bool window_always_on_top = false;
bool window_disable_round_corners = false;
bool client_keep_aspect_ratio = true; bool client_keep_aspect_ratio = true;
bool enable_window_resize = false; bool enable_window_resize = false;
int window_decoration = 0; // enum type WindowDecorationMode int window_decoration = 0; // enum type WindowDecorationMode
+1 -2
View File
@@ -915,8 +915,7 @@ namespace games::iidx {
log_warning( log_warning(
"iidx", "iidx",
"Failed to apply ASIO compatibility fix for iidx32+. " "Failed to apply ASIO compatibility fix for iidx32+. "
"Unless patches are applied, your ASIO device ({}) may hang or fail to work", "Unless patches are applied, your ASIO device may hang or fail to work");
ASIO_DRIVER->c_str());
} else { } else {
log_info( log_info(
"iidx", "iidx",
+1 -1
View File
@@ -475,7 +475,7 @@ namespace games::popn {
const auto data_size = std::min(map.data.capacity(), (size_t)number_of_leds / 3); const auto data_size = std::min(map.data.capacity(), (size_t)number_of_leds / 3);
// pick a color to use // pick a color to use
const auto rgb = tapeledutils::pick_color_from_led_tape((uint8_t *)i_pData, data_size); const auto rgb = tapeledutils::pick_color_from_led_tape(map, (uint8_t *)i_pData, data_size);
// program the lights into API // program the lights into API
auto &lights = get_lights(); auto &lights = get_lights();
+12
View File
@@ -136,6 +136,18 @@ std::vector<Light> &games::popn::get_lights() {
{"Pika", "IC Card R"}, {"Pika", "IC Card R"},
{"Pika", "IC Card G"}, {"Pika", "IC Card G"},
{"Pika", "IC Card B"}, {"Pika", "IC Card B"},
{"Pika", "Speakers R"},
{"Pika", "Speakers G"},
{"Pika", "Speakers B"},
{"Pika", "Monitor R"},
{"Pika", "Monitor G"},
{"Pika", "Monitor B"},
{"Pika", "Control Panel R"},
{"Pika", "Control Panel G"},
{"Pika", "Control Panel B"},
{"Pika", "Cabinet R"},
{"Pika", "Cabinet G"},
{"Pika", "Cabinet B"},
}); });
} }
+12
View File
@@ -121,6 +121,18 @@ namespace games::popn {
IC_Card_R, IC_Card_R,
IC_Card_G, IC_Card_G,
IC_Card_B, IC_Card_B,
Speaker_R,
Speaker_G,
Speaker_B,
Monitor_R,
Monitor_G,
Monitor_B,
ControlPanel_R,
ControlPanel_G,
ControlPanel_B,
Cabinet_R,
Cabinet_G,
Cabinet_B,
} popn_lights_t; } popn_lights_t;
} }
+56 -6
View File
@@ -19,11 +19,13 @@
#include "util/sysutils.h" #include "util/sysutils.h"
#include "io.h" #include "io.h"
#include "util/deferlog.h" #include "util/deferlog.h"
#include "misc/nativetouchhook.h"
#include "misc/wintouchemu.h" #include "misc/wintouchemu.h"
namespace games::popn { namespace games::popn {
bool SHOW_PIKA_MONITOR_WARNING = false; bool SHOW_PIKA_MONITOR_WARNING = false;
bool NATIVE_TOUCH = false;
#if SPICE64 && !SPICE_XP #if SPICE64 && !SPICE_XP
@@ -36,39 +38,83 @@ namespace games::popn {
// pin 1 = left pop (red pop kun), size 16, values 0-0xFF // pin 1 = left pop (red pop kun), size 16, values 0-0xFF
// pin 2 = right pop (blue pop kun), size 16, values 0-0xFF // pin 2 = right pop (blue pop kun), size 16, values 0-0xFF
// pin 3 = title, size 44, values 0-0xFF // pin 3 = title, size 44, values 0-0xFF
// pin 4 = speaker, size 40, values 0-0xFF - U region only // pin 4 = speaker, size 40, values 0-0x7F - U region only
// pin 5 = monitor, size 18, values 0-0x7F - U region only // pin 5 = monitor, size 18, values 0-0x7F - U region only
// pin 6 = control panel, size 28, values 0-0x7F - U region only // pin 6 = control panel, size 28, values 0-0x7F - U region only
// pin 7 = cabinet, size 22, values 0-0x7F - U region only // pin 7 = cabinet, size 22, values 0-0x7F - U region only
tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL] = { tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL] = {
{ {
0, // these are button lights and handled specially // [0] button lights: these are button lights and handled specially
0,
0,
0, 0,
0, 0,
0, 0,
"Invalid" "Invalid"
}, },
{ {
// [1] red pop-kun
5, // 5*3; game reports 16 but make it 15 5, // 5*3; game reports 16 but make it 15
Lights::popn_lights_t::RedPopKun_R, Lights::popn_lights_t::RedPopKun_R,
Lights::popn_lights_t::RedPopKun_G, Lights::popn_lights_t::RedPopKun_G,
Lights::popn_lights_t::RedPopKun_B, Lights::popn_lights_t::RedPopKun_B,
0xFF,
"Red Pop-Kun" "Red Pop-Kun"
}, },
{ {
// [2] blue pop-kun
5, // 5*3; game reports 16 but make it 15 5, // 5*3; game reports 16 but make it 15
Lights::popn_lights_t::BluePopKun_R, Lights::popn_lights_t::BluePopKun_R,
Lights::popn_lights_t::BluePopKun_G, Lights::popn_lights_t::BluePopKun_G,
Lights::popn_lights_t::BluePopKun_B, Lights::popn_lights_t::BluePopKun_B,
0xFF,
"Blue Pop-Kun" "Blue Pop-Kun"
}, },
{ {
14, // 14*3; game reports 44 but make it 42; these are lights above the banner // [3] top LED
14, // 14*3; game reports 44 but make it 42
Lights::popn_lights_t::TopLED_R, Lights::popn_lights_t::TopLED_R,
Lights::popn_lights_t::TopLED_G, Lights::popn_lights_t::TopLED_G,
Lights::popn_lights_t::TopLED_B, Lights::popn_lights_t::TopLED_B,
0xFF,
"Top" "Top"
}, },
{
// [4] speakers
13, // 13*3; game reports 40 but make it 39
Lights::popn_lights_t::Speaker_G,
Lights::popn_lights_t::Speaker_R,
Lights::popn_lights_t::Speaker_B,
0x7F,
"Speakers"
},
{
// [5] monitor
6,
Lights::popn_lights_t::Monitor_G,
Lights::popn_lights_t::Monitor_R,
Lights::popn_lights_t::Monitor_B,
0x7F,
"Monitor"
},
{
// [6] control panel
9, // 9*3; game reports 28
Lights::popn_lights_t::ControlPanel_G,
Lights::popn_lights_t::ControlPanel_R,
Lights::popn_lights_t::ControlPanel_B,
0x7F,
"Control Panel"
},
{
// [7] Cabinet
7, // 7*3; game reports 22
Lights::popn_lights_t::Cabinet_G,
Lights::popn_lights_t::Cabinet_R,
Lights::popn_lights_t::Cabinet_B,
0x7F,
"Cabinet"
},
}; };
@@ -670,9 +716,13 @@ namespace games::popn {
// set third column to 0 and it will work with BIO2 // set third column to 0 and it will work with BIO2
if (!GRAPHICS_WINDOWED) { if (!GRAPHICS_WINDOWED) {
wintouchemu::FORCE = true; if (NATIVE_TOUCH) {
wintouchemu::INJECT_MOUSE_AS_WM_TOUCH = true; nativetouchhook::hook(avs::game::DLL_INSTANCE);
wintouchemu::hook_title_ends("", "Main Screen", avs::game::DLL_INSTANCE); } else {
wintouchemu::FORCE = true;
wintouchemu::INJECT_MOUSE_AS_WM_TOUCH = true;
wintouchemu::hook_title_ends("", "Main Screen", avs::game::DLL_INSTANCE);
}
} }
sysutils::hook_EnumDisplayDevicesA(); sysutils::hook_EnumDisplayDevicesA();
+2 -1
View File
@@ -17,11 +17,12 @@ namespace games::popn {
} }
#if SPICE64 #if SPICE64
constexpr int POPN_TAPELED_TOTAL = 4; constexpr int POPN_TAPELED_TOTAL = 8;
extern tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL]; extern tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL];
#endif #endif
extern bool SHOW_PIKA_MONITOR_WARNING; extern bool SHOW_PIKA_MONITOR_WARNING;
extern bool NATIVE_TOUCH;
class POPNGame : public games::Game { class POPNGame : public games::Game {
public: public:
+11
View File
@@ -476,6 +476,14 @@ static HWND WINAPI CreateWindowExW_hook(DWORD dwExStyle, LPCWSTR lpClassName, LP
} }
} }
// FTT
if (avs::game::is_model("MMD")) {
// set window name
if (!lpWindowName) {
lpWindowName = L"Future TomTom";
}
}
if (GRAPHICS_WINDOWED) { if (GRAPHICS_WINDOWED) {
graphics_window_check_bounds_before_creation(x, y, nWidth, nHeight); graphics_window_check_bounds_before_creation(x, y, nWidth, nHeight);
} }
@@ -924,6 +932,9 @@ void graphics_hook_subscreen_window(HWND hWnd) {
if (GRAPHICS_WSUB_ALWAYS_ON_TOP) { if (GRAPHICS_WSUB_ALWAYS_ON_TOP) {
graphics_update_z_order(hWnd, true); graphics_update_z_order(hWnd, true);
} }
if (GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS) {
graphics_set_corner_preference(hWnd, true);
}
} }
void graphics_screens_register(int screen) { void graphics_screens_register(int screen) {
+5
View File
@@ -7,6 +7,9 @@
#include <windows.h> #include <windows.h>
#include <d3d9.h> #include <d3d9.h>
#if !SPICE_XP
#include <dwmapi.h>
#endif
#include "external/toojpeg/toojpeg.h" #include "external/toojpeg/toojpeg.h"
@@ -50,6 +53,7 @@ extern std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_WINDOW_SIZE;
extern std::optional<std::string> GRAPHICS_WINDOW_POS; extern std::optional<std::string> GRAPHICS_WINDOW_POS;
extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP; extern bool GRAPHICS_WINDOW_ALWAYS_ON_TOP;
extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE; extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE;
extern bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS;
extern std::optional<HWND> GRAPHICS_HOOKED_WINDOW; extern std::optional<HWND> GRAPHICS_HOOKED_WINDOW;
extern bool GRAPHICS_IIDX_WSUB; extern bool GRAPHICS_IIDX_WSUB;
@@ -103,6 +107,7 @@ void graphics_windowed_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
void graphics_capture_initial_window(HWND hWnd); void graphics_capture_initial_window(HWND hWnd);
void graphics_update_window_style(HWND hWnd, bool force_update=false); void graphics_update_window_style(HWND hWnd, bool force_update=false);
void graphics_update_z_order(HWND hWnd, bool always_on_top); void graphics_update_z_order(HWND hWnd, bool always_on_top);
void graphics_set_corner_preference(HWND hWnd, bool disable);
void graphics_move_resize_window(HWND hWnd); void graphics_move_resize_window(HWND hWnd);
bool graphics_window_options_breaks_game(); bool graphics_window_options_breaks_game();
bool graphics_window_decoration_change_crashes_game(); bool graphics_window_decoration_change_crashes_game();
@@ -24,6 +24,7 @@ std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_WINDOW_SIZE;
std::optional<std::string> GRAPHICS_WINDOW_POS; std::optional<std::string> GRAPHICS_WINDOW_POS;
bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false; bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false;
bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false; bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false;
bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = false;
std::optional<HWND> GRAPHICS_HOOKED_WINDOW; std::optional<HWND> GRAPHICS_HOOKED_WINDOW;
// IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed // IIDX Windowed Subscreen - starts out as false, enabled by IIDX module on pre-attach as needed
@@ -132,6 +133,10 @@ void graphics_capture_initial_window(HWND hWnd) {
log_info("graphics-windowed", "[{}] change window z-order - always on top", fmt::ptr(hWnd)); log_info("graphics-windowed", "[{}] change window z-order - always on top", fmt::ptr(hWnd));
graphics_update_z_order(hWnd, true); graphics_update_z_order(hWnd, true);
} }
if (cfg::SCREENRESIZE->window_disable_round_corners) {
log_info("graphics-windowed", "[{}] disabling rounded corners", fmt::ptr(hWnd));
graphics_set_corner_preference(hWnd, true);
}
// ensure spicetouch coordinates are initialized // ensure spicetouch coordinates are initialized
update_spicetouch_window_dimensions(hWnd); update_spicetouch_window_dimensions(hWnd);
@@ -181,6 +186,10 @@ void graphics_load_windowed_parameters() {
cfg::SCREENRESIZE->window_always_on_top = true; cfg::SCREENRESIZE->window_always_on_top = true;
} }
if (GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS) {
cfg::SCREENRESIZE->window_disable_round_corners = true;
}
log_debug("graphics-windowed", "graphics_load_windowed_parameters returned"); log_debug("graphics-windowed", "graphics_load_windowed_parameters returned");
} }
@@ -469,6 +478,27 @@ void graphics_update_z_order(HWND hWnd, bool always_on_top) {
log_debug("graphics-windowed", "graphics_update_z_order returned"); log_debug("graphics-windowed", "graphics_update_z_order returned");
} }
void graphics_set_corner_preference(HWND hWnd, bool disable) {
if (!GRAPHICS_WINDOWED) {
return;
}
#if !SPICE_XP
log_debug("graphics-windowed", "graphics_set_corner_preference called");
DWM_WINDOW_CORNER_PREFERENCE corner_preference = disable ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
DwmSetWindowAttribute(
hWnd,
DWMWA_WINDOW_CORNER_PREFERENCE,
&corner_preference, sizeof(corner_preference));
log_debug("graphics-windowed", "graphics_set_corner_preference returned");
#else
// don't link against DwmSetWindowAttribute on XP
log_debug("graphics-windowed", "graphics_set_corner_preference called; ignoring");
#endif
}
void graphics_move_resize_window(HWND hWnd) { void graphics_move_resize_window(HWND hWnd) {
if (!GRAPHICS_WINDOWED) { if (!GRAPHICS_WINDOWED) {
return; return;
@@ -502,8 +532,8 @@ bool graphics_window_decoration_change_crashes_game() {
static std::once_flag flag; static std::once_flag flag;
static bool result = false; static bool result = false;
std::call_once(flag, []() { std::call_once(flag, []() {
// ddr crashes when frame style changes // ddr and ftt crash when frame style changes
if (avs::game::is_model("MDX")) { if (avs::game::is_model("MDX") || avs::game::is_model("MMD")) {
result = true; result = true;
} }
+5 -3
View File
@@ -597,6 +597,9 @@ int main_implementation(int argc, char *argv[]) {
if (options[launcher::Options::PopnSubMonitorOverride].is_active()) { if (options[launcher::Options::PopnSubMonitorOverride].is_active()) {
sysutils::SECOND_MONITOR_OVERRIDE = options[launcher::Options::PopnSubMonitorOverride].value_text(); sysutils::SECOND_MONITOR_OVERRIDE = options[launcher::Options::PopnSubMonitorOverride].value_text();
} }
if (options[launcher::Options::PopnNativeTouch].value_bool()) {
games::popn::NATIVE_TOUCH = true;
}
if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) { if (options[launcher::Options::LoadMetalGearArcadeModule].value_bool()) {
attach_mga = true; attach_mga = true;
} }
@@ -1117,6 +1120,7 @@ int main_implementation(int argc, char *argv[]) {
} }
GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool(); GRAPHICS_WINDOW_ALWAYS_ON_TOP = options[launcher::Options::spice2x_WindowAlwaysOnTop].value_bool();
GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool(); GRAPHICS_WINDOW_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool();
GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = options[launcher::Options::WindowDisableRoundedCorners].value_bool();
// IIDX/SDVX Windowed Subscreen // IIDX/SDVX Windowed Subscreen
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) { if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) {
@@ -1831,9 +1835,7 @@ int main_implementation(int argc, char *argv[]) {
attach_ftt = true; attach_ftt = true;
// the game is windowed by default unless we set the env // the game is windowed by default unless we set the env
if (GRAPHICS_WINDOWED) { if (!GRAPHICS_WINDOWED) {
GRAPHICS_WINDOWED = false;
} else {
SetEnvironmentVariable("DAMAC_VIEWER_FULLSCREEN", "0"); SetEnvironmentVariable("DAMAC_VIEWER_FULLSCREEN", "0");
} }
+47 -26
View File
@@ -32,6 +32,7 @@ static const std::vector<std::string> CATEGORY_ORDER_BASIC = {
static const std::vector<std::string> CATEGORY_ORDER_ADVANCED = { static const std::vector<std::string> CATEGORY_ORDER_ADVANCED = {
"Game Options (Advanced)", "Game Options (Advanced)",
"Game Options (Peripherals)",
"Overlay", "Overlay",
"Network (Advanced)", "Network (Advanced)",
"Performance", "Performance",
@@ -513,7 +514,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Flip the camera order.", .desc = "Flip the camera order.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// IIDXDisableCameras // IIDXDisableCameras
@@ -523,7 +524,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Bool, .type = OptionType::Bool,
.hidden = true, .hidden = true,
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options", .category = "Game Options (Peripherals)",
}, },
{ {
// IIDXCabCamAccess // IIDXCabCamAccess
@@ -533,7 +534,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
"Only turn this on if you have OFFICIAL arcade cameras connected to the correct USB ports. Default: auto.", "Only turn this on if you have OFFICIAL arcade cameras connected to the correct USB ports. Default: auto.",
.type = OptionType::Enum, .type = OptionType::Enum,
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
.elements = { .elements = {
{"auto", ""}, {"auto", ""},
{"off", ""}, {"off", ""},
@@ -549,7 +550,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Experimental camera support for IIDX 27+ via texture hooking. Requires camera(s) that support YUY2 or NV12 encoding.", .desc = "Experimental camera support for IIDX 27+ via texture hooking. Requires camera(s) that support YUY2 or NV12 encoding.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// IIDXCamHookRatio // IIDXCamHookRatio
@@ -561,7 +562,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Enum, .type = OptionType::Enum,
.hidden = true, .hidden = true,
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
.elements = { .elements = {
{"43", "4:3"}, {"43", "4:3"},
{"169", "16:9"}, {"169", "16:9"},
@@ -579,7 +580,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Text, .type = OptionType::Text,
.setting_name = "0x5817a0,0x6fffbd8,0xbbae40,0xe0,0x30", .setting_name = "0x5817a0,0x6fffbd8,0xbbae40,0xe0,0x30",
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// IIDXCamHookTopId // IIDXCamHookTopId
@@ -594,7 +595,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Text, .type = OptionType::Text,
.setting_name = "vid_1234&pid_5678", .setting_name = "vid_1234&pid_5678",
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// IIDXCamHookFrontId // IIDXCamHookFrontId
@@ -609,7 +610,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Text, .type = OptionType::Text,
.setting_name = "vid_90ab&pid_cdef", .setting_name = "vid_90ab&pid_cdef",
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "IIDX Sound Output Device", .title = "IIDX Sound Output Device",
@@ -772,11 +773,11 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.category = "Game Options (Advanced)", .category = "Game Options (Advanced)",
}, },
{ {
.title = "SDVX Force 720p", .title = "SDVX Vivid Wave Force 720p Window (DEPRECATED - use -windowsize instead)",
.name = "sdvx720", .name = "sdvx720",
.desc = "Force Sound Voltex 720p display mode, used by older games. " .desc = "Old & deprecated option for launching Vivid Wave in 720p when using windowed mode.",
"For newer games, use window resize function instead.",
.type = OptionType::Bool, .type = OptionType::Bool,
.hidden = true,
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Advanced)",
}, },
@@ -786,7 +787,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Enable Sound Voltex printer emulation.", .desc = "Enable Sound Voltex printer emulation.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// SDVXPrinterOutputPath // SDVXPrinterOutputPath
@@ -795,7 +796,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Path to folder where images will be stored.", .desc = "Path to folder where images will be stored.",
.type = OptionType::Text, .type = OptionType::Text,
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
.picker = OptionPickerType::DirectoryPath, .picker = OptionPickerType::DirectoryPath,
}, },
{ {
@@ -804,7 +805,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Clean up saved images in the output directory on startup.", .desc = "Clean up saved images in the output directory on startup.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "SDVX Printer Output Overwrite", .title = "SDVX Printer Output Overwrite",
@@ -812,7 +813,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Always overwrite the same file in output directory.", .desc = "Always overwrite the same file in output directory.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// SDVXPrinterOutputFormat // SDVXPrinterOutputFormat
@@ -822,7 +823,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Text, .type = OptionType::Text,
.setting_name = "(png/bmp/tga/jpg)", .setting_name = "(png/bmp/tga/jpg)",
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "SDVX Printer JPG Quality", .title = "SDVX Printer JPG Quality",
@@ -831,7 +832,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Integer, .type = OptionType::Integer,
.setting_name = "(0-100)", .setting_name = "(0-100)",
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "SDVX Disable Cameras (DEPRECATED - no longer needed)", .title = "SDVX Disable Cameras (DEPRECATED - no longer needed)",
@@ -842,7 +843,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Bool, .type = OptionType::Bool,
.hidden = true, .hidden = true,
.game_name = "Sound Voltex", .game_name = "Sound Voltex",
.category = "Game Options", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "SDVX FS Subscreen Native Touch Handling", .title = "SDVX FS Subscreen Native Touch Handling",
@@ -1008,6 +1009,18 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.category = "Monitor", .category = "Monitor",
.picker = OptionPickerType::Monitor, .picker = OptionPickerType::Monitor,
}, },
{
// PopnNativeTouch
.title = "Pop'n Music PikaPika Native Touch Handling",
.name = "popnnativetouch",
.desc = "Disables touch hooks and lets the game access a touch screen directly. "
"Requires a touch screen to be connected as a secondary monitor. "
"Touch input must be routed to the primary screen via Windows Tablet PC settings. "
"Enable this when you get duplicate touch inputs from an actual touch screen.",
.type = OptionType::Bool,
.game_name = "Pop'n Music",
.category = "Game Options (Advanced)",
},
{ {
.title = "Force Load HELLO! Pop'n Music Module", .title = "Force Load HELLO! Pop'n Music Module",
.name = "hpm", .name = "hpm",
@@ -2218,6 +2231,14 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Bool, .type = OptionType::Bool,
.category = "Graphics (Windowed)", .category = "Graphics (Windowed)",
}, },
{
// WindowDisableRoundedCorners
.title = "Disable Round Window Corners",
.name = "windownoroundcorners",
.desc = "Windows 11 and above only: Disables rounded corners on the game window(s).",
.type = OptionType::Bool,
.category = "Graphics (Windowed)",
},
{ {
// spice2x_IIDXWindowedSubscreenSize // spice2x_IIDXWindowedSubscreenSize
.title = "IIDX Windowed Subscreen Size", .title = "IIDX Windowed Subscreen Size",
@@ -2347,7 +2368,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
"Note: this is NOT for the motion camera - you still need a real RealSense camera for that!", "Note: this is NOT for the motion camera - you still need a real RealSense camera for that!",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "DANCERUSH", .game_name = "DANCERUSH",
.category = "Game Options", .category = "Game Options (Peripherals)",
}, },
{ {
// spice2x_IIDXNativeTouch // spice2x_IIDXNativeTouch
@@ -2681,7 +2702,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Allow game to access camera; camera must be compatible with game.", .desc = "Allow game to access camera; camera must be compatible with game.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "LovePlus", .game_name = "LovePlus",
.category = "Game Options", .category = "Game Options (Peripherals)",
}, },
{ {
// LovePlusPrinterOutputPath // LovePlusPrinterOutputPath
@@ -2690,7 +2711,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Path to folder where images will be stored.", .desc = "Path to folder where images will be stored.",
.type = OptionType::Text, .type = OptionType::Text,
.game_name = "LovePlus", .game_name = "LovePlus",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
.picker = OptionPickerType::DirectoryPath, .picker = OptionPickerType::DirectoryPath,
}, },
{ {
@@ -2699,7 +2720,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Clean up saved images in the output directory on startup.", .desc = "Clean up saved images in the output directory on startup.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "LovePlus", .game_name = "LovePlus",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "LovePlus Printer Output Overwrite", .title = "LovePlus Printer Output Overwrite",
@@ -2707,7 +2728,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.desc = "Always overwrite the same file in output directory.", .desc = "Always overwrite the same file in output directory.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "LovePlus", .game_name = "LovePlus",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// LovePlusPrinterOutputFormat // LovePlusPrinterOutputFormat
@@ -2717,7 +2738,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Text, .type = OptionType::Text,
.setting_name = "(png/bmp/tga/jpg)", .setting_name = "(png/bmp/tga/jpg)",
.game_name = "LovePlus", .game_name = "LovePlus",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
.title = "LovePlus Printer JPG Quality", .title = "LovePlus Printer JPG Quality",
@@ -2726,7 +2747,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
.type = OptionType::Integer, .type = OptionType::Integer,
.setting_name = "(0-100)", .setting_name = "(0-100)",
.game_name = "LovePlus", .game_name = "LovePlus",
.category = "Game Options (Advanced)", .category = "Game Options (Peripherals)",
}, },
{ {
// OptionConflictResolution // OptionConflictResolution
@@ -2747,7 +2768,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
"option to bypass camera error during boot, allowing you to try out the game.", "option to bypass camera error during boot, allowing you to try out the game.",
.type = OptionType::Bool, .type = OptionType::Bool,
.game_name = "Otoca D'or", .game_name = "Otoca D'or",
.category = "Game Options", .category = "Game Options (Peripherals)",
} }
}; };
+2
View File
@@ -101,6 +101,7 @@ namespace launcher {
PopnMusicForceSDMode, PopnMusicForceSDMode,
PopnNoSub, PopnNoSub,
PopnSubMonitorOverride, PopnSubMonitorOverride,
PopnNativeTouch,
LoadHelloPopnMusicModule, LoadHelloPopnMusicModule,
LoadGitaDoraModule, LoadGitaDoraModule,
GitaDoraTwoChannelAudio, GitaDoraTwoChannelAudio,
@@ -232,6 +233,7 @@ namespace launcher {
spice2x_WindowPosition, spice2x_WindowPosition,
spice2x_WindowAlwaysOnTop, spice2x_WindowAlwaysOnTop,
WindowForceScaling, WindowForceScaling,
WindowDisableRoundedCorners,
spice2x_IIDXWindowedSubscreenSize, spice2x_IIDXWindowedSubscreenSize,
spice2x_IIDXWindowedSubscreenPosition, spice2x_IIDXWindowedSubscreenPosition,
IIDXWindowedSubscreenBorderless, IIDXWindowedSubscreenBorderless,
+3 -4
View File
@@ -86,13 +86,12 @@ namespace launcher {
if (LAUNCHER_ARGC > 0) { if (LAUNCHER_ARGC > 0) {
// build cmd line // build cmd line
std::stringstream cmd_line; std::string cmd_line = "START \"\" ";
cmd_line << "START \"\" ";
for (int i = 0; i < LAUNCHER_ARGC; i++) for (int i = 0; i < LAUNCHER_ARGC; i++)
cmd_line << " \"" << LAUNCHER_ARGV[i] << "\""; cmd_line += " \"" + std::string(LAUNCHER_ARGV[i]) + "\"";
// run command // run command
system(cmd_line.str().c_str()); system(cmd_line.c_str());
} }
} }
+31 -12
View File
@@ -17,6 +17,7 @@
#include "external/imgui/misc/cpp/imgui_stdlib.h" #include "external/imgui/misc/cpp/imgui_stdlib.h"
#include "games/io.h" #include "games/io.h"
#include "games/sdvx/sdvx.h" #include "games/sdvx/sdvx.h"
#include "games/popn/popn.h"
#include "avs/core.h" #include "avs/core.h"
#include "avs/ea3.h" #include "avs/ea3.h"
#include "avs/game.h" #include "avs/game.h"
@@ -283,18 +284,8 @@ namespace overlay::windows {
// keypad buttons // keypad buttons
ImGui::TextUnformatted(""); ImGui::TextUnformatted("");
if (this->games_selected_name == "Beatmania IIDX") { this->build_keypad_warning();
ImGui::Indent(INDENT);
ImGui::TextColored(
ImVec4(1, 0.5f, 0.5f, 1.f),
"WARNING: Lightning Model (TDJ) I/O will ignore the keypad!");
ImGui::TextWrapped(
"Use Toggle Sub Screen button to show the overlay and use your mouse, "
"connect using SpiceCompanion app, or connect a touch screen to enter "
"the PIN.");
ImGui::Unindent(INDENT);
ImGui::TextUnformatted("");
}
auto keypad_buttons = games::get_buttons_keypads(this->games_selected_name); auto keypad_buttons = games::get_buttons_keypads(this->games_selected_name);
auto keypad_count = eamuse_get_game_keypads_name(); auto keypad_count = eamuse_get_game_keypads_name();
if (keypad_count == 1) { if (keypad_count == 1) {
@@ -602,6 +593,34 @@ namespace overlay::windows {
} }
} }
void Config::build_keypad_warning() {
// not checking the -iidxtdj option here, we could do that in the future
const bool is_tdj = this->games_selected_name == "Beatmania IIDX";
// not using games::popn::is_pikapika_model() here since that always returns false on 32-bit
const bool is_popn = this->games_selected_name == "Pop'n Music" && avs::game::SPEC[0] == 'D';
if (!is_tdj && !is_popn) {
return;
}
ImGui::Indent(INDENT);
if (is_tdj) {
ImGui::TextColored(
ImVec4(1, 0.5f, 0.5f, 1.f),
"WARNING: Lightning Model (TDJ) I/O will ignore keypad number input!");
} else if (is_popn) {
ImGui::TextColored(
ImVec4(1, 0.5f, 0.5f, 1.f),
"WARNING: PikaPika Pop-Kun model will ignore keypad number input!");
}
ImGui::TextWrapped(
"Use Toggle Sub Screen button (Overlay tab) to show the overlay and use your mouse, "
"connect using SpiceCompanion app, or connect a touch screen to enter "
"the PIN.");
ImGui::Unindent(INDENT);
ImGui::TextUnformatted("");
}
void Config::build_buttons(const std::string &name, std::vector<Button> *buttons, int min, int max) { void Config::build_buttons(const std::string &name, std::vector<Button> *buttons, int min, int max) {
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "%s Buttons", name.c_str()); ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "%s Buttons", name.c_str());
+2
View File
@@ -193,6 +193,8 @@ namespace overlay::windows {
std::vector<Option> *options, const std::string &category, const std::string *filter=nullptr); std::vector<Option> *options, const std::string &category, const std::string *filter=nullptr);
void build_about(); void build_about();
void build_launcher(); void build_launcher();
void build_keypad_warning();
void launch_shell(LPCSTR app, LPCSTR file=nullptr); void launch_shell(LPCSTR app, LPCSTR file=nullptr);
void build_menu(int *game_selected); void build_menu(int *game_selected);
+8 -10
View File
@@ -628,13 +628,12 @@ namespace overlay::windows {
ImGui::Text("Wheel: %ld", mouse->pos_wheel); ImGui::Text("Wheel: %ld", mouse->pos_wheel);
// keys // keys
std::stringstream keys; std::string keys = "[";
keys << "[";
for (auto key : mouse->key_states) { for (auto key : mouse->key_states) {
keys << (key ? "1," : "0,"); keys += (key ? "1," : "0,");
} }
keys << "]"; keys += "]";
ImGui::Text("Keys: %s", keys.str().c_str()); ImGui::Text("Keys: %s", keys.c_str());
break; break;
} }
@@ -643,15 +642,14 @@ namespace overlay::windows {
ImGui::Text("Type: Keyboard"); ImGui::Text("Type: Keyboard");
// keys // keys
std::stringstream keys; std::string keys = "[";
keys << "[";
for (size_t i = 0; i < std::size(keyboard->key_states); i++) { for (size_t i = 0; i < std::size(keyboard->key_states); i++) {
if (keyboard->key_states[i]) { if (keyboard->key_states[i]) {
keys << i << ","; keys += std::to_string(i) + ",";
} }
} }
keys << "]"; keys += "]";
ImGui::Text("Keys: %s", keys.str().c_str()); ImGui::Text("Keys: %s", keys.c_str());
break; break;
} }
+8 -11
View File
@@ -192,8 +192,10 @@ namespace rawinput::touch {
contact_count = std::max(contact_count, (size_t) hid->value_states_raw[index]); contact_count = std::max(contact_count, (size_t) hid->value_states_raw[index]);
} }
// https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/touchscreen-packet-reporting-modes
// hybrid mode devices will report a contact count of 0 for subsequent reports that are // hybrid mode devices will report a contact count of 0 for subsequent reports that are
// part of the same initial frame // part of the same initial frame
// most laptops and touchscreens are like this - they have the contact count set to 5 but can actually report up to 10 fingers
if (contact_count > 0) { if (contact_count > 0) {
if (contact_count > touch_report_count) { if (contact_count > touch_report_count) {
touch.remaining_contact_count = contact_count - touch_report_count; touch.remaining_contact_count = contact_count - touch_report_count;
@@ -216,6 +218,12 @@ namespace rawinput::touch {
touch_points.reserve(touch.elements_x.size()); touch_points.reserve(touch.elements_x.size());
for (size_t i = 0; i < touch.elements_x.size(); i++) { for (size_t i = 0; i < touch.elements_x.size(); i++) {
// if there are no more touch events to handle, exit out early
if (touch_report_count == 0) {
break;
}
touch_report_count--;
// build touch point // build touch point
HIDTouchPoint hid_tp{}; HIDTouchPoint hid_tp{};
auto pos_x = hid->value_states[touch.elements_x[i]]; auto pos_x = hid->value_states[touch.elements_x[i]];
@@ -247,17 +255,6 @@ namespace rawinput::touch {
hid_tp.y = 1.f - hid_tp.y; hid_tp.y = 1.f - hid_tp.y;
} }
// check if this touch point should be considered valid
//
// If "Contact count" reports there are no touch reports remaining and the X and Y
// coordinates of this touch point are zero, then this report element should be
// skipped.
if (touch_report_count == 0 && hid_tp.x == 0.f && hid_tp.y == 0.f) {
continue;
} else if (touch_report_count > 0) {
touch_report_count--;
}
// generate ID (hopefully unique) // generate ID (hopefully unique)
hid_tp.id = (DWORD) hid->value_states_raw[touch.elements_contact_identifier[i]]; hid_tp.id = (DWORD) hid->value_states_raw[touch.elements_contact_identifier[i]];
hid_tp.id += (DWORD) (0xFFFFFF + device->id * 512); hid_tp.id += (DWORD) (0xFFFFFF + device->id * 512);
+14 -12
View File
@@ -219,20 +219,21 @@ intptr_t replace_pattern(HMODULE module, const std::string &signature,
strreplace(pattern_str, "??", "00"); strreplace(pattern_str, "??", "00");
auto pattern_bin = std::make_unique<uint8_t[]>(signature.length() / 2); auto pattern_bin = std::make_unique<uint8_t[]>(signature.length() / 2);
if (!hex2bin(pattern_str.c_str(), pattern_bin.get())) { if (!hex2bin(pattern_str.c_str(), pattern_bin.get())) {
return false; return 0;
} }
// build signature mask // build signature mask
std::ostringstream signature_mask; std::string signature_mask;
signature_mask.reserve(signature.size() / 2);
for (size_t i = 0; i < signature.length(); i += 2) { for (size_t i = 0; i < signature.length(); i += 2) {
if (signature[i] == '?') { if (signature[i] == '?') {
if (signature[i + 1] == '?') { if (signature[i + 1] == '?') {
signature_mask << '?'; signature_mask += '?';
} else { } else {
return false; return 0;
} }
} else { } else {
signature_mask << 'X'; signature_mask += 'X';
} }
} }
@@ -241,20 +242,21 @@ intptr_t replace_pattern(HMODULE module, const std::string &signature,
strreplace(replace_data_str, "??", "00"); strreplace(replace_data_str, "??", "00");
auto replace_data_bin = std::make_unique<uint8_t[]>(replacement.length() / 2); auto replace_data_bin = std::make_unique<uint8_t[]>(replacement.length() / 2);
if (!hex2bin(replace_data_str.c_str(), replace_data_bin.get())) { if (!hex2bin(replace_data_str.c_str(), replace_data_bin.get())) {
return false; return 0;
} }
// build replace mask // build replace mask
std::ostringstream replace_mask; std::string replace_mask;
replace_mask.reserve(replacement.size() / 2);
for (size_t i = 0; i < replacement.length(); i += 2) { for (size_t i = 0; i < replacement.length(); i += 2) {
if (replacement[i] == '?') { if (replacement[i] == '?') {
if (replacement[i + 1] == '?') { if (replacement[i + 1] == '?') {
replace_mask << '?'; replace_mask += '?';
} else { } else {
return false; return 0;
} }
} else { } else {
replace_mask << 'X'; replace_mask += 'X';
} }
} }
@@ -262,11 +264,11 @@ intptr_t replace_pattern(HMODULE module, const std::string &signature,
return replace_pattern( return replace_pattern(
module, module,
pattern_bin.get(), pattern_bin.get(),
signature_mask.str().c_str(), signature_mask.c_str(),
offset, offset,
usage, usage,
replace_data_bin.get(), replace_data_bin.get(),
replace_mask.str().c_str() replace_mask.c_str()
); );
} }
+12 -3
View File
@@ -9,7 +9,7 @@ namespace tapeledutils {
} }
// for bi2x-style byte array of all colors and LEDs at once // for bi2x-style byte array of all colors and LEDs at once
rgb_float3_t pick_color_from_led_tape(uint8_t *data, size_t data_size) { static rgb_float3_t pick_color_from_led_tape_internal(uint8_t *data, size_t data_size, uint8_t divisor) {
rgb_float3_t result = {0.f, 0.f, 0.f}; rgb_float3_t result = {0.f, 0.f, 0.f};
if (TAPE_LED_ALGORITHM == TAPE_LED_USE_AVERAGE) { if (TAPE_LED_ALGORITHM == TAPE_LED_USE_AVERAGE) {
@@ -25,7 +25,7 @@ namespace tapeledutils {
} }
// normalize // normalize
const float avg_mult = 1.f / (data_size * 255); const float avg_mult = 1.f / (data_size * divisor);
result.r = avg_ri * avg_mult; result.r = avg_ri * avg_mult;
result.g = avg_gi * avg_mult; result.g = avg_gi * avg_mult;
result.b = avg_bi * avg_mult; result.b = avg_bi * avg_mult;
@@ -50,7 +50,7 @@ namespace tapeledutils {
} }
// normalize // normalize
const float single_mult = 1.f / 255; const float single_mult = 1.f / divisor;
result.r = color[0] * single_mult; result.r = color[0] * single_mult;
result.g = color[1] * single_mult; result.g = color[1] * single_mult;
result.b = color[2] * single_mult; result.b = color[2] * single_mult;
@@ -58,6 +58,15 @@ namespace tapeledutils {
return result; return result;
} }
rgb_float3_t pick_color_from_led_tape(tape_led &light, uint8_t *data, size_t data_size) {
const auto max_value = (light.max_value > 0) ? light.max_value : 0xFF;
return pick_color_from_led_tape_internal(data, data_size, max_value);
}
rgb_float3_t pick_color_from_led_tape(uint8_t *data, size_t data_size) {
return pick_color_from_led_tape_internal(data, data_size, 0xFF);
}
// for bi2a-style that calls for each individual LED // for bi2a-style that calls for each individual LED
size_t get_led_index_using_avg_algo(size_t data_size) { size_t get_led_index_using_avg_algo(size_t data_size) {
size_t index_to_use; size_t index_to_use;
+22 -2
View File
@@ -25,13 +25,33 @@ namespace tapeledutils {
struct tape_led { struct tape_led {
std::vector<rgb_float3_t> data; std::vector<rgb_float3_t> data;
int index_r, index_g, index_b; // Averaged RGB light output indexes int index_r, index_g, index_b; // Averaged RGB light output indexes
uint8_t max_value;
std::string lightName; std::string lightName;
tape_led(size_t data_size, int index_r, int index_g, int index_b, std::string lightName) tape_led(
: data(std::vector<rgb_float3_t>(data_size)), index_r(index_r), index_g(index_g), index_b(index_b), lightName(std::move(lightName)) {} size_t data_size,
int index_r, int index_g, int index_b,
std::string lightName)
: data(
std::vector<rgb_float3_t>(data_size)),
index_r(index_r), index_g(index_g), index_b(index_b),
max_value(0),
lightName(std::move(lightName)) {}
tape_led(
size_t data_size,
int index_r, int index_g, int index_b,
uint8_t max_value,
std::string lightName)
: data(
std::vector<rgb_float3_t>(data_size)),
index_r(index_r), index_g(index_g), index_b(index_b),
max_value(max_value),
lightName(std::move(lightName)) {}
}; };
bool is_enabled(); bool is_enabled();
rgb_float3_t pick_color_from_led_tape(tape_led &light, uint8_t *data, size_t data_size);
rgb_float3_t pick_color_from_led_tape(uint8_t *data, size_t data_size); rgb_float3_t pick_color_from_led_tape(uint8_t *data, size_t data_size);
size_t get_led_index_using_avg_algo(size_t data_size); size_t get_led_index_using_avg_algo(size_t data_size);
} }