/// <summary> /// Display all screen info objects like fps, frame counter, lag counter, and input display /// </summary> public void DrawScreenInfo(IBlitter g) { if (_config.DisplayFrameCounter && !_emulator.IsNull()) { string message = MakeFrameCounter(); var point = GetCoordinates(g, _config.FrameCounter, message); DrawOsdMessage(g, message, Color.FromArgb(_config.MessagesColor), point.X, point.Y); if (_emulator.CanPollInput() && _emulator.AsInputPollable().IsLagFrame) { DrawOsdMessage(g, _emulator.Frame.ToString(), FixedAlertMessageColor, point.X, point.Y); } } if (_config.DisplayInput) { var moviePlaying = _movieSession.Movie.IsPlaying(); // After the last frame of the movie, we want both the last movie input and the current inputs. var atMovieEnd = _movieSession.Movie.IsFinished() && _movieSession.Movie.IsAtEnd(); if (moviePlaying || atMovieEnd) { var input = InputStrMovie(); var point = GetCoordinates(g, _config.InputDisplay, input); Color c = Color.FromArgb(_config.MovieInput); g.DrawString(input, MessageFont, c, point.X, point.Y); } if (!moviePlaying) // TODO: message config -- allow setting of "mixed", and "auto" { var previousColor = Color.FromArgb(_config.LastInputColor); Color immediateColor = Color.FromArgb(_config.MessagesColor); var autoColor = Color.Pink; var changedColor = Color.PeachPuff; //we need some kind of string for calculating position when right-anchoring, of something like that var bgStr = InputStrOrAll(); var point = GetCoordinates(g, _config.InputDisplay, bgStr); // now, we're going to render these repeatedly, with higher-priority things overriding // first display previous frame's input. // note: that's only available in case we're working on a movie var previousStr = InputPrevious(); g.DrawString(previousStr, MessageFont, previousColor, point.X, point.Y); // next, draw the immediate input. // that is, whatever is being held down interactively right this moment even if the game is paused // this includes things held down due to autohold or autofire // I know, this is all really confusing var immediate = InputStrImmediate(); g.DrawString(immediate, MessageFont, immediateColor, point.X, point.Y); // next draw anything that's pressed because it's sticky. // this applies to autofire and autohold both. somehow. I don't understand it. // basically we're tinting whatever is pressed because it's sticky specially // in order to achieve this we want to avoid drawing anything pink that isn't actually held down right now // so we make an AND adapter and combine it using immediate & sticky var autoString = MakeStringFor(_inputManager.StickyXorAdapter.Source.Xor(_inputManager.AutofireStickyXorAdapter).And(_inputManager.AutofireStickyXorAdapter)); g.DrawString(autoString, MessageFont, autoColor, point.X, point.Y); //recolor everything that's changed from the previous input var immediateOverlay = MakeIntersectImmediatePrevious(); g.DrawString(immediateOverlay, MessageFont, changedColor, point.X, point.Y); } } if (_config.DisplayFps && Fps != null) { var point = GetCoordinates(g, _config.Fps, Fps); DrawOsdMessage(g, Fps, FixedMessagesColor, point.X, point.Y); } if (_config.DisplayLagCounter && _emulator.CanPollInput()) { var counter = _emulator.AsInputPollable().LagCount.ToString(); var point = GetCoordinates(g, _config.LagCounter, counter); DrawOsdMessage(g, counter, FixedAlertMessageColor, point.X, point.Y); } if (_config.DisplayRerecordCount) { string rerecordCount = MakeRerecordCount(); var point = GetCoordinates(g, _config.ReRecordCounter, rerecordCount); DrawOsdMessage(g, rerecordCount, FixedMessagesColor, point.X, point.Y); } if (_inputManager.ClientControls["Autohold"] || _inputManager.ClientControls["Autofire"]) { var sb = new StringBuilder("Held: "); foreach (string sticky in _inputManager.StickyXorAdapter.CurrentStickies) { sb.Append(sticky).Append(' '); } foreach (string autoSticky in _inputManager.AutofireStickyXorAdapter.CurrentStickies) { sb .Append("Auto-") .Append(autoSticky) .Append(' '); } var message = sb.ToString(); var point = GetCoordinates(g, _config.Autohold, message); g.DrawString(message, MessageFont, Color.White, point.X, point.Y); } if (_movieSession.Movie.IsActive() && _config.DisplaySubtitles) { var subList = _movieSession.Movie.Subtitles.GetSubtitles(_emulator.Frame); foreach (var sub in subList) { DrawOsdMessage(g, sub.Message, Color.FromArgb((int)sub.Color), sub.X, sub.Y); } } }