iidx: millisecond-based delay option (#672)

## Link to GitHub Issue or related Pull Request, if one exists
#181 

## Description of change
Use millisecond-based calculation to add artificial delay to the TT
input.

## Testing
Tested 64 bit TDJ and LDJ.
This commit is contained in:
bicarus
2026-05-03 01:23:45 -07:00
committed by GitHub
parent c8962a0e77
commit c4193eddc5
2 changed files with 30 additions and 10 deletions
+22 -6
View File
@@ -789,17 +789,33 @@ namespace games::iidx {
if ((player == 0 && TT_DELAY_P1 > 0) || if ((player == 0 && TT_DELAY_P1 > 0) ||
(player == 1 && TT_DELAY_P2 > 0)) { (player == 1 && TT_DELAY_P2 > 0)) {
static std::queue<uint8_t> delay_queue[2]; static std::queue<std::pair<double, uint8_t>> delay_queue[2];
auto &queue = delay_queue[player]; auto &queue = delay_queue[player];
const auto max_size = const auto max_delta_ms =
static_cast<size_t>((player == 0) ? TT_DELAY_P1 : TT_DELAY_P2) + 1; static_cast<double>((player == 0) ? TT_DELAY_P1 : TT_DELAY_P2);
queue.push(result); // always push a new value
while (queue.size() > max_size) { const auto now = get_performance_milliseconds();
queue.push(std::make_pair(now, result));
// drain the queue down to reasonable length to prevent unconstrained growth
// this would accommodate 1 second at ~1000Hz
// (in reality all three iidx I/O emulation runs well under 500Hz)
while (queue.size() > 1024) {
queue.pop(); queue.pop();
} }
result = queue.front();
// pop until we find one that falls just under the time threshold
while (!queue.empty()) {
const auto delta_t = now - queue.front().first;
if (delta_t <= max_delta_ms) {
break;
}
queue.pop();
}
result = queue.front().second;
} }
return result; return result;
+8 -4
View File
@@ -657,21 +657,25 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
}, },
{ {
// IIDXTTDelayP1 // IIDXTTDelayP1
.title = "IIDX TT Delay Window (Player 1)", .title = "IIDX TT Delay ms (Player 1)",
.name = "iidxttdelayp1", .name = "iidxttdelayp1",
.desc = "Delays turntable by number of input polls. Duration is heavily dependent on what I/O emulation is in use. " .desc = "Delays turntable by number of milliseconds. "
"Delay will be *at most* the specified period; maximum error is dependent on the game's poll rate. "
"As usual, changing any option requires a restart. Default: 0 (no delay).", "As usual, changing any option requires a restart. Default: 0 (no delay).",
.type = OptionType::Integer, .type = OptionType::Integer,
.setting_name = "(0-500)",
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Advanced)",
}, },
{ {
// IIDXTTDelayP2 // IIDXTTDelayP2
.title = "IIDX TT Delay Window (Player 2)", .title = "IIDX TT Delay ms (Player 2)",
.name = "iidxttdelayp2", .name = "iidxttdelayp2",
.desc = "Delays turntable by number of input polls. Duration is heavily dependent on what I/O emulation is in use. " .desc = "Delays turntable by number of milliseconds. "
"Delay will be *at most* the specified period; maximum error is dependent on the game's poll rate. "
"As usual, changing any option requires a restart. Default: 0 (no delay).", "As usual, changing any option requires a restart. Default: 0 (no delay).",
.type = OptionType::Integer, .type = OptionType::Integer,
.setting_name = "(0-500)",
.game_name = "Beatmania IIDX", .game_name = "Beatmania IIDX",
.category = "Game Options (Advanced)", .category = "Game Options (Advanced)",
}, },