Skip to content

v0.6.7

Choose a tag to compare

@github-actions github-actions released this 12 May 17:43

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 / isPaused fields 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 shows currentState and mode as 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_PLAYING before reaching IN_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 in SONG_STARTING indefinitely 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: currentState and mode serialize 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) and isPaused (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:

  1. IN_MENUS → SONG_SELECTED is gated on gameStage. The transition previously fired on songTimer != 0 alone, which let transient memory garbage at process startup or Rocksmith restart march the state machine forward through SONG_SELECTED and into SONG_STARTING without the user actually being in a song. The new gate requires gameStage to be one of las_game, sa_game, nonstopplaygame, las_pause, sa_pause, or nsp_pause before the transition can fire.

  2. SONG_STARTING has an escape hatch back to IN_MENUS. If the user backs out of a song's loading screen before songTimer ever advances, the state machine previously had no exit and would park in SONG_STARTING indefinitely. The new escape branch fires when gameStage transitions 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, or gcade), unwinding cleanly back to IN_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, and END_OF_SONG_PAUSE_GUARD constants removed
  • stallCount field removed
  • Per-poll stall-tracking arithmetic in the playing loop removed
  • Six stallCount = 0; reset statements across the file removed
  • lastObservedTimer field 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 / +0x4080 shift 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_PAUSED via 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.