mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
Merge branch 'main' of https://github.com/spice2x/spice2x.github.io
This commit is contained in:
+122
-20
@@ -35,24 +35,33 @@ struct ICCA_STATUS_LA9 {
|
||||
static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes");
|
||||
|
||||
enum ICCA_WORKFLOW {
|
||||
STEP,
|
||||
SLEEP,
|
||||
START,
|
||||
INIT,
|
||||
READY,
|
||||
GET_USERID,
|
||||
ACTIVE,
|
||||
EJECT,
|
||||
EJECT_CHECK,
|
||||
END,
|
||||
CLOSE_EJECT,
|
||||
CLOSE_E_CHK,
|
||||
CLOSE_END,
|
||||
ERR_GETUID = -2
|
||||
STEP = 0,
|
||||
SLEEP = 1,
|
||||
START = 2,
|
||||
INIT = 3,
|
||||
READY = 4,
|
||||
GET_USERID = 5,
|
||||
ACTIVE = 6,
|
||||
EJECT = 7,
|
||||
EJECT_CHECK = 8,
|
||||
END = 9,
|
||||
CLOSE_EJECT = 10,
|
||||
CLOSE_E_CHK = 11,
|
||||
CLOSE_END = 12,
|
||||
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_STATUS status {};
|
||||
enum ICCA_WORKFLOW state = STEP;
|
||||
enum ICCA_WORKFLOW state_jdz = SLEEP;
|
||||
bool card_cmd_pressed = false;
|
||||
bool card_in = false;
|
||||
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) {
|
||||
// on RA the unit_id is zero-indexed
|
||||
if (avs::game::is_model("JDZ")) {
|
||||
return unit_id;
|
||||
}
|
||||
|
||||
if (icca_get_active_count() < 2)
|
||||
return 1;
|
||||
else {
|
||||
@@ -122,9 +136,15 @@ static inline void update_card(int unit_id) {
|
||||
IS_LAST_CARD_FELICA = is_card_uid_felica(unit->status.uid);
|
||||
|
||||
unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE;
|
||||
unit->state_jdz = ACTIVE;
|
||||
unit->status.error = 0;
|
||||
unit->status.front_sensor = 1;
|
||||
unit->status.rear_sensor = 1;
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
unit->card_in = true;
|
||||
@@ -132,10 +152,25 @@ static inline void update_card(int unit_id) {
|
||||
} else if (unit->state == EJECT_CHECK) {
|
||||
unit->state = SLEEP;
|
||||
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 {
|
||||
unit->state = acio::ICCA_COMPAT_ACTIVE ? START : ACTIVE;
|
||||
if (unit->state_jdz == READY) {
|
||||
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();
|
||||
}
|
||||
@@ -144,6 +179,12 @@ static inline void update_card(int unit_id) {
|
||||
unit->state = CLOSE_EJECT;
|
||||
if (fabs(get_performance_seconds() - unit->card_in_time) > CARD_TIMEOUT) {
|
||||
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
|
||||
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));
|
||||
|
||||
// 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) {
|
||||
unit_id = icca_get_unit_id(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 (fabs(get_performance_seconds() - unit->card_in_time) < CARD_TIMEOUT) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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);
|
||||
ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
|
||||
switch (workflow) {
|
||||
case STEP:
|
||||
if (avs::game::is_model("JDZ"))
|
||||
unit->state = SLEEP;
|
||||
else
|
||||
unit->state = STEP;
|
||||
unit->state = STEP;
|
||||
break;
|
||||
case SLEEP:
|
||||
unit->state = SLEEP;
|
||||
@@ -441,7 +536,6 @@ static int __cdecl ac_io_icca_workflow(int workflow, int unit_id) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return unit->state;
|
||||
}
|
||||
|
||||
@@ -467,6 +561,14 @@ acio::ICCAModule::ICCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModu
|
||||
void acio::ICCAModule::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
|
||||
ACIO_MODULE_HOOK(ac_io_icca_cardunit_init);
|
||||
ACIO_MODULE_HOOK(ac_io_icca_cardunit_init_isfinished);
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace cfg {
|
||||
// window = rectangle including the frame
|
||||
// client = just the content area without frames.
|
||||
bool window_always_on_top = false;
|
||||
bool window_disable_round_corners = false;
|
||||
bool client_keep_aspect_ratio = true;
|
||||
bool enable_window_resize = false;
|
||||
int window_decoration = 0; // enum type WindowDecorationMode
|
||||
|
||||
@@ -915,8 +915,7 @@ namespace games::iidx {
|
||||
log_warning(
|
||||
"iidx",
|
||||
"Failed to apply ASIO compatibility fix for iidx32+. "
|
||||
"Unless patches are applied, your ASIO device ({}) may hang or fail to work",
|
||||
ASIO_DRIVER->c_str());
|
||||
"Unless patches are applied, your ASIO device may hang or fail to work");
|
||||
} else {
|
||||
log_info(
|
||||
"iidx",
|
||||
|
||||
@@ -475,7 +475,7 @@ namespace games::popn {
|
||||
const auto data_size = std::min(map.data.capacity(), (size_t)number_of_leds / 3);
|
||||
|
||||
// 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
|
||||
auto &lights = get_lights();
|
||||
|
||||
@@ -136,6 +136,18 @@ std::vector<Light> &games::popn::get_lights() {
|
||||
{"Pika", "IC Card R"},
|
||||
{"Pika", "IC Card G"},
|
||||
{"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"},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,18 @@ namespace games::popn {
|
||||
IC_Card_R,
|
||||
IC_Card_G,
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
#include "util/sysutils.h"
|
||||
#include "io.h"
|
||||
#include "util/deferlog.h"
|
||||
#include "misc/nativetouchhook.h"
|
||||
#include "misc/wintouchemu.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
bool SHOW_PIKA_MONITOR_WARNING = false;
|
||||
bool NATIVE_TOUCH = false;
|
||||
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
@@ -36,39 +38,83 @@ namespace games::popn {
|
||||
// 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 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 6 = control panel, size 28, 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] = {
|
||||
{
|
||||
0, // these are button lights and handled specially
|
||||
// [0] button lights: these are button lights and handled specially
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"Invalid"
|
||||
},
|
||||
{
|
||||
// [1] red pop-kun
|
||||
5, // 5*3; game reports 16 but make it 15
|
||||
Lights::popn_lights_t::RedPopKun_R,
|
||||
Lights::popn_lights_t::RedPopKun_G,
|
||||
Lights::popn_lights_t::RedPopKun_B,
|
||||
0xFF,
|
||||
"Red Pop-Kun"
|
||||
},
|
||||
{
|
||||
// [2] blue pop-kun
|
||||
5, // 5*3; game reports 16 but make it 15
|
||||
Lights::popn_lights_t::BluePopKun_R,
|
||||
Lights::popn_lights_t::BluePopKun_G,
|
||||
Lights::popn_lights_t::BluePopKun_B,
|
||||
0xFF,
|
||||
"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_G,
|
||||
Lights::popn_lights_t::TopLED_B,
|
||||
0xFF,
|
||||
"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
|
||||
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
wintouchemu::FORCE = true;
|
||||
wintouchemu::INJECT_MOUSE_AS_WM_TOUCH = true;
|
||||
wintouchemu::hook_title_ends("", "Main Screen", avs::game::DLL_INSTANCE);
|
||||
if (NATIVE_TOUCH) {
|
||||
nativetouchhook::hook(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();
|
||||
|
||||
@@ -17,11 +17,12 @@ namespace games::popn {
|
||||
}
|
||||
|
||||
#if SPICE64
|
||||
constexpr int POPN_TAPELED_TOTAL = 4;
|
||||
constexpr int POPN_TAPELED_TOTAL = 8;
|
||||
extern tapeledutils::tape_led TAPELED_MAPPING[POPN_TAPELED_TOTAL];
|
||||
#endif
|
||||
|
||||
extern bool SHOW_PIKA_MONITOR_WARNING;
|
||||
extern bool NATIVE_TOUCH;
|
||||
|
||||
class POPNGame : public games::Game {
|
||||
public:
|
||||
|
||||
@@ -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) {
|
||||
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) {
|
||||
graphics_update_z_order(hWnd, true);
|
||||
}
|
||||
if (GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS) {
|
||||
graphics_set_corner_preference(hWnd, true);
|
||||
}
|
||||
}
|
||||
|
||||
void graphics_screens_register(int screen) {
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d9.h>
|
||||
#if !SPICE_XP
|
||||
#include <dwmapi.h>
|
||||
#endif
|
||||
|
||||
#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 bool GRAPHICS_WINDOW_ALWAYS_ON_TOP;
|
||||
extern bool GRAPHICS_WINDOW_BACKBUFFER_SCALE;
|
||||
extern bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS;
|
||||
extern std::optional<HWND> GRAPHICS_HOOKED_WINDOW;
|
||||
|
||||
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_update_window_style(HWND hWnd, bool force_update=false);
|
||||
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);
|
||||
bool graphics_window_options_breaks_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;
|
||||
bool GRAPHICS_WINDOW_ALWAYS_ON_TOP = false;
|
||||
bool GRAPHICS_WINDOW_BACKBUFFER_SCALE = false;
|
||||
bool GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = false;
|
||||
std::optional<HWND> GRAPHICS_HOOKED_WINDOW;
|
||||
|
||||
// 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));
|
||||
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
|
||||
update_spicetouch_window_dimensions(hWnd);
|
||||
@@ -181,6 +186,10 @@ void graphics_load_windowed_parameters() {
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -469,6 +478,27 @@ void graphics_update_z_order(HWND hWnd, bool always_on_top) {
|
||||
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) {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
return;
|
||||
@@ -502,8 +532,8 @@ bool graphics_window_decoration_change_crashes_game() {
|
||||
static std::once_flag flag;
|
||||
static bool result = false;
|
||||
std::call_once(flag, []() {
|
||||
// ddr crashes when frame style changes
|
||||
if (avs::game::is_model("MDX")) {
|
||||
// ddr and ftt crash when frame style changes
|
||||
if (avs::game::is_model("MDX") || avs::game::is_model("MMD")) {
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -597,6 +597,9 @@ int main_implementation(int argc, char *argv[]) {
|
||||
if (options[launcher::Options::PopnSubMonitorOverride].is_active()) {
|
||||
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()) {
|
||||
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_BACKBUFFER_SCALE = options[launcher::Options::WindowForceScaling].value_bool();
|
||||
GRAPHICS_WINDOW_DISABLE_ROUNDED_CORNERS = options[launcher::Options::WindowDisableRoundedCorners].value_bool();
|
||||
|
||||
// IIDX/SDVX Windowed Subscreen
|
||||
if (options[launcher::Options::spice2x_IIDXWindowedSubscreenSize].is_active()) {
|
||||
@@ -1831,9 +1835,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
attach_ftt = true;
|
||||
|
||||
// the game is windowed by default unless we set the env
|
||||
if (GRAPHICS_WINDOWED) {
|
||||
GRAPHICS_WINDOWED = false;
|
||||
} else {
|
||||
if (!GRAPHICS_WINDOWED) {
|
||||
SetEnvironmentVariable("DAMAC_VIEWER_FULLSCREEN", "0");
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ static const std::vector<std::string> CATEGORY_ORDER_BASIC = {
|
||||
|
||||
static const std::vector<std::string> CATEGORY_ORDER_ADVANCED = {
|
||||
"Game Options (Advanced)",
|
||||
"Game Options (Peripherals)",
|
||||
"Overlay",
|
||||
"Network (Advanced)",
|
||||
"Performance",
|
||||
@@ -513,7 +514,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc = "Flip the camera order.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// IIDXDisableCameras
|
||||
@@ -523,7 +524,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Bool,
|
||||
.hidden = true,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// 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.",
|
||||
.type = OptionType::Enum,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
.elements = {
|
||||
{"auto", ""},
|
||||
{"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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// IIDXCamHookRatio
|
||||
@@ -561,7 +562,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Enum,
|
||||
.hidden = true,
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
.elements = {
|
||||
{"43", "4:3"},
|
||||
{"169", "16:9"},
|
||||
@@ -579,7 +580,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "0x5817a0,0x6fffbd8,0xbbae40,0xe0,0x30",
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// IIDXCamHookTopId
|
||||
@@ -594,7 +595,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "vid_1234&pid_5678",
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// IIDXCamHookFrontId
|
||||
@@ -609,7 +610,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "vid_90ab&pid_cdef",
|
||||
.game_name = "Beatmania IIDX",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.title = "IIDX Sound Output Device",
|
||||
@@ -772,11 +773,11 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
{
|
||||
.title = "SDVX Force 720p",
|
||||
.title = "SDVX Vivid Wave Force 720p Window (DEPRECATED - use -windowsize instead)",
|
||||
.name = "sdvx720",
|
||||
.desc = "Force Sound Voltex 720p display mode, used by older games. "
|
||||
"For newer games, use window resize function instead.",
|
||||
.desc = "Old & deprecated option for launching Vivid Wave in 720p when using windowed mode.",
|
||||
.type = OptionType::Bool,
|
||||
.hidden = true,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
},
|
||||
@@ -786,7 +787,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc = "Enable Sound Voltex printer emulation.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// SDVXPrinterOutputPath
|
||||
@@ -795,7 +796,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc = "Path to folder where images will be stored.",
|
||||
.type = OptionType::Text,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
.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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// SDVXPrinterOutputFormat
|
||||
@@ -822,7 +823,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "(png/bmp/tga/jpg)",
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.title = "SDVX Printer JPG Quality",
|
||||
@@ -831,7 +832,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Integer,
|
||||
.setting_name = "(0-100)",
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.title = "SDVX Disable Cameras (DEPRECATED - no longer needed)",
|
||||
@@ -842,7 +843,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Bool,
|
||||
.hidden = true,
|
||||
.game_name = "Sound Voltex",
|
||||
.category = "Game Options",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.title = "SDVX FS Subscreen Native Touch Handling",
|
||||
@@ -1008,6 +1009,18 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "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",
|
||||
.name = "hpm",
|
||||
@@ -2218,6 +2231,14 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Bool,
|
||||
.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
|
||||
.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!",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "DANCERUSH",
|
||||
.category = "Game Options",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// 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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// LovePlusPrinterOutputPath
|
||||
@@ -2690,7 +2711,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc = "Path to folder where images will be stored.",
|
||||
.type = OptionType::Text,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
.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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// LovePlusPrinterOutputFormat
|
||||
@@ -2717,7 +2738,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "(png/bmp/tga/jpg)",
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
.title = "LovePlus Printer JPG Quality",
|
||||
@@ -2726,7 +2747,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Integer,
|
||||
.setting_name = "(0-100)",
|
||||
.game_name = "LovePlus",
|
||||
.category = "Game Options (Advanced)",
|
||||
.category = "Game Options (Peripherals)",
|
||||
},
|
||||
{
|
||||
// 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.",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Otoca D'or",
|
||||
.category = "Game Options",
|
||||
.category = "Game Options (Peripherals)",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ namespace launcher {
|
||||
PopnMusicForceSDMode,
|
||||
PopnNoSub,
|
||||
PopnSubMonitorOverride,
|
||||
PopnNativeTouch,
|
||||
LoadHelloPopnMusicModule,
|
||||
LoadGitaDoraModule,
|
||||
GitaDoraTwoChannelAudio,
|
||||
@@ -232,6 +233,7 @@ namespace launcher {
|
||||
spice2x_WindowPosition,
|
||||
spice2x_WindowAlwaysOnTop,
|
||||
WindowForceScaling,
|
||||
WindowDisableRoundedCorners,
|
||||
spice2x_IIDXWindowedSubscreenSize,
|
||||
spice2x_IIDXWindowedSubscreenPosition,
|
||||
IIDXWindowedSubscreenBorderless,
|
||||
|
||||
@@ -86,13 +86,12 @@ namespace launcher {
|
||||
if (LAUNCHER_ARGC > 0) {
|
||||
|
||||
// build cmd line
|
||||
std::stringstream cmd_line;
|
||||
cmd_line << "START \"\" ";
|
||||
std::string cmd_line = "START \"\" ";
|
||||
for (int i = 0; i < LAUNCHER_ARGC; i++)
|
||||
cmd_line << " \"" << LAUNCHER_ARGV[i] << "\"";
|
||||
cmd_line += " \"" + std::string(LAUNCHER_ARGV[i]) + "\"";
|
||||
|
||||
// run command
|
||||
system(cmd_line.str().c_str());
|
||||
system(cmd_line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "external/imgui/misc/cpp/imgui_stdlib.h"
|
||||
#include "games/io.h"
|
||||
#include "games/sdvx/sdvx.h"
|
||||
#include "games/popn/popn.h"
|
||||
#include "avs/core.h"
|
||||
#include "avs/ea3.h"
|
||||
#include "avs/game.h"
|
||||
@@ -283,18 +284,8 @@ namespace overlay::windows {
|
||||
|
||||
// keypad buttons
|
||||
ImGui::TextUnformatted("");
|
||||
if (this->games_selected_name == "Beatmania IIDX") {
|
||||
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("");
|
||||
}
|
||||
this->build_keypad_warning();
|
||||
|
||||
auto keypad_buttons = games::get_buttons_keypads(this->games_selected_name);
|
||||
auto keypad_count = eamuse_get_game_keypads_name();
|
||||
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) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "%s Buttons", name.c_str());
|
||||
|
||||
@@ -193,13 +193,15 @@ namespace overlay::windows {
|
||||
std::vector<Option> *options, const std::string &category, const std::string *filter=nullptr);
|
||||
void build_about();
|
||||
void build_launcher();
|
||||
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
||||
void build_keypad_warning();
|
||||
|
||||
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
||||
|
||||
void build_menu(int *game_selected);
|
||||
void shutdown_system(bool force, bool reboot_instead);
|
||||
|
||||
|
||||
void set_alternating_row_colors(const int row_index);
|
||||
|
||||
|
||||
bool validate_ea_card(char card_number[16]);
|
||||
|
||||
public:
|
||||
|
||||
@@ -628,13 +628,12 @@ namespace overlay::windows {
|
||||
ImGui::Text("Wheel: %ld", mouse->pos_wheel);
|
||||
|
||||
// keys
|
||||
std::stringstream keys;
|
||||
keys << "[";
|
||||
std::string keys = "[";
|
||||
for (auto key : mouse->key_states) {
|
||||
keys << (key ? "1," : "0,");
|
||||
keys += (key ? "1," : "0,");
|
||||
}
|
||||
keys << "]";
|
||||
ImGui::Text("Keys: %s", keys.str().c_str());
|
||||
keys += "]";
|
||||
ImGui::Text("Keys: %s", keys.c_str());
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -643,15 +642,14 @@ namespace overlay::windows {
|
||||
ImGui::Text("Type: Keyboard");
|
||||
|
||||
// keys
|
||||
std::stringstream keys;
|
||||
keys << "[";
|
||||
std::string keys = "[";
|
||||
for (size_t i = 0; i < std::size(keyboard->key_states); i++) {
|
||||
if (keyboard->key_states[i]) {
|
||||
keys << i << ",";
|
||||
keys += std::to_string(i) + ",";
|
||||
}
|
||||
}
|
||||
keys << "]";
|
||||
ImGui::Text("Keys: %s", keys.str().c_str());
|
||||
keys += "]";
|
||||
ImGui::Text("Keys: %s", keys.c_str());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -192,8 +192,10 @@ namespace rawinput::touch {
|
||||
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
|
||||
// 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 > 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());
|
||||
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
|
||||
HIDTouchPoint hid_tp{};
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
hid_tp.id = (DWORD) hid->value_states_raw[touch.elements_contact_identifier[i]];
|
||||
hid_tp.id += (DWORD) (0xFFFFFF + device->id * 512);
|
||||
|
||||
@@ -219,20 +219,21 @@ intptr_t replace_pattern(HMODULE module, const std::string &signature,
|
||||
strreplace(pattern_str, "??", "00");
|
||||
auto pattern_bin = std::make_unique<uint8_t[]>(signature.length() / 2);
|
||||
if (!hex2bin(pattern_str.c_str(), pattern_bin.get())) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (signature[i] == '?') {
|
||||
if (signature[i + 1] == '?') {
|
||||
signature_mask << '?';
|
||||
signature_mask += '?';
|
||||
} else {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
} 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");
|
||||
auto replace_data_bin = std::make_unique<uint8_t[]>(replacement.length() / 2);
|
||||
if (!hex2bin(replace_data_str.c_str(), replace_data_bin.get())) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (replacement[i] == '?') {
|
||||
if (replacement[i + 1] == '?') {
|
||||
replace_mask << '?';
|
||||
replace_mask += '?';
|
||||
} else {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
replace_mask << 'X';
|
||||
replace_mask += 'X';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,11 +264,11 @@ intptr_t replace_pattern(HMODULE module, const std::string &signature,
|
||||
return replace_pattern(
|
||||
module,
|
||||
pattern_bin.get(),
|
||||
signature_mask.str().c_str(),
|
||||
signature_mask.c_str(),
|
||||
offset,
|
||||
usage,
|
||||
replace_data_bin.get(),
|
||||
replace_mask.str().c_str()
|
||||
replace_mask.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace tapeledutils {
|
||||
}
|
||||
|
||||
// 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};
|
||||
if (TAPE_LED_ALGORITHM == TAPE_LED_USE_AVERAGE) {
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace tapeledutils {
|
||||
}
|
||||
|
||||
// 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.g = avg_gi * avg_mult;
|
||||
result.b = avg_bi * avg_mult;
|
||||
@@ -50,7 +50,7 @@ namespace tapeledutils {
|
||||
}
|
||||
|
||||
// normalize
|
||||
const float single_mult = 1.f / 255;
|
||||
const float single_mult = 1.f / divisor;
|
||||
result.r = color[0] * single_mult;
|
||||
result.g = color[1] * single_mult;
|
||||
result.b = color[2] * single_mult;
|
||||
@@ -58,6 +58,15 @@ namespace tapeledutils {
|
||||
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
|
||||
size_t get_led_index_using_avg_algo(size_t data_size) {
|
||||
size_t index_to_use;
|
||||
|
||||
@@ -25,13 +25,33 @@ namespace tapeledutils {
|
||||
struct tape_led {
|
||||
std::vector<rgb_float3_t> data;
|
||||
int index_r, index_g, index_b; // Averaged RGB light output indexes
|
||||
uint8_t max_value;
|
||||
std::string lightName;
|
||||
|
||||
tape_led(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), lightName(std::move(lightName)) {}
|
||||
tape_led(
|
||||
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();
|
||||
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);
|
||||
size_t get_led_index_using_avg_algo(size_t data_size);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user