private VideoWriterChooserForm(IMainFormForTools mainForm, IEmulator emulator, Config config) { DialogController = mainForm; InitializeComponent(); // TODO: do we want to use virtual w/h? if (emulator.HasVideoProvider()) { var videoProvider = emulator.AsVideoProvider(); _captureWidth = videoProvider.BufferWidth; _captureHeight = videoProvider.BufferHeight; } if (config.AviCaptureOsd) { using var bb = mainForm.CaptureOSD(); _captureWidth = bb.Width; _captureHeight = bb.Height; } lblSize.Text = $"Size:\r\n{_captureWidth}x{_captureHeight}"; if (_captureWidth % 4 != 0 || _captureHeight % 4 != 0) { lblResolutionWarning.Visible = true; } else { lblResolutionWarning.Visible = false; } }
public static int VsyncDenominator(this IEmulator core) { if (core != null && core.HasVideoProvider()) { return(core.AsVideoProvider().VsyncDenominator); } return(1); }
public SavestateFile(IEmulator emulator, IMovieSession movieSession, IDictionary <string, object> userBag) { if (!emulator.HasSavestates()) { throw new InvalidOperationException("The provided core must have savestates"); } _emulator = emulator; _statable = emulator.AsStatable(); if (emulator.HasVideoProvider()) { _videoProvider = emulator.AsVideoProvider(); } _movieSession = movieSession; _userBag = userBag; }
/// <summary> /// If the given movie contains a savestate it will be loaded if /// the given core has savestates, and a framebuffer populated /// if it is contained in the state and the given core supports it /// </summary> public static void ProcessSavestate(this IMovie movie, IEmulator emulator) { if (emulator.HasSavestates() && movie.StartsFromSavestate) { if (movie.TextSavestate != null) { emulator.AsStatable().LoadStateText(movie.TextSavestate); } else { emulator.AsStatable().LoadStateBinary(movie.BinarySavestate); } if (movie.SavestateFramebuffer != null && emulator.HasVideoProvider()) { emulator.AsVideoProvider().PopulateFromBuffer(movie.SavestateFramebuffer); } emulator.ResetCounters(); } }
private void Ok_Click(object sender, EventArgs e) { var path = MakePath(); if (!string.IsNullOrWhiteSpace(path)) { var test = new FileInfo(path); if (test.Exists) { var result = MessageBox.Show(path + " already exists, overwrite?", "Confirm overwrite", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (result == DialogResult.Cancel) { return; } } var movieToRecord = MovieService.Get(path); var fileInfo = new FileInfo(path); if (!fileInfo.Exists) { Directory.CreateDirectory(fileInfo.DirectoryName); } if (StartFromCombo.SelectedItem.ToString() == "Now" && Emulator.HasSavestates()) { var core = Emulator.AsStatable(); movieToRecord.StartsFromSavestate = true; movieToRecord.StartsFromSaveRam = false; if (core.BinarySaveStatesPreferred) { movieToRecord.BinarySavestate = (byte[])core.SaveStateBinary().Clone(); } else { using (var sw = new StringWriter()) { core.SaveStateText(sw); movieToRecord.TextSavestate = sw.ToString(); } } // TODO: do we want to support optionally not saving this? if (true) { // hack: some IMovies eat the framebuffer, so don't bother with them movieToRecord.SavestateFramebuffer = new int[0]; if (movieToRecord.SavestateFramebuffer != null && Emulator.HasVideoProvider()) { movieToRecord.SavestateFramebuffer = (int[])Emulator.AsVideoProvider().GetVideoBuffer().Clone(); } } } else if (StartFromCombo.SelectedItem.ToString() == "SaveRam" && Emulator.HasSaveRam()) { var core = Emulator.AsSaveRam(); movieToRecord.StartsFromSavestate = false; movieToRecord.StartsFromSaveRam = true; movieToRecord.SaveRam = core.CloneSaveRam(); } movieToRecord.PopulateWithDefaultHeaderValues(AuthorBox.Text); movieToRecord.Save(); GlobalWin.MainForm.StartNewMovie(movieToRecord, true); Global.Config.UseDefaultAuthor = DefaultAuthorCheckBox.Checked; if (DefaultAuthorCheckBox.Checked) { Global.Config.DefaultAuthor = AuthorBox.Text; } Close(); } else { MessageBox.Show("Please select a movie to record", "File selection error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void Ok_Click(object sender, EventArgs e) { var path = MakePath(); if (!string.IsNullOrWhiteSpace(path)) { var test = new FileInfo(path); if (test.Exists) { var result = DialogController.ShowMessageBox2($"{path} already exists, overwrite?", "Confirm overwrite", EMsgBoxIcon.Warning, useOKCancel: true); if (!result) { return; } } var movieToRecord = _movieSession.Get(path); var fileInfo = new FileInfo(path); if (!fileInfo.Exists) { Directory.CreateDirectory(fileInfo.DirectoryName); } if (StartFromCombo.SelectedItem.ToString() == "Now" && _emulator.HasSavestates()) { var core = _emulator.AsStatable(); movieToRecord.StartsFromSavestate = true; if (_config.Savestates.Type == SaveStateType.Binary) { movieToRecord.BinarySavestate = core.CloneSavestate(); } else { using var sw = new StringWriter(); core.SaveStateText(sw); movieToRecord.TextSavestate = sw.ToString(); } // TODO: do we want to support optionally not saving this? movieToRecord.SavestateFramebuffer = Array.Empty <int>(); if (_emulator.HasVideoProvider()) { movieToRecord.SavestateFramebuffer = (int[])_emulator.AsVideoProvider().GetVideoBuffer().Clone(); } } else if (StartFromCombo.SelectedItem.ToString() == "SaveRam" && _emulator.HasSaveRam()) { var core = _emulator.AsSaveRam(); movieToRecord.StartsFromSaveRam = true; movieToRecord.SaveRam = core.CloneSaveRam(); } movieToRecord.PopulateWithDefaultHeaderValues( _emulator, _game, _firmwareManager, AuthorBox.Text ?? _config.DefaultAuthor); movieToRecord.Save(); _mainForm.StartNewMovie(movieToRecord, true); _config.UseDefaultAuthor = DefaultAuthorCheckBox.Checked; if (DefaultAuthorCheckBox.Checked) { _config.DefaultAuthor = AuthorBox.Text; } Close(); } else { DialogController.ShowMessageBox("Please select a movie to record", "File selection error", EMsgBoxIcon.Error); } }
public static void SaveStateFile(IEmulator emulator, string filename) { var core = emulator.AsStatable(); // the old method of text savestate save is now gone. // a text savestate is just like a binary savestate, but with a different core lump using var bs = new BinaryStateSaver(filename); if (Global.Config.SaveStateType == SaveStateTypeE.Text) { // text savestate format using (new SimpleTime("Save Core")) { bs.PutLump(BinaryStateLump.CorestateText, tw => core.SaveStateText(tw)); } } else { // binary core lump format using (new SimpleTime("Save Core")) { bs.PutLump(BinaryStateLump.Corestate, bw => core.SaveStateBinary(bw)); } } if (Global.Config.SaveScreenshotWithStates && emulator.HasVideoProvider()) { var vp = emulator.AsVideoProvider(); var buff = vp.GetVideoBuffer(); if (buff.Length == 1) { // is a hacky opengl texture ID. can't handle this now! // need to discuss options // 1. cores must be able to provide a pixels VideoProvider in addition to a texture ID, on command (not very hard overall but interface changing and work per core) // 2. SavestateManager must be setup with a mechanism for resolving texture IDs (even less work, but sloppy) // There are additional problems with AVWriting. They depend on VideoProvider providing pixels. } else { int outWidth = vp.BufferWidth; int outHeight = vp.BufferHeight; // if buffer is too big, scale down screenshot if (!Global.Config.NoLowResLargeScreenshotWithStates && buff.Length >= Global.Config.BigScreenshotSize) { outWidth /= 2; outHeight /= 2; } using (new SimpleTime("Save Framebuffer")) { bs.PutLump(BinaryStateLump.Framebuffer, s => QuickBmpFile.Save(emulator.AsVideoProvider(), s, outWidth, outHeight)); } } } if (Global.MovieSession.Movie.IsActive()) { bs.PutLump(BinaryStateLump.Input, delegate(TextWriter tw) { // this never should have been a core's responsibility tw.WriteLine("Frame {0}", emulator.Frame); Global.MovieSession.HandleSaveState(tw); }); } if (Global.UserBag.Any()) { bs.PutLump(BinaryStateLump.UserData, delegate(TextWriter tw) { var data = ConfigService.SaveWithType(Global.UserBag); tw.WriteLine(data); }); } if (Global.MovieSession.Movie.IsActive() && Global.MovieSession.Movie is TasMovie) { bs.PutLump(BinaryStateLump.LagLog, delegate(TextWriter tw) { ((TasMovie)Global.MovieSession.Movie).LagLog.Save(tw); }); } }
public static bool LoadStateFile(IEmulator emulator, string path) { var core = emulator.AsStatable(); // try to detect binary first var bl = BinaryStateLoader.LoadAndDetect(path); if (bl != null) { try { var succeed = false; // Movie timeline check must happen before the core state is loaded if (Global.MovieSession.Movie.IsActive()) { bl.GetLump(BinaryStateLump.Input, true, tr => succeed = Global.MovieSession.CheckSavestateTimeline(tr)); if (!succeed) { return(false); } } using (new SimpleTime("Load Core")) { bl.GetCoreState(br => core.LoadStateBinary(br), tr => core.LoadStateText(tr)); } // We must handle movie input AFTER the core is loaded to properly handle mode changes, and input latching if (Global.MovieSession.Movie.IsActive()) { bl.GetLump(BinaryStateLump.Input, true, tr => succeed = Global.MovieSession.HandleLoadState(tr)); if (!succeed) { return(false); } } if (emulator.HasVideoProvider()) { bl.GetLump(BinaryStateLump.Framebuffer, false, br => PopulateFramebuffer(br, emulator.AsVideoProvider())); } string userData = ""; bl.GetLump(BinaryStateLump.UserData, false, delegate(TextReader tr) { string line; while ((line = tr.ReadLine()) != null) { if (!string.IsNullOrWhiteSpace(line)) { userData = line; } } }); if (!string.IsNullOrWhiteSpace(userData)) { Global.UserBag = (Dictionary <string, object>)ConfigService.LoadWithType(userData); } if (Global.MovieSession.Movie.IsActive() && Global.MovieSession.Movie is ITasMovie) { bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr) { ((ITasMovie)Global.MovieSession.Movie).LagLog.Load(tr); }); } } finally { bl.Dispose(); } return(true); } return(false); }