Issues #39 + #40: gate input until the scene presents; cap the wait-screen idle loop

#39 (field: 'I was able to input before the game screen actually came
up -- fired weapons, moving, could hear the audio'): the simulation
runs during load/wait and PadRIO fed it live input.  Poll now emits
only the analog heartbeat until gBTSceneHasPresented -- keyboard, pad
and joystick all stand down; edge state stays parked so keys held
across the boundary press cleanly at first frame.  BT_BTNTEST and the
panel-click seam stay live (event injection, same as before).

#40 (field: 'GPU usage during waiting screen is sometimes consuming up
to 45-50%'): ExecuteIdle Cleared+Presented uncapped for the whole join
wait.  Now capped at ~40 Hz with a 5 ms sleep on skipped passes (the
overlay's change gate is 12.5 Hz -- nothing visible changes faster).

Regression: 2-node relay round through the wait screen -> load ->
mission (135 in-mission ticks, autofire) -> clean.  Awaiting the
reporter's live confirm on both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-24 09:57:06 -05:00
co-authored by Claude Opus 4.8
parent 85ac54fcee
commit b2b7a45b5c
2 changed files with 38 additions and 0 deletions
+22
View File
@@ -403,6 +403,28 @@ void
}
lastPollMilliseconds = now;
//
// Issue #39 (field 2026-07-23): the simulation runs during load/wait,
// so a player could fire, walk and hear it all BEFORE the first frame
// presented ("I was able to input before the game screen came up").
// Until the scene is live, emit only the analog heartbeat -- keyboard,
// pad and joystick reads all stand down (edge state stays parked, so
// keys held across the boundary press cleanly at first frame). The
// scripted BT_BTNTEST harness above stays live (it injects through the
// event seam, same as the on-screen panel clicks).
//
{
extern Logical gBTSceneHasPresented;
if (!gBTSceneHasPresented)
{
RIOEvent analog;
analog.Type = AnalogEvent;
analog.Data.Unit = 0;
PushEvent(analog);
return;
}
}
//
//-----------------------------------------------------------------
// XInput: hot-plug probe every ~3 s, then read the connected pad.
+16
View File
@@ -8917,6 +8917,22 @@ void DPLRenderer::ExecuteIdle()
if (gBTSceneHasPresented)
return; // game graphics own the screen now
// Issue #40 (wait screen burned 45-50% GPU, field 2026-07-23): the idle
// loop Cleared+Presented at an UNCAPPED rate for the whole join wait.
// Cap it at ~40 Hz -- the overlay's own change gate runs at 12.5 Hz, so
// nothing visible changes faster than that anyway. The 5 ms sleep also
// keeps the caller's spin off a CPU core.
{
static unsigned long s_lastIdlePresent = 0;
unsigned long now = GetTickCount();
if (now - s_lastIdlePresent < 25UL)
{
Sleep(5);
return;
}
s_lastIdlePresent = now;
}
{
static unsigned long s_lastIdleLog = 0;
unsigned long now = GetTickCount();