mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 23:00:42 -07:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 06374ef78a | |||
| bdde1ec6b8 | |||
| d2176fe4f0 | |||
| fb9eef904a | |||
| 48903998a5 | |||
| f2dca0265f | |||
| 1147ed9858 | |||
| 19d93f4ffd | |||
| 15bfffa1d3 | |||
| 18a9a47c33 | |||
| 6838e69ebe | |||
| 26b3b64794 | |||
| aadd2bdd59 | |||
| d0e24e31ca | |||
| 4fb7f20c7b | |||
| 6ddae70c5a | |||
| b38160d6c2 | |||
| 231c998cc0 | |||
| 127d31a85c |
+122
-20
@@ -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);
|
||||||
|
|||||||
@@ -217,8 +217,10 @@ namespace avs {
|
|||||||
ea3_config_name = "prop/eamuse-config.xml";
|
ea3_config_name = "prop/eamuse-config.xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avs::core::file_exists(ea3_config_name)) {
|
if (fileutils::file_exists(ea3_config_name)) {
|
||||||
log_info("avs-ea3", "booting (using {})", ea3_config_name);
|
log_info("avs-ea3", "found {} on disk", ea3_config_name);
|
||||||
|
} else if (CFG_PATH.size()) {
|
||||||
|
log_fatal("avs-ea3", "user-specified ea3 config file is missing: {}", ea3_config_name);
|
||||||
} else {
|
} else {
|
||||||
log_warning("avs-ea3", "looked for the following files in order:");
|
log_warning("avs-ea3", "looked for the following files in order:");
|
||||||
log_warning("avs-ea3", " * prop/ea3-config.xml");
|
log_warning("avs-ea3", " * prop/ea3-config.xml");
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ time (
|
|||||||
if ((BUILD_XP > 0))
|
if ((BUILD_XP > 0))
|
||||||
then
|
then
|
||||||
# 32 bit Windows XP
|
# 32 bit Windows XP
|
||||||
|
echo ""
|
||||||
echo "Building 32bit targets (WinXP toolchain)..."
|
echo "Building 32bit targets (WinXP toolchain)..."
|
||||||
echo "========================="
|
echo "========================="
|
||||||
if ((CLEAN_BUILD > 0))
|
if ((CLEAN_BUILD > 0))
|
||||||
@@ -187,6 +188,7 @@ time (
|
|||||||
CXXFLAGS="$CXXFLAGS -DSPICE_XP=1" cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_WINXP_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_XP64}
|
CXXFLAGS="$CXXFLAGS -DSPICE_XP=1" cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_WINXP_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_XP64}
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
else
|
else
|
||||||
|
echo ""
|
||||||
echo "Skipping WinXP builds, toolchain not specified"
|
echo "Skipping WinXP builds, toolchain not specified"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -199,9 +199,19 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
|
|||||||
if (vKey < value_states->size()) {
|
if (vKey < value_states->size()) {
|
||||||
auto value = value_states->at(vKey);
|
auto value = value_states->at(vKey);
|
||||||
if (current_button->getAnalogType() == BAT_POSITIVE) {
|
if (current_button->getAnalogType() == BAT_POSITIVE) {
|
||||||
state = value > 0.6f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
float threshold = 0.6f;
|
||||||
|
if (current_button->getBatThreshold() > 0) {
|
||||||
|
threshold = std::clamp(current_button->getBatThreshold() / 100.f, 0.01f, 0.99f);
|
||||||
|
}
|
||||||
|
state = value > threshold ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
|
||||||
} else if (current_button->getAnalogType() == BAT_NEGATIVE) {
|
} else if (current_button->getAnalogType() == BAT_NEGATIVE) {
|
||||||
state = value < 0.4f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
float threshold = 0.4f;
|
||||||
|
if (current_button->getBatThreshold() > 0) {
|
||||||
|
threshold = std::clamp((100 - current_button->getBatThreshold()) / 100.f, 0.01f, 0.99f);
|
||||||
|
}
|
||||||
|
state = value < threshold ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
state = value > 0.01f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = value > 0.01f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ private:
|
|||||||
ButtonAnalogType analog_type = BAT_NONE;
|
ButtonAnalogType analog_type = BAT_NONE;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
|
int bat_threshold = 0; // for positive/negative only, value in percentage, zero is default
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
bool is_temporary = false;
|
bool is_temporary = false;
|
||||||
|
|
||||||
@@ -109,6 +110,7 @@ public:
|
|||||||
alternatives.clear();
|
alternatives.clear();
|
||||||
device_identifier = "";
|
device_identifier = "";
|
||||||
analog_type = BAT_NONE;
|
analog_type = BAT_NONE;
|
||||||
|
bat_threshold = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getDisplayString(rawinput::RawInputManager* manager);
|
std::string getDisplayString(rawinput::RawInputManager* manager);
|
||||||
@@ -169,6 +171,14 @@ public:
|
|||||||
this->debounce_down = debounce_time_down;
|
this->debounce_down = debounce_time_down;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void setBatThreshold(int bat_threshold) {
|
||||||
|
this->bat_threshold = bat_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getBatThreshold() const {
|
||||||
|
return this->bat_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool getInvert() const {
|
inline bool getInvert() const {
|
||||||
return this->invert;
|
return this->invert;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ bool Config::addGame(Game &game) {
|
|||||||
auto analogType = (int) BAT_NONE;
|
auto analogType = (int) BAT_NONE;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
|
int bat_threshold = 0;
|
||||||
int velocity_threshold = 0;
|
int velocity_threshold = 0;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
tinyxml2::XMLError attrError = gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
tinyxml2::XMLError attrError = gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
||||||
@@ -169,6 +170,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
||||||
|
gameButtonNode->QueryIntAttribute("bat_threshold", &bat_threshold);
|
||||||
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
|
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
|
||||||
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
||||||
if (attrError != tinyxml2::XMLError::XML_SUCCESS) {
|
if (attrError != tinyxml2::XMLError::XML_SUCCESS) {
|
||||||
@@ -180,6 +182,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->SetAttribute("devid", button->getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", button->getDeviceIdentifier().c_str());
|
||||||
gameButtonNode->SetAttribute("debounce_up", debounce_up);
|
gameButtonNode->SetAttribute("debounce_up", debounce_up);
|
||||||
gameButtonNode->SetAttribute("debounce_down", debounce_down);
|
gameButtonNode->SetAttribute("debounce_down", debounce_down);
|
||||||
|
gameButtonNode->SetAttribute("bat_threshold", bat_threshold);
|
||||||
gameButtonNode->SetAttribute("velocity_threshold", velocity_threshold);
|
gameButtonNode->SetAttribute("velocity_threshold", velocity_threshold);
|
||||||
gameButtonNode->SetAttribute("invert", invert);
|
gameButtonNode->SetAttribute("invert", invert);
|
||||||
gameButtonsNode->InsertEndChild(gameButtonNode);
|
gameButtonsNode->InsertEndChild(gameButtonNode);
|
||||||
@@ -188,6 +191,7 @@ bool Config::addGame(Game &game) {
|
|||||||
button->setAnalogType((ButtonAnalogType) analogType);
|
button->setAnalogType((ButtonAnalogType) analogType);
|
||||||
button->setDebounceUp(debounce_up);
|
button->setDebounceUp(debounce_up);
|
||||||
button->setDebounceDown(debounce_down);
|
button->setDebounceDown(debounce_down);
|
||||||
|
button->setBatThreshold(bat_threshold);
|
||||||
button->setVelocityThreshold(velocity_threshold);
|
button->setVelocityThreshold(velocity_threshold);
|
||||||
button->setInvert(invert);
|
button->setInvert(invert);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
@@ -207,6 +211,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->SetAttribute("analogtype", (int) it.getAnalogType());
|
gameButtonNode->SetAttribute("analogtype", (int) it.getAnalogType());
|
||||||
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
||||||
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
||||||
|
gameButtonNode->SetAttribute("bat_threshold", it.getBatThreshold());
|
||||||
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
|
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
|
||||||
gameButtonNode->SetAttribute("invert", it.getInvert());
|
gameButtonNode->SetAttribute("invert", it.getInvert());
|
||||||
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
||||||
@@ -432,6 +437,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->SetAttribute("analogtype", it.getAnalogType());
|
gameButtonNode->SetAttribute("analogtype", it.getAnalogType());
|
||||||
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
||||||
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
||||||
|
gameButtonNode->SetAttribute("bat_threshold", it.getBatThreshold());
|
||||||
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
|
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
|
||||||
gameButtonNode->SetAttribute("invert", it.getInvert());
|
gameButtonNode->SetAttribute("invert", it.getInvert());
|
||||||
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
||||||
@@ -535,6 +541,7 @@ bool Config::updateBinding(const Game &game, const Button &button, int alternati
|
|||||||
gameButtonNode->SetAttribute("analogtype", (int) button.getAnalogType());
|
gameButtonNode->SetAttribute("analogtype", (int) button.getAnalogType());
|
||||||
gameButtonNode->SetAttribute("debounce_up", button.getDebounceUp());
|
gameButtonNode->SetAttribute("debounce_up", button.getDebounceUp());
|
||||||
gameButtonNode->SetAttribute("debounce_down", button.getDebounceDown());
|
gameButtonNode->SetAttribute("debounce_down", button.getDebounceDown());
|
||||||
|
gameButtonNode->SetAttribute("bat_threshold", button.getBatThreshold());
|
||||||
gameButtonNode->SetAttribute("velocity_threshold", button.getVelocityThreshold());
|
gameButtonNode->SetAttribute("velocity_threshold", button.getVelocityThreshold());
|
||||||
gameButtonNode->SetAttribute("invert", button.getInvert());
|
gameButtonNode->SetAttribute("invert", button.getInvert());
|
||||||
gameButtonNode->SetAttribute("devid", button.getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", button.getDeviceIdentifier().c_str());
|
||||||
@@ -551,6 +558,7 @@ bool Config::updateBinding(const Game &game, const Button &button, int alternati
|
|||||||
gameButtonNode->SetAttribute("analogtype", 0);
|
gameButtonNode->SetAttribute("analogtype", 0);
|
||||||
gameButtonNode->SetAttribute("debounce_up", 0.0);
|
gameButtonNode->SetAttribute("debounce_up", 0.0);
|
||||||
gameButtonNode->SetAttribute("debounce_down", 0.0);
|
gameButtonNode->SetAttribute("debounce_down", 0.0);
|
||||||
|
gameButtonNode->SetAttribute("bat_threshold", 0);
|
||||||
gameButtonNode->SetAttribute("velocity_threshold", 0);
|
gameButtonNode->SetAttribute("velocity_threshold", 0);
|
||||||
gameButtonNode->SetAttribute("invert", false);
|
gameButtonNode->SetAttribute("invert", false);
|
||||||
gameButtonNode->SetAttribute("devid", "");
|
gameButtonNode->SetAttribute("devid", "");
|
||||||
@@ -946,12 +954,14 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
|
|||||||
auto analogType = (int) BAT_NONE;
|
auto analogType = (int) BAT_NONE;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
|
int bat_threshold = 0;
|
||||||
int velocity_threshold = 0;
|
int velocity_threshold = 0;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
||||||
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
||||||
|
gameButtonNode->QueryIntAttribute("bat_threshold", &bat_threshold);
|
||||||
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
|
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
|
||||||
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
||||||
const char *devid = gameButtonNode->Attribute("devid");
|
const char *devid = gameButtonNode->Attribute("devid");
|
||||||
@@ -966,6 +976,7 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
|
|||||||
alt.setAnalogType((ButtonAnalogType) analogType);
|
alt.setAnalogType((ButtonAnalogType) analogType);
|
||||||
alt.setDebounceUp(debounce_up);
|
alt.setDebounceUp(debounce_up);
|
||||||
alt.setDebounceDown(debounce_down);
|
alt.setDebounceDown(debounce_down);
|
||||||
|
alt.setBatThreshold(bat_threshold);
|
||||||
alt.setVelocityThreshold(velocity_threshold);
|
alt.setVelocityThreshold(velocity_threshold);
|
||||||
alt.setInvert(invert);
|
alt.setInvert(invert);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
@@ -984,6 +995,7 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
|
|||||||
button.setAnalogType((ButtonAnalogType) analogType);
|
button.setAnalogType((ButtonAnalogType) analogType);
|
||||||
button.setDebounceUp(debounce_up);
|
button.setDebounceUp(debounce_up);
|
||||||
button.setDebounceDown(debounce_down);
|
button.setDebounceDown(debounce_down);
|
||||||
|
button.setBatThreshold(bat_threshold);
|
||||||
button.setVelocityThreshold(velocity_threshold);
|
button.setVelocityThreshold(velocity_threshold);
|
||||||
button.setInvert(invert);
|
button.setInvert(invert);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace overlay::windows {
|
|||||||
el->SetAttribute("invert", entry.invert);
|
el->SetAttribute("invert", entry.invert);
|
||||||
el->SetAttribute("debounce_up", entry.debounce_up);
|
el->SetAttribute("debounce_up", entry.debounce_up);
|
||||||
el->SetAttribute("debounce_down", entry.debounce_down);
|
el->SetAttribute("debounce_down", entry.debounce_down);
|
||||||
|
el->SetAttribute("bat_threshold", entry.bat_threshold);
|
||||||
el->SetAttribute("velocity_threshold", entry.velocity_threshold);
|
el->SetAttribute("velocity_threshold", entry.velocity_threshold);
|
||||||
parent->InsertEndChild(el);
|
parent->InsertEndChild(el);
|
||||||
}
|
}
|
||||||
@@ -49,6 +50,10 @@ namespace overlay::windows {
|
|||||||
el->QueryIntAttribute("velocity_threshold", &vel);
|
el->QueryIntAttribute("velocity_threshold", &vel);
|
||||||
entry.velocity_threshold = (unsigned short)vel;
|
entry.velocity_threshold = (unsigned short)vel;
|
||||||
|
|
||||||
|
int bat = 0;
|
||||||
|
el->QueryIntAttribute("bat_threshold", &bat);
|
||||||
|
entry.bat_threshold = bat;
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -387,15 +387,6 @@ namespace games::popn {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PopnLight {
|
|
||||||
int data_index;
|
|
||||||
Lights::popn_lights_t light;
|
|
||||||
uint8_t size;
|
|
||||||
PopnLight(
|
|
||||||
int data_index, Lights::popn_lights_t light, uint8_t size) :
|
|
||||||
data_index(data_index), light(light), size(size) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __fastcall aioIob5Bi3a_SetTapeLedDataPart(
|
static void __fastcall aioIob5Bi3a_SetTapeLedDataPart(
|
||||||
AIO_IOB5_BI3A *i_pNodeCtl, uint32_t i_CnPin, char i_LedType, const void *i_pData, uint32_t i_DataSize, bool i_bIsLast) {
|
AIO_IOB5_BI3A *i_pNodeCtl, uint32_t i_CnPin, char i_LedType, const void *i_pData, uint32_t i_DataSize, bool i_bIsLast) {
|
||||||
|
|
||||||
@@ -484,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();
|
||||||
|
|||||||
@@ -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"},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -66,14 +66,16 @@ static HRESULT STDAPICALLTYPE CoCreateInstance_hook(
|
|||||||
if (FAILED(ret)) {
|
if (FAILED(ret)) {
|
||||||
if (IsEqualCLSID(rclsid, CLSID_MMDeviceEnumerator)) {
|
if (IsEqualCLSID(rclsid, CLSID_MMDeviceEnumerator)) {
|
||||||
log_warning("audio", "CoCreateInstance failed for CLSID_MMDeviceEnumerator, hr={}", FMT_HRESULT(ret));
|
log_warning("audio", "CoCreateInstance failed for CLSID_MMDeviceEnumerator, hr={}", FMT_HRESULT(ret));
|
||||||
}
|
} else if (IsEqualCLSID(rclsid, CLSID_DirectSoundI3DL2ReverbDMO)) {
|
||||||
|
// deal with reverb DMO missing from dsdmo.dll
|
||||||
// Windows 11 KB5052093 issue - reverb DMO went missing from dsdmo.dll (fails with 0x80040154)
|
// it usually fails with 0x80040154 (REGDB_E_CLASSNOTREG), but we have also seen 0x8007007e (ERROR_MOD_NOT_FOUND)
|
||||||
if (IsEqualCLSID(rclsid, CLSID_DirectSoundI3DL2ReverbDMO) && ret == (HRESULT)0x80040154) {
|
static std::once_flag printed;
|
||||||
log_warning(
|
std::call_once(printed, [ret]() {
|
||||||
"audio",
|
log_warning(
|
||||||
"CoCreateInstance for CLSID_DirectSoundI3DL2ReverbDMO failed with 0x80040154, swap with CLSID_DirectSoundWavesReverbDMO "
|
"audio",
|
||||||
"(workaround for Windows 11 KB5052093 issue); REVERB EX replaced with REVERB");
|
"CoCreateInstance for CLSID_DirectSoundI3DL2ReverbDMO failed with {}, swap with CLSID_DirectSoundWavesReverbDMO...",
|
||||||
|
FMT_HRESULT(ret));
|
||||||
|
});
|
||||||
ret = CoCreateInstance_orig(CLSID_DirectSoundWavesReverbDMO, pUnkOuter, dwClsContext, riid, ppv);
|
ret = CoCreateInstance_orig(CLSID_DirectSoundWavesReverbDMO, pUnkOuter, dwClsContext, riid, ppv);
|
||||||
if (FAILED(ret)) {
|
if (FAILED(ret)) {
|
||||||
log_warning("audio", "CoCreateInstance(CLSID_DirectSoundWavesReverbDMO...) failed, hr={}", FMT_HRESULT(ret));
|
log_warning("audio", "CoCreateInstance(CLSID_DirectSoundWavesReverbDMO...) failed, hr={}", FMT_HRESULT(ret));
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2362,9 +2364,9 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
// layeredfs
|
// layeredfs
|
||||||
if (fileutils::dir_exists("data_mods") &&
|
if (fileutils::dir_exists("data_mods") &&
|
||||||
GetModuleHandleA("ifs_hook.dll") == nullptr) {
|
GetModuleHandleA("ifs_hook.dll") == nullptr) {
|
||||||
log_warning("launcher", "data_mods directory found, but ifs_hook.dll is not present; mods will not load");
|
log_warning("launcher", "data_mods directory found, but ifs_hook.dll is not loaded; mods will not load");
|
||||||
deferredlogs::defer_error_messages({
|
deferredlogs::defer_error_messages({
|
||||||
"data_mods directory was found, but ifs_hook.dll is not present",
|
"data_mods directory was found, but ifs_hook.dll is not loaded",
|
||||||
" your mods will not load",
|
" your mods will not load",
|
||||||
" to fix this, download ifs_layeredfs and add it as a DLL hook (-k)",
|
" to fix this, download ifs_layeredfs and add it as a DLL hook (-k)",
|
||||||
" https://github.com/mon/ifs_layeredfs"
|
" https://github.com/mon/ifs_layeredfs"
|
||||||
|
|||||||
@@ -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)",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
@@ -1044,6 +1063,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
button->setInvert(false);
|
button->setInvert(false);
|
||||||
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
|
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
|
||||||
@@ -1246,6 +1266,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(bat);
|
button->setAnalogType(bat);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1294,6 +1315,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(buffer[0]);
|
button->setAnalogType(buffer[0]);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1341,6 +1363,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
// same idea as setMidiVKey - keep velocity threshold consistent
|
// same idea as setMidiVKey - keep velocity threshold consistent
|
||||||
button->setVelocityThreshold(
|
button->setVelocityThreshold(
|
||||||
device->midiInfo->v2_velocity_threshold[button->getVKey()]);
|
device->midiInfo->v2_velocity_threshold[button->getVKey()]);
|
||||||
@@ -1366,6 +1389,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_MIDI_CTRL_PRECISION);
|
button->setAnalogType(BAT_MIDI_CTRL_PRECISION);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1392,6 +1416,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_MIDI_CTRL_SINGLE);
|
button->setAnalogType(BAT_MIDI_CTRL_SINGLE);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1418,6 +1443,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_MIDI_CTRL_ONOFF);
|
button->setAnalogType(BAT_MIDI_CTRL_ONOFF);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1443,6 +1469,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_MIDI_PITCH_DOWN);
|
button->setAnalogType(BAT_MIDI_PITCH_DOWN);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1463,6 +1490,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_MIDI_PITCH_UP);
|
button->setAnalogType(BAT_MIDI_PITCH_UP);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1492,6 +1520,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1616,6 +1645,7 @@ namespace overlay::windows {
|
|||||||
button->setVKey(vKey);
|
button->setVKey(vKey);
|
||||||
button->setDebounceUp(0.0);
|
button->setDebounceUp(0.0);
|
||||||
button->setDebounceDown(0.0);
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
@@ -1667,6 +1697,9 @@ namespace overlay::windows {
|
|||||||
button->setDeviceIdentifier(device.name);
|
button->setDeviceIdentifier(device.name);
|
||||||
// reset controls when switching devices
|
// reset controls when switching devices
|
||||||
button->setAnalogType(ButtonAnalogType::BAT_NONE);
|
button->setAnalogType(ButtonAnalogType::BAT_NONE);
|
||||||
|
button->setDebounceUp(0.0);
|
||||||
|
button->setDebounceDown(0.0);
|
||||||
|
button->setBatThreshold(0);
|
||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
button->setVKey(0);
|
button->setVKey(0);
|
||||||
button->setInvert(false);
|
button->setInvert(false);
|
||||||
@@ -2031,11 +2064,48 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
// invert
|
// invert
|
||||||
bool invert = button->getInvert();
|
bool invert = button->getInvert();
|
||||||
if (ImGui::Checkbox("Invert", &invert)) {
|
if (ImGui::Checkbox("Invert Resulting Value", &invert)) {
|
||||||
button->setInvert(invert);
|
button->setInvert(invert);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bat threshold
|
||||||
|
if (device->type == rawinput::HID &&
|
||||||
|
(button->getAnalogType() == BAT_POSITIVE || button->getAnalogType() == BAT_NEGATIVE)) {
|
||||||
|
int bat_threshold = button->getBatThreshold();
|
||||||
|
|
||||||
|
bool is_active = (bat_threshold > 0);
|
||||||
|
if (ImGui::Checkbox("Custom Analog Threshold", &is_active)) {
|
||||||
|
if (!is_active) {
|
||||||
|
button->setBatThreshold(0);
|
||||||
|
} else if (bat_threshold == 0) {
|
||||||
|
button->setBatThreshold(60);
|
||||||
|
}
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::HelpMarker(
|
||||||
|
"Assuming that 50% is the center, value exceeding 60% triggers the button by default. "
|
||||||
|
"With this option, you can customize the trigger threshold.\n\n"
|
||||||
|
"Setting this to 51% means tiny movements will trigger the button (small deadzone), "
|
||||||
|
"while setting this to 99% means the button will only trigger at maximum value (large deadzone).\n\n"
|
||||||
|
"Setting this to below 50% adjusts the neutral / center position.");
|
||||||
|
|
||||||
|
if (is_active) {
|
||||||
|
if (ImGui::SliderInt(
|
||||||
|
"Analog Threshold",
|
||||||
|
&bat_threshold,
|
||||||
|
1, 99,
|
||||||
|
"%d%%",
|
||||||
|
ImGuiSliderFlags_AlwaysClamp)) {
|
||||||
|
button->setBatThreshold(bat_threshold);
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// state display
|
// state display
|
||||||
ImGui::TextUnformatted("");
|
ImGui::TextUnformatted("");
|
||||||
if (device != nullptr && device->type == rawinput::MIDI) {
|
if (device != nullptr && device->type == rawinput::MIDI) {
|
||||||
@@ -5264,6 +5334,7 @@ namespace overlay::windows {
|
|||||||
btn.setInvert(entry->invert);
|
btn.setInvert(entry->invert);
|
||||||
btn.setDebounceUp(entry->debounce_up);
|
btn.setDebounceUp(entry->debounce_up);
|
||||||
btn.setDebounceDown(entry->debounce_down);
|
btn.setDebounceDown(entry->debounce_down);
|
||||||
|
btn.setBatThreshold(entry->bat_threshold);
|
||||||
btn.setVelocityThreshold(entry->velocity_threshold);
|
btn.setVelocityThreshold(entry->velocity_threshold);
|
||||||
::Config::getInstance().updateBinding(game, btn, -1);
|
::Config::getInstance().updateBinding(game, btn, -1);
|
||||||
} else {
|
} else {
|
||||||
@@ -5274,6 +5345,7 @@ namespace overlay::windows {
|
|||||||
alt_btn.setInvert(entry->invert);
|
alt_btn.setInvert(entry->invert);
|
||||||
alt_btn.setDebounceUp(entry->debounce_up);
|
alt_btn.setDebounceUp(entry->debounce_up);
|
||||||
alt_btn.setDebounceDown(entry->debounce_down);
|
alt_btn.setDebounceDown(entry->debounce_down);
|
||||||
|
alt_btn.setBatThreshold(entry->bat_threshold);
|
||||||
alt_btn.setVelocityThreshold(entry->velocity_threshold);
|
alt_btn.setVelocityThreshold(entry->velocity_threshold);
|
||||||
alt_btn.setTemporary(true);
|
alt_btn.setTemporary(true);
|
||||||
btn.getAlternatives().push_back(alt_btn);
|
btn.getAlternatives().push_back(alt_btn);
|
||||||
|
|||||||
@@ -193,13 +193,15 @@ 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 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 build_menu(int *game_selected);
|
||||||
void shutdown_system(bool force, bool reboot_instead);
|
void shutdown_system(bool force, bool reboot_instead);
|
||||||
|
|
||||||
void set_alternating_row_colors(const int row_index);
|
void set_alternating_row_colors(const int row_index);
|
||||||
|
|
||||||
bool validate_ea_card(char card_number[16]);
|
bool validate_ea_card(char card_number[16]);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace overlay::windows {
|
|||||||
bool invert = false;
|
bool invert = false;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
|
int bat_threshold = 0;
|
||||||
unsigned short velocity_threshold = 0;
|
unsigned short velocity_threshold = 0;
|
||||||
|
|
||||||
bool is_naive() const { return device_identifier.empty() && vKey != INVALID_VKEY; }
|
bool is_naive() const { return device_identifier.empty() && vKey != INVALID_VKEY; }
|
||||||
@@ -31,6 +32,7 @@ namespace overlay::windows {
|
|||||||
e.invert = btn.getInvert();
|
e.invert = btn.getInvert();
|
||||||
e.debounce_up = btn.getDebounceUp();
|
e.debounce_up = btn.getDebounceUp();
|
||||||
e.debounce_down = btn.getDebounceDown();
|
e.debounce_down = btn.getDebounceDown();
|
||||||
|
e.bat_threshold = btn.getBatThreshold();
|
||||||
e.velocity_threshold = btn.getVelocityThreshold();
|
e.velocity_threshold = btn.getVelocityThreshold();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "avs/game.h"
|
#include "avs/game.h"
|
||||||
#include "games/iidx/iidx.h"
|
#include "games/iidx/iidx.h"
|
||||||
|
#include "games/popn/popn.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "overlay/imgui/extensions.h"
|
#include "overlay/imgui/extensions.h"
|
||||||
@@ -42,6 +43,8 @@ namespace overlay::windows {
|
|||||||
void Keypad::build_content() {
|
void Keypad::build_content() {
|
||||||
if (avs::game::is_model("LDJ") && games::iidx::TDJ_MODE) {
|
if (avs::game::is_model("LDJ") && games::iidx::TDJ_MODE) {
|
||||||
build_tdj_keypad();
|
build_tdj_keypad();
|
||||||
|
} else if (games::popn::is_pikapika_model()) {
|
||||||
|
build_popn_pika_keypad();
|
||||||
} else {
|
} else {
|
||||||
build_keypad();
|
build_keypad();
|
||||||
}
|
}
|
||||||
@@ -132,4 +135,26 @@ namespace overlay::windows {
|
|||||||
eamuse_set_keypad_overrides_overlay(this->unit, 0);
|
eamuse_set_keypad_overrides_overlay(this->unit, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Keypad::build_popn_pika_keypad() {
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::TextDisabled("Keypad disabled in Pop'n Pikapika model!\nUse subscreen overlay.");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::WarnMarker(
|
||||||
|
nullptr,
|
||||||
|
"Pop'n Music Pikapika cabinets do not have any keypads; they use the subscreen.\n\n"
|
||||||
|
"Fullscreen mode: bind a key in Overlay tab, and press it in game to show the subscreen, "
|
||||||
|
"then use your mouse to click. Page Up button is the default binding.\n\n"
|
||||||
|
"Windowed mode: look for the second window in the taskbar (or ALT+TAB).\n\n"
|
||||||
|
"Windowed mode with -popnnosub: bring up the subscreen overlay (default Page Up).\n\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
if (ImGui::Button("Insert Card")) {
|
||||||
|
eamuse_set_keypad_overrides_overlay(this->unit, 1 << EAM_IO_INSERT);
|
||||||
|
} else {
|
||||||
|
eamuse_set_keypad_overrides_overlay(this->unit, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace overlay::windows {
|
|||||||
size_t unit = 0;
|
size_t unit = 0;
|
||||||
void build_keypad();
|
void build_keypad();
|
||||||
void build_tdj_keypad();
|
void build_tdj_keypad();
|
||||||
|
void build_popn_pika_keypad();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -605,16 +605,6 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
value_caps.LogicalMax = 255;
|
value_caps.LogicalMax = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix min and max values
|
|
||||||
if (value_caps.BitSize > 0 && value_caps.BitSize <= sizeof(value_caps.LogicalMin) * 8) {
|
|
||||||
auto shift_size = sizeof(value_caps.LogicalMin) * 8 - value_caps.BitSize + 1;
|
|
||||||
auto mask = ((uint64_t) 1 << value_caps.BitSize) - 1;
|
|
||||||
value_caps.LogicalMin &= mask;
|
|
||||||
value_caps.LogicalMin <<= shift_size;
|
|
||||||
value_caps.LogicalMin >>= shift_size;
|
|
||||||
value_caps.LogicalMax &= mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix up hat switch to initially report as neutral position
|
// fix up hat switch to initially report as neutral position
|
||||||
if (value_caps.UsagePage == 0x1 && value_caps.Range.UsageMin == 0x39) {
|
if (value_caps.UsagePage == 0x1 && value_caps.Range.UsageMin == 0x39) {
|
||||||
value_states[value_cap_num] = -1.f;
|
value_states[value_cap_num] = -1.f;
|
||||||
@@ -1914,15 +1904,6 @@ LRESULT CALLBACK rawinput::RawInputManager::input_wnd_proc(
|
|||||||
LONG value_min = value_caps.LogicalMin;
|
LONG value_min = value_caps.LogicalMin;
|
||||||
LONG value_max = value_caps.LogicalMax;
|
LONG value_max = value_caps.LogicalMax;
|
||||||
|
|
||||||
// fix sign bits for signed values
|
|
||||||
if (value_caps.LogicalMin < 0 &&
|
|
||||||
value_caps.BitSize > 0 &&
|
|
||||||
value_caps.BitSize <= sizeof(value_caps.LogicalMin) * 8) {
|
|
||||||
auto shift_size = sizeof(value_caps.LogicalMin) * 8 - value_caps.BitSize + 1;
|
|
||||||
value_raw <<= shift_size;
|
|
||||||
value_raw >>= shift_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
float value;
|
float value;
|
||||||
// 0x1 == generic desktop, 0x39 == hat switch
|
// 0x1 == generic desktop, 0x39 == hat switch
|
||||||
if (value_caps.UsagePage == 0x1 && value_caps.Range.UsageMin == 0x39) {
|
if (value_caps.UsagePage == 0x1 && value_caps.Range.UsageMin == 0x39) {
|
||||||
@@ -1935,6 +1916,16 @@ LRESULT CALLBACK rawinput::RawInputManager::input_wnd_proc(
|
|||||||
value = -1.f;
|
value = -1.f;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// fix sign bits for signed values
|
||||||
|
if (value_caps.LogicalMin < 0 &&
|
||||||
|
0 < value_caps.BitSize && value_caps.BitSize < 32) {
|
||||||
|
|
||||||
|
ULONG raw = static_cast<ULONG>(value_raw) & ((1u << value_caps.BitSize) - 1u);
|
||||||
|
const ULONG sign_bit = 1u << (value_caps.BitSize - 1);
|
||||||
|
value_raw = static_cast<LONG>((raw ^ sign_bit) - sign_bit);
|
||||||
|
}
|
||||||
|
|
||||||
// automatic calibration
|
// automatic calibration
|
||||||
if (value_raw < value_min) {
|
if (value_raw < value_min) {
|
||||||
value_caps.LogicalMin = value_raw;
|
value_caps.LogicalMin = value_raw;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ namespace rawinput::touch {
|
|||||||
|
|
||||||
// check type
|
// check type
|
||||||
if (device->type != HID) {
|
if (device->type != HID) {
|
||||||
log_fatal("rawinput", "touch update called on non HID device");
|
log_warning("rawinput", "touch update called on non HID device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user