private async void DoMemoryReadout() { while (running) { await Task.Delay(100); RSMemoryReadout newReadout = null; try { //Read data from memory newReadout = memReader.DoReadout(); } catch (Exception e) { if (running) { Logger.LogError("Error while reading memory: {0} {1}\r\n{2}", e.GetType(), e.Message, e.StackTrace); } } if (newReadout == null) { continue; } if (newReadout.songID != currentMemoryReadout.songID || (currentCDLCDetails == null || !currentCDLCDetails.IsValid())) { var newDetails = cache.Get(newReadout.songID); if (newDetails != null && newDetails.IsValid()) { currentCDLCDetails = cache.Get(newReadout.songID); OnSongChanged?.Invoke(this, new OnSongChangedArgs { songDetails = currentCDLCDetails }); currentCDLCDetails.Print(); } } newReadout.CopyTo(ref currentMemoryReadout); OnMemoryReadout?.Invoke(this, new OnMemoryReadoutArgs() { memoryReadout = currentMemoryReadout }); //Print memreadout if debug is enabled currentMemoryReadout.Print(); } }
/// <summary> /// Update the state of the sniffer /// </summary> private void UpdateState() { //Super complex state machine of state transitions switch (currentState) { case SnifferState.IN_MENUS: if (currentMemoryReadout.songTimer != 0) { currentState = SnifferState.SONG_SELECTED; } break; case SnifferState.SONG_SELECTED: if (currentMemoryReadout.songTimer == 0) { currentState = SnifferState.SONG_STARTING; } //If we somehow missed some states, skip to SONG_PLAYING //Or if the user reset if (currentMemoryReadout.songTimer > 1) { currentState = SnifferState.SONG_PLAYING; } break; case SnifferState.SONG_STARTING: if (currentMemoryReadout.songTimer > 0) { currentState = SnifferState.SONG_PLAYING; } break; case SnifferState.SONG_PLAYING: //Allow 5 seconds of error margin on song ending if (currentMemoryReadout.songTimer >= currentCDLCDetails.songLength - 5) { currentState = SnifferState.SONG_ENDING; } //If the timer goes to 0, the user must have quit if (currentMemoryReadout.songTimer == 0) { currentState = SnifferState.IN_MENUS; } break; case SnifferState.SONG_ENDING: if (currentMemoryReadout.songTimer == 0) { currentState = SnifferState.IN_MENUS; } break; default: break; } //Force state to IN_MENUS if the current song details are not valid if (!currentCDLCDetails.IsValid()) { currentState = SnifferState.IN_MENUS; } //If state changed if (currentState != previousState) { //Invoke event OnStateChanged?.Invoke(this, new OnStateChangedArgs() { oldState = previousState, newState = currentState }); //Remember previous state previousState = currentState; if (Logger.logStateMachine) { Logger.Log("Current state: {0}", currentState.ToString()); } } }