mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
MDX: Updated Ring Buffer Backfill Implementation (P4IO Timing Fix) (#456)
## Link to GitHub Issue, if one exists #452 ## Description of change - Extension of #450 - Moved the call to `arkGetTickTime64()` outside the update function to bring the timestamps closer to real-time - Changed the update function to only call `getState()` if called from `rawinput`, otherwise just fill the ring buffer entries with the last known state - Changed the update function to only write one ring buffer entry if called from `rawinput` - Moved the call to `mdxf_poll()` within `rawinput.cpp` outside the loop that iterates over all devices ## Testing - Logging was done to verify the span of poll history covered by each request for 7 ring buffer entries was ~28ms, as the game expects - Observed some improvement in timing precision since the prior implementation
This commit is contained in:
@@ -152,7 +152,7 @@ static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl ac_io_mdxf_update_control_status_buffer_impl(int node, MDXFPollSource source) {
|
||||
static bool __cdecl ac_io_mdxf_update_control_status_buffer_impl(int node, MDXFPollSource source, uint64_t current_time) {
|
||||
|
||||
// check freeze
|
||||
if (STATUS_BUFFER_FREEZE) {
|
||||
@@ -224,37 +224,38 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer_impl(int node, MDXFP
|
||||
button_map = &buttons_p2[0];
|
||||
break;
|
||||
}
|
||||
|
||||
// get buttons
|
||||
auto &buttons = games::ddr::get_buttons();
|
||||
uint8_t up_down = 0;
|
||||
uint8_t left_right = 0;
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[0]))) {
|
||||
up_down |= 0xF0;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[1]))) {
|
||||
up_down |= 0x0F;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[2]))) {
|
||||
left_right |= 0xF0;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[3]))) {
|
||||
left_right |= 0x0F;
|
||||
}
|
||||
|
||||
const uint16_t current_state = (uint16_t(up_down) << 8) | left_right;
|
||||
const uint64_t current_time = arkGetTickTime64();
|
||||
uint16_t current_state;
|
||||
if (source == EXTERNAL_POLL) {
|
||||
// get buttons
|
||||
auto &buttons = games::ddr::get_buttons();
|
||||
uint8_t up_down = 0;
|
||||
uint8_t left_right = 0;
|
||||
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[0]))) {
|
||||
up_down |= 0xF0;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[1]))) {
|
||||
up_down |= 0x0F;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[2]))) {
|
||||
left_right |= 0xF0;
|
||||
}
|
||||
if (GameAPI::Buttons::getState(RI_MGR, buttons.at(button_map[3]))) {
|
||||
left_right |= 0x0F;
|
||||
}
|
||||
current_state = (uint16_t(up_down) << 8) | left_right;
|
||||
} else {
|
||||
current_state = *prev_state;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(*mutex);
|
||||
|
||||
// If state hasn't changed and the update was triggered externally, then don't advance head pointer or write a new entry
|
||||
if (source == EXTERNAL_POLL && *prev_state == current_state) {
|
||||
return true;
|
||||
}
|
||||
const bool has_state_changed = *prev_state != current_state;
|
||||
const bool has_time_changed = *prev_time < current_time;
|
||||
|
||||
// If there's already an entry for this exact time, then don't advance head pointer or write a new entry
|
||||
if (*prev_time >= current_time) {
|
||||
// If state hasn't changed and either the update was triggered externally or the time hasn't changed, then don't advance head pointer or write a new entry
|
||||
if (!has_state_changed && (source == EXTERNAL_POLL || !has_time_changed)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -275,6 +276,11 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer_impl(int node, MDXFP
|
||||
start_time = min_time;
|
||||
}
|
||||
|
||||
// Only write one entry if called externally
|
||||
if (source == EXTERNAL_POLL) {
|
||||
start_time = stop_time - 1;
|
||||
}
|
||||
|
||||
uint64_t time = start_time;
|
||||
uint16_t state = *prev_state;
|
||||
|
||||
@@ -313,14 +319,15 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer_impl(int node, MDXFP
|
||||
}
|
||||
|
||||
static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
||||
return ac_io_mdxf_update_control_status_buffer_impl(node, ARKMDXP4_POLL);
|
||||
return ac_io_mdxf_update_control_status_buffer_impl(node, ARKMDXP4_POLL, arkGetTickTime64());
|
||||
}
|
||||
|
||||
// Used for triggering updates of the controller states from outside arkmdxp4.dll main refresh loop (i.e. within rawinput.cpp on controller events)
|
||||
void mdxf_poll() {
|
||||
if (IS_MDXF_ACTIVE) {
|
||||
ac_io_mdxf_update_control_status_buffer_impl(17, EXTERNAL_POLL);
|
||||
ac_io_mdxf_update_control_status_buffer_impl(18, EXTERNAL_POLL);
|
||||
const uint64_t call_time_ms = arkGetTickTime64();
|
||||
ac_io_mdxf_update_control_status_buffer_impl(17, EXTERNAL_POLL, call_time_ms);
|
||||
ac_io_mdxf_update_control_status_buffer_impl(18, EXTERNAL_POLL, call_time_ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user