Update to spice2x-25-04-25 (pre-apply)
> broken commit
This commit is contained in:
@@ -70,6 +70,9 @@ void acio::attach() {
|
||||
libraryhook_hook_library("libacioex.dll", acio::DLL_INSTANCE);
|
||||
libraryhook_hook_library("libacio_ex.dll", acio::DLL_INSTANCE);
|
||||
libraryhook_hook_library("libacio_old.dll", acio::DLL_INSTANCE);
|
||||
// libacioEx.dll for Road Fighters 3D
|
||||
// needed as comparisons in LoadLibrary hooks are case-sensitive
|
||||
libraryhook_hook_library("libacioEx.dll", acio::DLL_INSTANCE);
|
||||
libraryhook_enable(avs::game::DLL_INSTANCE);
|
||||
|
||||
// get hook mode
|
||||
|
||||
+288
-2
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "avs/game.h"
|
||||
#include "games/ddr/io.h"
|
||||
#include "games/ddr/ddr.h"
|
||||
#include "games/sdvx/sdvx.h"
|
||||
#include "games/sdvx/io.h"
|
||||
#include "games/drs/io.h"
|
||||
@@ -9,6 +10,7 @@
|
||||
#include "misc/eamuse.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
#include "util/tapeled.h"
|
||||
|
||||
using namespace GameAPI;
|
||||
|
||||
@@ -399,6 +401,148 @@ static long __cdecl ac_io_bi2a_control_led_bright(size_t index, uint8_t brightne
|
||||
if (light.light2 >= 0) {
|
||||
Lights::writeLight(RI_MGR, lights[light.light2], brightness / light.max);
|
||||
}
|
||||
|
||||
// DANCERUSH
|
||||
} else if (avs::game::is_model("REC")) {
|
||||
|
||||
/*
|
||||
* Control R G B
|
||||
* ==============================
|
||||
* CARD UNIT 13 14 15
|
||||
* TITLE PANEL 28 29 30
|
||||
* MONITOR SIDE LEFT (tape LED - see ac_io_bi2a_control_tapeled_bright)
|
||||
* MONITOR SIDE RIGHT (tape LED - see ac_io_bi2a_control_tapeled_bright)
|
||||
*
|
||||
* Values go up to 127.
|
||||
*
|
||||
* Control Index
|
||||
* ==================
|
||||
* 1P LEFT 11
|
||||
* 1P RIGHT 12
|
||||
* 1P UP 9
|
||||
* 1P DOWN 10
|
||||
* 1P START 8
|
||||
* 2P LEFT 19
|
||||
* 2P RIGHT 20
|
||||
* 2P UP 17
|
||||
* 2P DOWN 18
|
||||
* 2P START 16
|
||||
*
|
||||
* Values go up to 127.
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
int light;
|
||||
float max;
|
||||
} mapping[] = {
|
||||
{ -1, 0 }, // 0
|
||||
{ -1, 0 }, // 1
|
||||
{ -1, 0 }, // 2
|
||||
{ -1, 0 }, // 3
|
||||
{ -1, 0 }, // 4
|
||||
{ -1, 0 }, // 5
|
||||
{ -1, 0 }, // 6
|
||||
{ -1, 0 }, // 7
|
||||
{ games::drs::Lights::P1_START, 127 }, // 8
|
||||
{ games::drs::Lights::P1_MENU_UP, 127 }, // 9
|
||||
{ games::drs::Lights::P1_MENU_DOWN, 127 }, // 10
|
||||
{ games::drs::Lights::P1_MENU_LEFT, 127 }, // 11
|
||||
{ games::drs::Lights::P1_MENU_RIGHT, 127 }, // 12
|
||||
{ games::drs::Lights::CARD_READER_R, 127 }, // 13
|
||||
{ games::drs::Lights::CARD_READER_G, 127 }, // 14
|
||||
{ games::drs::Lights::CARD_READER_B, 127 }, // 15
|
||||
{ games::drs::Lights::P2_START, 127 }, // 16
|
||||
{ games::drs::Lights::P2_MENU_UP, 127 }, // 17
|
||||
{ games::drs::Lights::P2_MENU_DOWN, 127 }, // 18
|
||||
{ games::drs::Lights::P2_MENU_LEFT, 127 }, // 19
|
||||
{ games::drs::Lights::P2_MENU_RIGHT, 127 }, // 20
|
||||
{ -1, 0 }, // 21
|
||||
{ -1, 0 }, // 22
|
||||
{ -1, 0 }, // 23
|
||||
{ -1, 0 }, // 24
|
||||
{ -1, 0 }, // 25
|
||||
{ -1, 0 }, // 26
|
||||
{ -1, 0 }, // 27
|
||||
{ games::drs::Lights::TITLE_PANEL_R, 127 }, // 28
|
||||
{ games::drs::Lights::TITLE_PANEL_G, 127 }, // 29
|
||||
{ games::drs::Lights::TITLE_PANEL_B, 127 }, // 30
|
||||
};
|
||||
|
||||
// ignore index out of range
|
||||
if (index > std::size(mapping)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get lights
|
||||
auto &lights = games::drs::get_lights();
|
||||
|
||||
// get light from mapping
|
||||
auto light = mapping[index];
|
||||
|
||||
// write lights
|
||||
if (light.light >= 0) {
|
||||
Lights::writeLight(RI_MGR, lights[light.light], brightness / light.max);
|
||||
} else {
|
||||
log_warning("drs", "light unset {} {}", index, (int) brightness);
|
||||
}
|
||||
|
||||
// DanceDanceRevolution
|
||||
} else if (avs::game::is_model("MDX")) {
|
||||
|
||||
static const struct {
|
||||
int light;
|
||||
float max;
|
||||
} mapping[] = {
|
||||
{ -1, 0 }, // 0
|
||||
{ -1, 0 }, // 1
|
||||
{ -1, 0 }, // 2
|
||||
{ -1, 0 }, // 3
|
||||
{ -1, 0 }, // 4
|
||||
{ -1, 0 }, // 5
|
||||
{ -1, 0 }, // 6
|
||||
{ -1, 0 }, // 7
|
||||
{ games::ddr::Lights::GOLD_P1_MENU_START, 127 }, // 8
|
||||
{ games::ddr::Lights::GOLD_P1_MENU_UP, 127 }, // 9
|
||||
{ games::ddr::Lights::GOLD_P1_MENU_DOWN, 127 }, // 10
|
||||
{ games::ddr::Lights::GOLD_P1_MENU_LEFT, 127 }, // 11
|
||||
{ games::ddr::Lights::GOLD_P1_MENU_RIGHT, 127 }, // 12
|
||||
{ games::ddr::Lights::GOLD_P1_CARD_UNIT_R, 127 }, // 13
|
||||
{ games::ddr::Lights::GOLD_P1_CARD_UNIT_G, 127 }, // 14
|
||||
{ games::ddr::Lights::GOLD_P1_CARD_UNIT_B, 127 }, // 15
|
||||
{ games::ddr::Lights::GOLD_P2_MENU_START, 127 }, // 16
|
||||
{ games::ddr::Lights::GOLD_P2_MENU_UP, 127 }, // 17
|
||||
{ games::ddr::Lights::GOLD_P2_MENU_DOWN, 127 }, // 18
|
||||
{ games::ddr::Lights::GOLD_P2_MENU_LEFT, 127 }, // 19
|
||||
{ games::ddr::Lights::GOLD_P2_MENU_RIGHT, 127 }, // 20
|
||||
{ games::ddr::Lights::GOLD_P2_CARD_UNIT_R, 0 }, // 21
|
||||
{ games::ddr::Lights::GOLD_P2_CARD_UNIT_G, 0 }, // 22
|
||||
{ games::ddr::Lights::GOLD_P2_CARD_UNIT_B, 0 }, // 23
|
||||
{ -1, 0 }, // 24
|
||||
{ -1, 0 }, // 25
|
||||
{ -1, 0 }, // 26
|
||||
{ -1, 0 }, // 27
|
||||
{ games::ddr::Lights::GOLD_TITLE_PANEL_LEFT, 0 }, // 28
|
||||
{ games::ddr::Lights::GOLD_TITLE_PANEL_CENTER, 0 }, // 29
|
||||
{ games::ddr::Lights::GOLD_TITLE_PANEL_RIGHT, 0 }, // 30
|
||||
{ games::ddr::Lights::GOLD_P1_WOOFER_CORNER, 0 }, // 31
|
||||
{ games::ddr::Lights::GOLD_P2_WOOFER_CORNER, 0 } // 32
|
||||
};
|
||||
|
||||
// ignore index out of range
|
||||
if (index > std::size(mapping)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get lights
|
||||
auto &lights = games::ddr::get_lights();
|
||||
|
||||
// get light from mapping
|
||||
auto light = mapping[index];
|
||||
|
||||
// write lights
|
||||
if (light.light >= 0) {
|
||||
Lights::writeLight(RI_MGR, lights[light.light], brightness / light.max);
|
||||
}
|
||||
}
|
||||
|
||||
// return success
|
||||
@@ -443,7 +587,7 @@ static bool __cdecl ac_io_bi2a_tapeled_init_is_finished() {
|
||||
static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_sz, size_t y_sz) {
|
||||
|
||||
// check dimensions
|
||||
if (x_sz != 38 || y_sz != 49) {
|
||||
if (x_sz != DRS_TAPELED_COLS || y_sz != DRS_TAPELED_ROWS) {
|
||||
log_fatal("drs", "DRS tapeled wrong dimensions");
|
||||
}
|
||||
|
||||
@@ -458,9 +602,151 @@ static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_s
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: this controls the upright RGB bars on the sides
|
||||
// TODO: DRS tape lights
|
||||
static bool __cdecl ac_io_bi2a_control_tapeled_bright(size_t off1, size_t off2,
|
||||
uint8_t r, uint8_t g, uint8_t b, uint8_t bank) {
|
||||
|
||||
if (!tapeledutils::is_enabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (avs::game::is_model("MDX")) {
|
||||
|
||||
/*
|
||||
* r, g, b values range from [0-255]
|
||||
* bank always seems to be [0]
|
||||
*
|
||||
* [off1.off2] [LEDs] [tape name]
|
||||
* 0.0 25 P1 Foot Up (0.0 to 0.24, inclusive)
|
||||
* 0.25 25 P1 Foot Right
|
||||
* 1.0 25 P1 Foot Left
|
||||
* 1.25 25 P1 Foot Down
|
||||
*
|
||||
* 2.0 25 P2 Foot Up
|
||||
* 2.25 25 P2 Foot Right
|
||||
* 3.0 25 P2 Foot Left
|
||||
* 3.25 25 P2 Foot Down
|
||||
*
|
||||
* 5.0 50 Top Panel
|
||||
* 6.0 50 Monitor side left
|
||||
* 7.0 50 Monitor side right
|
||||
*/
|
||||
|
||||
// In order to set the data that can be output via Spice API, we first
|
||||
// need to figure out which device in our buffers this data belongs to
|
||||
int device = -1;
|
||||
if (off1 == 0) {
|
||||
if (off2 < 25) device = 0; // P1 Foot Up
|
||||
else device = 1; // P1 Foot Right
|
||||
} else if (off1 == 1) {
|
||||
if (off2 < 25) device = 2; // P1 Foot Left
|
||||
else device = 3; // P1 Foot Down
|
||||
} else if (off1 == 2) {
|
||||
if (off2 < 25) device = 4; // P2 Foot Up
|
||||
else device = 5; // P2 Foot Right
|
||||
} else if (off1 == 3) {
|
||||
if (off2 < 25) device = 6; // P2 Foot Left
|
||||
else device = 7; // P2 Foot Down
|
||||
} else if (off1 >= 5 && off1 <= 7) {
|
||||
device = off1 + 3; // Top Panel / Monitor Side Left / Monitor Side Right
|
||||
}
|
||||
|
||||
if (device != -1) {
|
||||
// We subtract 25 from off2 to get the device's LED index, if it's for one of the
|
||||
// arrow panels that is on the latter half of the logical strip
|
||||
size_t subtractor = 0;
|
||||
if (off1 <= 3 && off2 >= 25) {
|
||||
subtractor = 25;
|
||||
}
|
||||
size_t led_index = off2 - subtractor;
|
||||
|
||||
games::ddr::DDR_TAPELEDS[device][led_index][0] = r;
|
||||
games::ddr::DDR_TAPELEDS[device][led_index][1] = g;
|
||||
games::ddr::DDR_TAPELEDS[device][led_index][2] = b;
|
||||
}
|
||||
|
||||
static struct TapeLedMapping {
|
||||
bool split; // true == 50 LEDs for one light, false == 25 for two lights
|
||||
uint8_t index_r0, index_g0, index_b0;
|
||||
uint8_t index_r1, index_g1, index_b1;
|
||||
size_t index_for_avg0 = UINT8_MAX;
|
||||
size_t index_for_avg1 = UINT8_MAX;
|
||||
|
||||
TapeLedMapping(
|
||||
uint8_t index_r0, uint8_t index_g0, uint8_t index_b0,
|
||||
uint8_t index_r1, uint8_t index_g1, uint8_t index_b1)
|
||||
: index_r0(index_r0), index_g0(index_g0), index_b0(index_b0),
|
||||
index_r1(index_r1), index_g1(index_g1), index_b1(index_b1) {
|
||||
|
||||
split = (index_r1 != UINT8_MAX);
|
||||
if (split) {
|
||||
index_for_avg0 = tapeledutils::get_led_index_using_avg_algo(25);
|
||||
index_for_avg1 = index_for_avg0 + 25;
|
||||
} else {
|
||||
index_for_avg0 = tapeledutils::get_led_index_using_avg_algo(50);
|
||||
index_for_avg1 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} mapping[] = {
|
||||
{
|
||||
games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_B,
|
||||
games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_B
|
||||
},
|
||||
{
|
||||
games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_B,
|
||||
games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_B
|
||||
},
|
||||
{
|
||||
games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_B,
|
||||
games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_B
|
||||
},
|
||||
{
|
||||
games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_B,
|
||||
games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_B
|
||||
},
|
||||
{
|
||||
games::ddr::Lights::GOLD_TOP_PANEL_AVG_R, games::ddr::Lights::GOLD_TOP_PANEL_AVG_G, games::ddr::Lights::GOLD_TOP_PANEL_AVG_B,
|
||||
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||
},
|
||||
{
|
||||
UINT8_MAX, UINT8_MAX, UINT8_MAX,
|
||||
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||
},
|
||||
{
|
||||
games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_R, games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_G, games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_B,
|
||||
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||
},
|
||||
{
|
||||
games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_R, games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_G, games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_B,
|
||||
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||
},
|
||||
};
|
||||
|
||||
if (off1 < std::size(mapping)) {
|
||||
auto &map = mapping[off1];
|
||||
|
||||
size_t off2_match = -1;
|
||||
if (!map.split || off2 < 25) {
|
||||
off2_match = map.index_for_avg0;
|
||||
} else {
|
||||
off2_match = map.index_for_avg1;
|
||||
}
|
||||
if (off2_match == off2 && map.index_r0 != UINT8_MAX) {
|
||||
auto &lights = games::ddr::get_lights();
|
||||
if (!map.split || off2 < 25) {
|
||||
Lights::writeLight(RI_MGR, lights[map.index_r0], r / 255.f);
|
||||
Lights::writeLight(RI_MGR, lights[map.index_g0], g / 255.f);
|
||||
Lights::writeLight(RI_MGR, lights[map.index_b0], b / 255.f);
|
||||
} else {
|
||||
Lights::writeLight(RI_MGR, lights[map.index_r1], r / 255.f);
|
||||
Lights::writeLight(RI_MGR, lights[map.index_g1], g / 255.f);
|
||||
Lights::writeLight(RI_MGR, lights[map.index_b1], b / 255.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_off() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 0.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -44,6 +49,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_on() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 1.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -55,6 +65,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_off() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 0.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -66,6 +81,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_on() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 1.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
+47
-12
@@ -25,6 +25,13 @@ struct ICCA_STATUS {
|
||||
uint32_t key_edge;
|
||||
uint32_t key_level;
|
||||
};
|
||||
struct ICCA_STATUS_LA9 {
|
||||
uint8_t status_code;
|
||||
uint8_t card_in;
|
||||
uint8_t uid[8];
|
||||
uint8_t error;
|
||||
uint8_t uid2[8];
|
||||
};
|
||||
static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes");
|
||||
|
||||
enum ICCA_WORKFLOW {
|
||||
@@ -52,6 +59,7 @@ struct ICCA_UNIT {
|
||||
char key_serial = 0;
|
||||
bool uid_skip = false;
|
||||
bool initialized = false;
|
||||
int felica_retries = 0;
|
||||
};
|
||||
static ICCA_UNIT ICCA_UNITS[2] {};
|
||||
static bool IS_LAST_CARD_FELICA = false;
|
||||
@@ -88,14 +96,25 @@ static inline void update_card(int unit_id) {
|
||||
// eamio keypress
|
||||
int index = unit_id > 0 && icca_get_active_count() > 1 ? 1 : 0;
|
||||
bool kb_insert_press = (eamuse_get_keypad_state(index) & (1 << EAM_IO_INSERT)) > 0;
|
||||
static bool kb_insert_press_old[2] = {false, false};
|
||||
|
||||
// get unit
|
||||
ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
|
||||
|
||||
const bool card_presented = eamuse_card_insert_consume(icca_get_active_count(), unit_id);
|
||||
const bool key_pressed = (kb_insert_press && !kb_insert_press_old[unit_id]);
|
||||
|
||||
// beatstream and nostalgia have logic that requires ac_io_icca_get_uid_felica to return the
|
||||
// exact same card number multiple times in a row in order for the card number to be read...
|
||||
// for whatever reason setting this to 3-4 doesn't work the very first time the game boots up
|
||||
// so we use 10 just to be safe
|
||||
const bool need_felica_retries = avs::game::is_model({"NBT", "PAN"});
|
||||
if (need_felica_retries && (card_presented || key_pressed)) {
|
||||
unit->felica_retries = 10;
|
||||
}
|
||||
|
||||
// check for card insert
|
||||
static bool kb_insert_press_old[2] = {false, false};
|
||||
if (eamuse_card_insert_consume(icca_get_active_count(), unit_id) ||
|
||||
(kb_insert_press && !kb_insert_press_old[unit_id])) {
|
||||
if (card_presented || key_pressed || (0 < unit->felica_retries)) {
|
||||
if (!unit->card_cmd_pressed) {
|
||||
unit->card_cmd_pressed = true;
|
||||
if (unit->state == GET_USERID || unit->state == CLOSE_EJECT || unit->state == STEP) {
|
||||
@@ -288,17 +307,29 @@ static char __cdecl ac_io_icca_get_status(void *a1, void *a2) {
|
||||
|
||||
// funny workaround
|
||||
if (acio::ICCA_COMPAT_ACTIVE) {
|
||||
if (avs::game::is_model("LA9")) {
|
||||
auto p = (ICCA_STATUS*) status;
|
||||
|
||||
// the struct is different (28 bytes instead of 24) but nobody ain't got time for that
|
||||
auto p = (ICCA_STATUS*) status;
|
||||
p->error = p->key_level << 16;
|
||||
p->front_sensor = p->uid[0];
|
||||
p->rear_sensor = p->uid[1];
|
||||
for (size_t i = 2; i < sizeof(p->uid); i++) {
|
||||
p->uid[i - 2] = p->uid[i];
|
||||
ICCA_STATUS_LA9 p_la9;
|
||||
p_la9.status_code = unit->state;
|
||||
p_la9.card_in = unit->card_in;
|
||||
memcpy(p_la9.uid, p->uid, sizeof(p_la9.uid));
|
||||
p_la9.error = p->error;
|
||||
memcpy(p_la9.uid2, p->uid, sizeof(p_la9.uid));
|
||||
|
||||
memcpy(status, &p_la9, sizeof(ICCA_STATUS_LA9));
|
||||
} else {
|
||||
// the struct is different (28 bytes instead of 24) but nobody ain't got time for that
|
||||
auto p = (ICCA_STATUS*) status;
|
||||
p->error = p->key_level << 16;
|
||||
p->front_sensor = p->uid[0];
|
||||
p->rear_sensor = p->uid[1];
|
||||
for (size_t i = 2; i < sizeof(p->uid); i++) {
|
||||
p->uid[i - 2] = p->uid[i];
|
||||
}
|
||||
p->uid[sizeof(p->uid) - 2] = 0;
|
||||
p->uid[sizeof(p->uid) - 1] = 0;
|
||||
}
|
||||
p->uid[sizeof(p->uid) - 2] = 0;
|
||||
p->uid[sizeof(p->uid) - 1] = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -330,6 +361,10 @@ static char __cdecl ac_io_icca_get_uid_felica(int unit_id, char *card) {
|
||||
card[8] = (char) (felica ? 1 : 0);
|
||||
IS_LAST_CARD_FELICA = felica;
|
||||
|
||||
if (0 < unit->felica_retries) {
|
||||
unit->felica_retries--;
|
||||
}
|
||||
|
||||
// check for error
|
||||
return unit->state != ERR_GETUID;
|
||||
}
|
||||
|
||||
+68
-16
@@ -16,13 +16,26 @@ static uint8_t COUNTER = 0;
|
||||
// buffers
|
||||
#pragma pack(push, 1)
|
||||
static struct {
|
||||
uint8_t STATUS_BUFFER_17[7][STATUS_BUFFER_SIZE] {};
|
||||
uint8_t STATUS_BUFFER_18[7][STATUS_BUFFER_SIZE] {};
|
||||
uint8_t STATUS_BUFFER_P1[7][STATUS_BUFFER_SIZE] {};
|
||||
uint8_t STATUS_BUFFER_P2[7][STATUS_BUFFER_SIZE] {};
|
||||
} BUFFERS {};
|
||||
#pragma pack(pop)
|
||||
|
||||
static bool STATUS_BUFFER_FREEZE = false;
|
||||
|
||||
typedef uint64_t (__cdecl *ARK_GET_TICK_TIME64_T)();
|
||||
|
||||
static uint64_t arkGetTickTime64() {
|
||||
static ARK_GET_TICK_TIME64_T getTickTime64 =
|
||||
(ARK_GET_TICK_TIME64_T)GetProcAddress(avs::game::DLL_INSTANCE, "arkGetTickTime64");
|
||||
if (getTickTime64 == nullptr) {
|
||||
// this works on 32-bit versions of avs, but not on 64.
|
||||
// it's better than nothing though.
|
||||
return timeGetTime();
|
||||
}
|
||||
return getTickTime64();
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementations
|
||||
*/
|
||||
@@ -33,13 +46,13 @@ static bool __cdecl ac_io_mdxf_get_control_status_buffer(int node, void *buffer,
|
||||
if (avs::game::is_model("MDX")) {
|
||||
|
||||
// get buffer index
|
||||
auto i = (COUNTER + a3) % std::size(BUFFERS.STATUS_BUFFER_17);
|
||||
auto i = (COUNTER + a3) % std::size(BUFFERS.STATUS_BUFFER_P1);
|
||||
|
||||
// copy buffer
|
||||
if (node == 17) {
|
||||
memcpy(buffer, BUFFERS.STATUS_BUFFER_17[i], STATUS_BUFFER_SIZE);
|
||||
} else if (node == 18) {
|
||||
memcpy(buffer, BUFFERS.STATUS_BUFFER_18[i], STATUS_BUFFER_SIZE);
|
||||
if (node == 17 || node == 25) {
|
||||
memcpy(buffer, BUFFERS.STATUS_BUFFER_P1[i], STATUS_BUFFER_SIZE);
|
||||
} else if (node == 18 || node == 26) {
|
||||
memcpy(buffer, BUFFERS.STATUS_BUFFER_P2[i], STATUS_BUFFER_SIZE);
|
||||
} else {
|
||||
|
||||
// fill with zeros on unknown node
|
||||
@@ -52,16 +65,49 @@ static bool __cdecl ac_io_mdxf_get_control_status_buffer(int node, void *buffer,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2, uint8_t a3) {
|
||||
// TODO(felix): DDR BIO2 lights
|
||||
static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2, uint8_t value) {
|
||||
if (avs::game::is_model("MDX")) {
|
||||
static const struct {
|
||||
int a2[4];
|
||||
} mapping[] = {
|
||||
{
|
||||
// a1 == 17
|
||||
{
|
||||
games::ddr::Lights::GOLD_P1_STAGE_UP_RIGHT,
|
||||
games::ddr::Lights::GOLD_P1_STAGE_DOWN_LEFT,
|
||||
games::ddr::Lights::GOLD_P1_STAGE_UP_LEFT,
|
||||
games::ddr::Lights::GOLD_P1_STAGE_DOWN_RIGHT
|
||||
}
|
||||
},
|
||||
{
|
||||
// a1 == 18
|
||||
{
|
||||
games::ddr::Lights::GOLD_P2_STAGE_UP_RIGHT,
|
||||
games::ddr::Lights::GOLD_P2_STAGE_DOWN_LEFT,
|
||||
games::ddr::Lights::GOLD_P2_STAGE_UP_LEFT,
|
||||
games::ddr::Lights::GOLD_P2_STAGE_DOWN_RIGHT
|
||||
}
|
||||
}
|
||||
};
|
||||
if ((a1 == 17 || a1 == 18) && (a2 < 4)) {
|
||||
// get light from mapping
|
||||
const auto light = mapping[a1 - 17].a2[a2];
|
||||
|
||||
// get lights
|
||||
auto &lights = games::ddr::get_lights();
|
||||
|
||||
// write lights
|
||||
GameAPI::Lights::writeLight(RI_MGR, lights[light], value / 128.f);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
||||
|
||||
// increase counter
|
||||
COUNTER = (COUNTER + 1) % std::size(BUFFERS.STATUS_BUFFER_17);
|
||||
COUNTER = (COUNTER + 1) % std::size(BUFFERS.STATUS_BUFFER_P1);
|
||||
|
||||
// check freeze
|
||||
if (STATUS_BUFFER_FREEZE) {
|
||||
@@ -72,10 +118,12 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
||||
uint8_t *buffer = nullptr;
|
||||
switch (node) {
|
||||
case 17:
|
||||
buffer = BUFFERS.STATUS_BUFFER_17[COUNTER];
|
||||
case 25:
|
||||
buffer = BUFFERS.STATUS_BUFFER_P1[COUNTER];
|
||||
break;
|
||||
case 18:
|
||||
buffer = BUFFERS.STATUS_BUFFER_18[COUNTER];
|
||||
case 26:
|
||||
buffer = BUFFERS.STATUS_BUFFER_P2[COUNTER];
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -92,13 +140,13 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
||||
// FOOT UP = bit 36-39 = byte 4, bit 4-7
|
||||
// FOOT RIGHT = bit 40-43 = byte 5, bit 0-3
|
||||
// FOOT LEFT = bit 44-47 = byte 5, bit 4-7
|
||||
static const size_t buttons_17[] = {
|
||||
static const size_t buttons_p1[] = {
|
||||
games::ddr::Buttons::P1_PANEL_UP,
|
||||
games::ddr::Buttons::P1_PANEL_DOWN,
|
||||
games::ddr::Buttons::P1_PANEL_LEFT,
|
||||
games::ddr::Buttons::P1_PANEL_RIGHT,
|
||||
};
|
||||
static const size_t buttons_18[] = {
|
||||
static const size_t buttons_p2[] = {
|
||||
games::ddr::Buttons::P2_PANEL_UP,
|
||||
games::ddr::Buttons::P2_PANEL_DOWN,
|
||||
games::ddr::Buttons::P2_PANEL_LEFT,
|
||||
@@ -109,13 +157,17 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
||||
const size_t *button_map = nullptr;
|
||||
switch (node) {
|
||||
case 17:
|
||||
button_map = &buttons_17[0];
|
||||
case 25:
|
||||
button_map = &buttons_p1[0];
|
||||
break;
|
||||
case 18:
|
||||
button_map = &buttons_18[0];
|
||||
case 26:
|
||||
button_map = &buttons_p2[0];
|
||||
break;
|
||||
}
|
||||
|
||||
*(uint64_t*)&buffer[0x18] = arkGetTickTime64();
|
||||
|
||||
// get buttons
|
||||
auto &buttons = games::ddr::get_buttons();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
+110
-9
@@ -6,6 +6,11 @@
|
||||
#include "util/logging.h"
|
||||
#include "avs/game.h"
|
||||
|
||||
// std::min
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
using namespace GameAPI;
|
||||
|
||||
// static stuff
|
||||
@@ -79,6 +84,32 @@ static bool __cdecl ac_io_panb_start_auto_input() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t panb_get_button_velocity(Button button, Button button_soft, Button button_medium, Button button_hard) {
|
||||
const auto velocity = Buttons::getVelocity(RI_MGR, button);
|
||||
const auto velocity_soft = Buttons::getVelocity(RI_MGR, button_soft);
|
||||
const auto velocity_medium = Buttons::getVelocity(RI_MGR, button_medium);
|
||||
const auto velocity_hard = Buttons::getVelocity(RI_MGR, button_hard);
|
||||
|
||||
// note that the digital values have been obtained via trial-and-error in recital mode
|
||||
// based on Op3:
|
||||
// * soft presses glow blue, should trigger Elegant in blue sections
|
||||
// * hard presses glow red/orange, should trigger Elegant in yellow sections
|
||||
// * default (medium) presses glow green, triggers Elegant in both blue and yellow sections
|
||||
|
||||
// digital-only values
|
||||
if (velocity_hard > 0.f) {
|
||||
// do NOT use 15 here!! 14 properly registers as a hard press, but 15 does not
|
||||
return 14;
|
||||
} else if (velocity_medium > 0.f) {
|
||||
return 11;
|
||||
} else if (velocity_soft > 0.f) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// digital or midi (velocity-sensitive) values
|
||||
return std::min((uint8_t)(velocity * 15.999f), (uint8_t)14);
|
||||
}
|
||||
|
||||
static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
||||
|
||||
// check freeze
|
||||
@@ -107,6 +138,7 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
||||
auto &analogs = games::nost::get_analogs();
|
||||
|
||||
// mappings
|
||||
// "normal" buttons - these are velocity sensitive (digital or MIDI)
|
||||
static const size_t button_mapping[] = {
|
||||
games::nost::Buttons::Key1, games::nost::Buttons::Key2,
|
||||
games::nost::Buttons::Key3, games::nost::Buttons::Key4,
|
||||
@@ -123,6 +155,60 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
||||
games::nost::Buttons::Key25, games::nost::Buttons::Key26,
|
||||
games::nost::Buttons::Key27, games::nost::Buttons::Key28,
|
||||
};
|
||||
|
||||
// soft (digital) button - always registers as soft press
|
||||
static const size_t soft_button_mapping[] = {
|
||||
games::nost::Buttons::Key1Soft, games::nost::Buttons::Key2Soft,
|
||||
games::nost::Buttons::Key3Soft, games::nost::Buttons::Key4Soft,
|
||||
games::nost::Buttons::Key5Soft, games::nost::Buttons::Key6Soft,
|
||||
games::nost::Buttons::Key7Soft, games::nost::Buttons::Key8Soft,
|
||||
games::nost::Buttons::Key9Soft, games::nost::Buttons::Key10Soft,
|
||||
games::nost::Buttons::Key11Soft, games::nost::Buttons::Key12Soft,
|
||||
games::nost::Buttons::Key13Soft, games::nost::Buttons::Key14Soft,
|
||||
games::nost::Buttons::Key15Soft, games::nost::Buttons::Key16Soft,
|
||||
games::nost::Buttons::Key17Soft, games::nost::Buttons::Key18Soft,
|
||||
games::nost::Buttons::Key19Soft, games::nost::Buttons::Key20Soft,
|
||||
games::nost::Buttons::Key21Soft, games::nost::Buttons::Key22Soft,
|
||||
games::nost::Buttons::Key23Soft, games::nost::Buttons::Key24Soft,
|
||||
games::nost::Buttons::Key25Soft, games::nost::Buttons::Key26Soft,
|
||||
games::nost::Buttons::Key27Soft, games::nost::Buttons::Key28Soft,
|
||||
};
|
||||
|
||||
// medium (digital) button - always registers as medium press
|
||||
static const size_t medium_button_mapping[] = {
|
||||
games::nost::Buttons::Key1Medium, games::nost::Buttons::Key2Medium,
|
||||
games::nost::Buttons::Key3Medium, games::nost::Buttons::Key4Medium,
|
||||
games::nost::Buttons::Key5Medium, games::nost::Buttons::Key6Medium,
|
||||
games::nost::Buttons::Key7Medium, games::nost::Buttons::Key8Medium,
|
||||
games::nost::Buttons::Key9Medium, games::nost::Buttons::Key10Medium,
|
||||
games::nost::Buttons::Key11Medium, games::nost::Buttons::Key12Medium,
|
||||
games::nost::Buttons::Key13Medium, games::nost::Buttons::Key14Medium,
|
||||
games::nost::Buttons::Key15Medium, games::nost::Buttons::Key16Medium,
|
||||
games::nost::Buttons::Key17Medium, games::nost::Buttons::Key18Medium,
|
||||
games::nost::Buttons::Key19Medium, games::nost::Buttons::Key20Medium,
|
||||
games::nost::Buttons::Key21Medium, games::nost::Buttons::Key22Medium,
|
||||
games::nost::Buttons::Key23Medium, games::nost::Buttons::Key24Medium,
|
||||
games::nost::Buttons::Key25Medium, games::nost::Buttons::Key26Medium,
|
||||
games::nost::Buttons::Key27Medium, games::nost::Buttons::Key28Medium,
|
||||
};
|
||||
|
||||
// hard (digital) button - always registers as hard press
|
||||
static const size_t hard_button_mapping[] = {
|
||||
games::nost::Buttons::Key1Hard, games::nost::Buttons::Key2Hard,
|
||||
games::nost::Buttons::Key3Hard, games::nost::Buttons::Key4Hard,
|
||||
games::nost::Buttons::Key5Hard, games::nost::Buttons::Key6Hard,
|
||||
games::nost::Buttons::Key7Hard, games::nost::Buttons::Key8Hard,
|
||||
games::nost::Buttons::Key9Hard, games::nost::Buttons::Key10Hard,
|
||||
games::nost::Buttons::Key11Hard, games::nost::Buttons::Key12Hard,
|
||||
games::nost::Buttons::Key13Hard, games::nost::Buttons::Key14Hard,
|
||||
games::nost::Buttons::Key15Hard, games::nost::Buttons::Key16Hard,
|
||||
games::nost::Buttons::Key17Hard, games::nost::Buttons::Key18Hard,
|
||||
games::nost::Buttons::Key19Hard, games::nost::Buttons::Key20Hard,
|
||||
games::nost::Buttons::Key21Hard, games::nost::Buttons::Key22Hard,
|
||||
games::nost::Buttons::Key23Hard, games::nost::Buttons::Key24Hard,
|
||||
games::nost::Buttons::Key25Hard, games::nost::Buttons::Key26Hard,
|
||||
games::nost::Buttons::Key27Hard, games::nost::Buttons::Key28Hard,
|
||||
};
|
||||
static const size_t analog_mapping[] = {
|
||||
games::nost::Analogs::Key1, games::nost::Analogs::Key2,
|
||||
games::nost::Analogs::Key3, games::nost::Analogs::Key4,
|
||||
@@ -148,23 +234,38 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
||||
uint8_t state1 = 0;
|
||||
|
||||
// check analogs
|
||||
//
|
||||
// while 15 is technically allowed by the I/O board & is recognized correctly in test
|
||||
// menu, when you play recital mode, 15 fails to register Elegant in yellow sections.
|
||||
// therefore, cap the value at 14. tested with Nostroller.
|
||||
auto &analog0 = analogs.at(analog_mapping[key_pair * 2 + 0]);
|
||||
auto &analog1 = analogs.at(analog_mapping[key_pair * 2 + 1]);
|
||||
if (analog0.isSet()) {
|
||||
state0 = (uint8_t) (Analogs::getState(RI_MGR, analog0) * 15.999f);
|
||||
state0 = std::min((uint8_t)(Analogs::getState(RI_MGR, analog0) * 15.999f), (uint8_t)14);
|
||||
}
|
||||
if (analog1.isSet()) {
|
||||
state1 = (uint8_t) (Analogs::getState(RI_MGR, analog1) * 15.999f);
|
||||
state1 = std::min((uint8_t)(Analogs::getState(RI_MGR, analog1) * 15.999f), (uint8_t)14);
|
||||
}
|
||||
|
||||
// check buttons
|
||||
auto velocity0 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 0]));
|
||||
auto velocity1 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 1]));
|
||||
if (velocity0 > 0.f) {
|
||||
state0 = (uint8_t) (velocity0 * 15.999f);
|
||||
// check digital buttons
|
||||
const auto button0 = panb_get_button_velocity(
|
||||
buttons.at(button_mapping[key_pair * 2 + 0]),
|
||||
buttons.at(soft_button_mapping[key_pair * 2 + 0]),
|
||||
buttons.at(medium_button_mapping[key_pair * 2 + 0]),
|
||||
buttons.at(hard_button_mapping[key_pair * 2 + 0])
|
||||
);
|
||||
if (button0 > 0) {
|
||||
state0 = button0;
|
||||
}
|
||||
if (velocity1 > 0.f) {
|
||||
state1 = (uint8_t) (velocity1 * 15.999f);
|
||||
|
||||
const auto button1 = panb_get_button_velocity(
|
||||
buttons.at(button_mapping[key_pair * 2 + 1]),
|
||||
buttons.at(soft_button_mapping[key_pair * 2 + 1]),
|
||||
buttons.at(medium_button_mapping[key_pair * 2 + 1]),
|
||||
buttons.at(hard_button_mapping[key_pair * 2 + 1])
|
||||
);
|
||||
if (button1 > 0) {
|
||||
state1 = button1;
|
||||
}
|
||||
|
||||
// build value
|
||||
|
||||
Reference in New Issue
Block a user