From c4193eddc59d9f01bef5afa25f5581e05e6633e1 Mon Sep 17 00:00:00 2001 From: bicarus <202771338+bicarus-dev@users.noreply.github.com> Date: Sun, 3 May 2026 01:23:45 -0700 Subject: [PATCH] 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. --- src/spice2x/games/iidx/iidx.cpp | 28 ++++++++++++++++++++++------ src/spice2x/launcher/options.cpp | 12 ++++++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/spice2x/games/iidx/iidx.cpp b/src/spice2x/games/iidx/iidx.cpp index a64179d..f7449dd 100644 --- a/src/spice2x/games/iidx/iidx.cpp +++ b/src/spice2x/games/iidx/iidx.cpp @@ -789,17 +789,33 @@ namespace games::iidx { if ((player == 0 && TT_DELAY_P1 > 0) || (player == 1 && TT_DELAY_P2 > 0)) { - static std::queue delay_queue[2]; + static std::queue> delay_queue[2]; auto &queue = delay_queue[player]; - const auto max_size = - static_cast((player == 0) ? TT_DELAY_P1 : TT_DELAY_P2) + 1; + const auto max_delta_ms = + static_cast((player == 0) ? TT_DELAY_P1 : TT_DELAY_P2); - queue.push(result); - while (queue.size() > max_size) { + // always push a new value + 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(); } - 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; diff --git a/src/spice2x/launcher/options.cpp b/src/spice2x/launcher/options.cpp index 5d96f19..aeb7a0a 100644 --- a/src/spice2x/launcher/options.cpp +++ b/src/spice2x/launcher/options.cpp @@ -657,21 +657,25 @@ static const std::vector OPTION_DEFINITIONS = { }, { // IIDXTTDelayP1 - .title = "IIDX TT Delay Window (Player 1)", + .title = "IIDX TT Delay ms (Player 1)", .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).", .type = OptionType::Integer, + .setting_name = "(0-500)", .game_name = "Beatmania IIDX", .category = "Game Options (Advanced)", }, { // IIDXTTDelayP2 - .title = "IIDX TT Delay Window (Player 2)", + .title = "IIDX TT Delay ms (Player 2)", .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).", .type = OptionType::Integer, + .setting_name = "(0-500)", .game_name = "Beatmania IIDX", .category = "Game Options (Advanced)", },