Repository navigation
v0.6.7
v0.6.7 - flag-driven pause detection, state machine reliability, readable JSON enums
Pause and resume are detected on the first poll across all song modes and Guitarcade minigames. New
pauseMenuMode/isPausedfields expose Rocksmith's overlay state to addons. The state machine no longer gets stuck on RockSniffer attach, Rocksmith restart, or song-load backout. JSON output now showscurrentStateandmodeas readable strings.
Highlights
- Pause detection is now first-poll instant across all three song modes and Guitarcade minigames. The state machine no longer waits for consecutive timer-stalled polls before flipping to
SONG_PAUSED, dropping detection latency from roughly 100–300 ms to a single poll. - Resume detection is also first-poll instant, with the tuner-from-pause sub-flow handled cleanly. Entering the tuner from the pause menu no longer triggers a spurious "resume" event, and exiting a song from the pause menu no longer briefly flickers through
SONG_PLAYINGbefore reachingIN_MENUS. - Pause is now correctly detected near the end of a song. The previous heuristic had to suppress pause detection in the final 2 seconds to avoid false positives from end-of-song timer stalls. That guard is gone; false positives are no longer possible.
- Pause is now correctly detected in Guitarcade minigames. The previous timer-stall heuristic was scoped to song-timer behavior; Guitarcade games don't have a song timer in the conventional sense, so pause was effectively invisible.
- The state machine no longer gets stuck in
SONG_STARTING. Three scenarios that previously left the state machine parked inSONG_STARTINGindefinitely now recover cleanly: RockSniffer attaching to an already-running Rocksmith, Rocksmith restarting while RockSniffer is running, and the user pressing Esc on a song's loading screen before gameplay begins. - JSON output is now human-readable:
currentStateandmodeserialize as enum names (e.g."SONG_PAUSED","SCOREATTACK") instead of underlying integers. Affects the debug overlay and any addon consuming the JSON readout. - New addon-accessible fields:
pauseMenuMode(raw byte, 0/1/2) andisPaused(derived bool) on the memory readout, both auto-serialized into the addon JSON.
What changed in pause detection
SnifferState's SONG_PLAYING ↔ SONG_PAUSED transitions now read Rocksmith's pause-menu mode byte directly from a .data-section static at Rocksmith2014.exe+0xF5F5FC (Remastered). The variable encodes blocking-overlay state:
| Value | Meaning | Where observed |
|---|---|---|
0 |
No blocking overlay | Active gameplay, menus, loading, song review |
1 |
Sub-overlay active | Tuner accessed from the pause menu; Tools-menu sub-options |
2 |
Top-level blocking overlay | Pause menu, Mixer, Tools menu (from main menu), restart-confirmation prompts |
The state machine treats any non-zero value as "user is in a pause sub-flow." This handles the tuner-from-pause edge case without any special-case logic: the engine transitions cleanly between 2 → 1 → 2 when entering and exiting the tuner, never dropping to 0, so SnifferState.SONG_PAUSED is preserved correctly throughout.
Pause-exit (user hits Exit from the pause menu) is also handled cleanly: a pauseTimerSnapshot captured at pause-entry is compared against the current songTimer in the resume condition, so the moment Exit clears pauseMenuMode doesn't briefly flip the state to SONG_PLAYING while songTimer is still frozen at the pause-point.
Cross-mode validated for Score Attack, Learn-A-Song, Nonstop Play, and Guitarcade minigames. Verified to survive game relaunch as a true static (no warmup gate, no per-session memory shifting).
State-machine reliability improvements
Two additional guards prevent the currentState field from getting stuck in unexpected states:
-
IN_MENUS → SONG_SELECTEDis gated ongameStage. The transition previously fired onsongTimer != 0alone, which let transient memory garbage at process startup or Rocksmith restart march the state machine forward throughSONG_SELECTEDand intoSONG_STARTINGwithout the user actually being in a song. The new gate requiresgameStageto be one oflas_game,sa_game,nonstopplaygame,las_pause,sa_pause, ornsp_pausebefore the transition can fire. -
SONG_STARTINGhas an escape hatch back toIN_MENUS. If the user backs out of a song's loading screen beforesongTimerever advances, the state machine previously had no exit and would park inSONG_STARTINGindefinitely. The new escape branch fires whengameStagetransitions to a known menu/tuner/songreview state (mainmenu,gcpre,learnasong,scoreattack,nonstopplay,nsp_main,las_songs,las_options,las_tuner,nsp_tuner,las_songreview,sa_songreview,panel_bib,shop, orgcade), unwinding cleanly back toIN_MENUS.
Both guards deliberately exclude *_pause gameStages, which are sticky after the first pause during any song and would otherwise produce false signals.
Readable JSON enums
Two enum fields exposed to addons now serialize as their string names rather than underlying integers:
| Field | Before v0.6.7 | After v0.6.7 |
|---|---|---|
currentState (top-level) |
"currentState": 6 |
"currentState": "SONG_PAUSED" |
memoryReadout.mode |
"mode": 2 |
"mode": "SCOREATTACK" |
This makes the debug overlay output legible at a glance and removes the need for addons to hardcode integer-to-name mappings.
Breaking-change note: any third-party addon that compared currentState or mode to integer literals (e.g. if (data.currentState === 6)) will break. None of the bundled addons in this repository do this. Affected third-party addons need a one-line fix to compare against string names instead.
Why both pause signals coexist on the readout
pauseMenuMode reflects Rocksmith's engine state directly; including the fact that the main menu's Tools overlay (accessible via SPACE while not in a song) also reads as 2, even though it has nothing to do with mid-song pause. Addons that want to filter for "user is paused during an active song specifically" should combine pauseMenuMode != 0 with a SnifferState check (e.g. currentState is SONG_PLAYING or SONG_PAUSED).
isPaused is the raw pauseMenuMode != 0 test exposed as a convenience boolean. For addons that don't care about the Tools-menu distinction, it's a one-bit answer.
Both fields propagate every poll regardless of songTimer, so addons consuming prevReadout see fresh pause state during transitional windows (loading screens, song boundaries).
Internal cleanup
The timer-stall heuristic that previously drove pause detection has been retired entirely:
STALL_THRESHOLD,STALL_EPSILON, andEND_OF_SONG_PAUSE_GUARDconstants removedstallCountfield removed- Per-poll stall-tracking arithmetic in the playing loop removed
- Six
stallCount = 0;reset statements across the file removed lastObservedTimerfield retained for diagnostic logging only
The pause-entry / pause-exit logic in Sniffer.UpdateState() is now flag-driven with explicit timer-snapshot disambiguation, replacing the old multi-poll stall accumulator.
Compatibility
- Verified on: Rocksmith 2014 Remastered. Cross-mode tested: Score Attack, Learn-A-Song, Nonstop Play, Guitarcade minigames. Process-relaunch tested.
- Beta and Learn-And-Play builds: memory offset back-derived using the standard
+0x3080/+0x4080shift convention (now consistent across twelve mapped addresses). Untested on those builds. If pause detection misbehaves on Beta or LaP (no pause ever registered, or constant pause), the new offset is the most likely suspect. - Existing addons: consumers of
SnifferState.SONG_PAUSEDvia the event API continue working unchanged; they get faster pause transitions automatically. Consumers reading enum values from JSON as strings work correctly. Consumers reading enum values from JSON as integers need a one-line fix.
Discovery credit
The pause-menu mode byte was discovered using Cheat Engine memory inspection in the neighborhood of two named candidate addresses provided by kokolihapihvi (upstream RockSniffer maintainer): MustBlockInputsDueToPauseMenu and EnablePauseMenu. Both turned out to be dead in the current Remastered build (consistently zero across all states), but the neighborhood inspection they prompted led directly to this find. Thanks Koko.