Esempio n. 1
0
        private void TasView_QueryItemText(int index, int column, out string text)
        {
            try
            {
                text = string.Empty;
                var columnName = TasView.Columns[column].Name;

                if (columnName == MarkerColumnName)
                {
                    text = Global.Emulator.Frame == index ? ">" : string.Empty;
                }
                else if (columnName == FrameColumnName)
                {
                    text = (index).ToString().PadLeft(5, '0');
                }
                else
                {
                    if (index < _tas.InputLogLength)
                    {
                        text = _tas.DisplayValue(index, columnName);
                    }
                    else if (Global.Emulator.Frame == _tas.InputLogLength)                     // In this situation we have a "pending" frame for the user to click
                    {
                        text = TasMovie.CreateDisplayValueForButton(
                            Global.ClickyVirtualPadController,
                            columnName);
                    }
                }
            }
            catch (Exception ex)
            {
                text = string.Empty;
                MessageBox.Show("oops\n" + ex);
            }
        }
        public static TasMovie ToTasMovie(this IMovie old, bool copy = false)
        {
            string newFilename = old.Filename + "." + TasMovie.Extension;

            if (File.Exists(newFilename))
            {
                int  fileNum      = 1;
                bool fileConflict = true;
                while (fileConflict)
                {
                    if (File.Exists(newFilename))
                    {
                        newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
                        fileNum++;
                    }
                    else
                    {
                        fileConflict = false;
                    }
                }
            }

            var tas = new TasMovie(newFilename, old.StartsFromSavestate);

            for (var i = 0; i < old.InputLogLength; i++)
            {
                var input = old.GetInputState(i);
                tas.AppendFrame(input);
            }

            if (!copy)
            {
                old.Truncate(0);                 // Trying to minimize ram usage
            }

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.SyncSettingsJson = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (var comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (var sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            tas.TextSavestate   = old.TextSavestate;
            tas.BinarySavestate = old.BinarySavestate;

            return(tas);
        }
        public static TasMovie ConvertToSaveRamAnchoredMovie(this TasMovie old, byte[] saveRam)
        {
            string newFilename = old.Filename + "." + TasMovie.Extension;

            if (File.Exists(newFilename))
            {
                int  fileNum      = 1;
                bool fileConflict = true;
                while (fileConflict)
                {
                    if (File.Exists(newFilename))
                    {
                        newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
                        fileNum++;
                    }
                    else
                    {
                        fileConflict = false;
                    }
                }
            }

            TasMovie tas = new TasMovie(newFilename, true);

            tas.SaveRam = saveRam;
            tas.TasStateManager.Clear();
            tas.ClearLagLog();

            var entries = old.GetLogEntries();

            tas.CopyVerificationLog(old.VerificationLog);
            tas.CopyVerificationLog(entries);

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.StartsFromSaveRam   = true;
            tas.StartsFromSavestate = false;
            tas.SyncSettingsJson    = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (string comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (Subtitle sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            tas.TasStateManager.Settings = old.TasStateManager.Settings;

            tas.Save();
            return(tas);
        }
Esempio n. 4
0
        private bool HandleMovieLoadStuff(TasMovie movie = null)
        {
            bool result;

            WantsToControlStopMovie = false;

            if (movie == null)
            {
                movie  = CurrentTasMovie;
                result = StartNewMovieWrapper(movie.InputLogLength == 0, movie);
            }
            else
            {
                result = StartNewMovieWrapper(false, movie);
            }

            if (!result)
            {
                return(false);
            }

            WantsToControlStopMovie = true;

            CurrentTasMovie.ChangeLog.ClearLog();
            CurrentTasMovie.ClearChanges();

            SetTextProperty();
            MessageStatusLabel.Text = $"{Path.GetFileName(CurrentTasMovie.Filename)} loaded.";

            return(true);
        }
		public static TasMovie ToTasMovie(this IMovie old)
		{
			var newFilename = old.Filename + "." +  TasMovie.Extension;
			var tas = new TasMovie(newFilename);
			tas.HeaderEntries.Clear();
			foreach (var kvp in old.HeaderEntries)
			{
				tas.HeaderEntries[kvp.Key] = kvp.Value;
			}

			tas.SyncSettingsJson = old.SyncSettingsJson;

			tas.Comments.Clear();
			foreach (var comment in old.Comments)
			{
				tas.Comments.Add(comment);
			}

			tas.Subtitles.Clear();
			foreach (var sub in old.Subtitles)
			{
				tas.Subtitles.Add(sub);
			}

			tas.TextSavestate = old.TextSavestate;
			tas.BinarySavestate = old.BinarySavestate;

			for (var i = 0; i < old.InputLogLength; i++)
			{
				var input = old.GetInputState(i);
				tas.AppendFrame(input);
			}

			return tas;
		}
        public static TasMovie ConvertToSaveRamAnchoredMovie(this TasMovie old, byte[] saveRam)
        {
            string newFilename = old.Filename + "." + TasMovie.Extension;

            if (File.Exists(newFilename))
            {
                int fileNum = 1;
                bool fileConflict = true;
                while (fileConflict)
                {
                    if (File.Exists(newFilename))
                    {
                        newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
                        fileNum++;
                    }
                    else
                    {
                        fileConflict = false;
                    }
                }
            }

            TasMovie tas = new TasMovie(newFilename, true);
            tas.SaveRam = saveRam;
            tas.TasStateManager.Clear();
            tas.ClearLagLog();

            List<string> entries = old.GetLogEntries();

            tas.CopyVerificationLog(old.VerificationLog);
            tas.CopyVerificationLog(entries);

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.StartsFromSaveRam = true;
            tas.StartsFromSavestate = false;
            tas.SyncSettingsJson = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (string comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (Subtitle sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            tas.TasStateManager.Settings = old.TasStateManager.Settings;

            tas.Save();
            return tas;
        }
Esempio n. 7
0
        private bool LoadFile(FileInfo file, bool startsFromSavestate = false, int gotoFrame = 0)
        {
            if (!file.Exists)
            {
                Settings.RecentTas.HandleLoadError(file.FullName);
                return(false);
            }

            TasMovie newMovie = new TasMovie(startsFromSavestate: startsFromSavestate);

            newMovie.TasStateManager.InvalidateCallback = GreenzoneInvalidated;
            newMovie.Filename           = file.FullName;
            newMovie.BindMarkersToInput = Settings.BindMarkersToInput;

            BookMarkControl.LoadedCallback  = BranchLoaded;
            BookMarkControl.SavedCallback   = BranchSaved;
            BookMarkControl.RemovedCallback = BranchRemoved;

            if (!HandleMovieLoadStuff(newMovie))
            {
                return(false);
            }

            Settings.RecentTas.Add(newMovie.Filename);             // only add if it did load

            if (startsFromSavestate)
            {
                GoToFrame(0);
            }
            else if (gotoFrame > 0)
            {
                GoToFrame(gotoFrame);
            }
            else
            {
                GoToFrame(CurrentTasMovie.Session.CurrentFrame);
            }

            // If we are loading an existing non-default movie, we will already have columns generated
            // Only set up columns if needed
            if (!TasView.AllColumns.Any())
            {
                SetUpColumns();
            }

            SetUpToolStripColumns();

            CurrentTasMovie.PropertyChanged += TasMovie_OnPropertyChanged;
            CurrentTasMovie.CurrentBranch    = CurrentTasMovie.Session.CurrentBranch;
            BookMarkControl.UpdateTextColumnWidth();
            MarkerControl.UpdateTextColumnWidth();
            // clear all selections
            TasView.DeselectAll();
            BookMarkControl.Restart();
            MarkerControl.Restart();

            RefreshDialog();
            return(true);
        }
Esempio n. 8
0
		private void NewTasMovie()
		{
			Global.MovieSession.Movie = new TasMovie();
			_tas = Global.MovieSession.Movie as TasMovie;
			_tas.Filename = DefaultTasProjName(); // TODO don't do this, take over any mainform actions that can crash without a filename
			_tas.PopulateWithDefaultHeaderValues();
			_tas.ClearChanges();
		}
Esempio n. 9
0
        private bool LoadFile(FileInfo file, bool startsFromSavestate = false, int gotoFrame = 0)
        {
            if (!file.Exists)
            {
                Settings.RecentTas.HandleLoadError(file.FullName);
                return(false);
            }

            TasMovie newMovie = new TasMovie(startsFromSavestate, _seekBackgroundWorker);

            newMovie.TasStateManager.InvalidateCallback = GreenzoneInvalidated;
            newMovie.Filename = file.FullName;

            BookMarkControl.LoadedCallback  = BranchLoaded;
            BookMarkControl.SavedCallback   = BranchSaved;
            BookMarkControl.RemovedCallback = BranchRemoved;

            if (!HandleMovieLoadStuff(newMovie))
            {
                return(false);
            }

            Settings.RecentTas.Add(newMovie.Filename);             // only add if it did load

            if (startsFromSavestate)
            {
                GoToFrame(0);
            }
            else if (gotoFrame > 0)
            {
                GoToFrame(gotoFrame);
            }
            else
            {
                GoToFrame(CurrentTasMovie.Session.CurrentFrame);
            }

            if (TasView.AllColumns.Count == 0 || file.Extension != $".{TasMovie.Extension}")
            {
                SetUpColumns();
            }
            else
            {
                SetUpToolStripColumns();
            }

            CurrentTasMovie.PropertyChanged += TasMovie_OnPropertyChanged;
            CurrentTasMovie.CurrentBranch    = CurrentTasMovie.Session.CurrentBranch;
            BookMarkControl.UpdateTextColumnWidth();

            // clear all selections
            TasView.DeselectAll();
            BookMarkControl.Restart();
            MarkerControl.Restart();

            RefreshDialog();
            return(true);
        }
Esempio n. 10
0
 private void SetTasMovieCallbacks(TasMovie movie = null)
 {
     if (movie == null)
     {
         movie = CurrentTasMovie;
     }
     movie.ClientSettingsForSave   = ClientSettingsForSave;
     movie.GetClientSettingsOnLoad = GetClientSettingsOnLoad;
 }
Esempio n. 11
0
        private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e)
        {
            if (AskSaveChanges())
            {
                int index = Emulator.Frame;

                TasMovie newProject = CurrentTasMovie.ConvertToSavestateAnchoredMovie(
                    index, (byte[])StatableEmulator.SaveStateBinary().Clone());

                GlobalWin.MainForm.PauseEmulator();
                LoadFile(new FileInfo(newProject.Filename), true);
            }
        }
Esempio n. 12
0
        private bool HandleMovieLoadStuff(TasMovie movie = null)
        {
            bool result;

            WantsToControlStopMovie = false;

            if (movie == null)
            {
                movie  = CurrentTasMovie;
                result = StartNewMovieWrapper(movie.InputLogLength == 0, movie);
            }
            else
            {
                if (movie.Filename.EndsWith(TasMovie.Extension))
                {
                }
                else if (movie.Filename.EndsWith(".bkm") || movie.Filename.EndsWith(".bk2"))                 // was loaded using "All Files" filter. todo: proper extention iteration
                {
                    var result1 = MessageBox.Show("This is a regular movie, a new project must be created from it, in order to use in TAStudio\nProceed?", "Convert movie", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                    if (result1 == DialogResult.OK)
                    {
                        ConvertCurrentMovieToTasproj();
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    MessageBox.Show("This is not a BizHawk movie!", "Movie load error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }
                result = StartNewMovieWrapper(false, movie);
            }

            if (!result)
            {
                return(false);
            }

            WantsToControlStopMovie = true;

            CurrentTasMovie.ChangeLog.ClearLog();
            CurrentTasMovie.ClearChanges();

            SetTextProperty();
            MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " loaded.";

            return(true);
        }
Esempio n. 13
0
        private void StartANewProjectFromSaveRamMenuItem_Click(object sender, EventArgs e)
        {
            if (AskSaveChanges())
            {
                int index = TasView.SelectedRows.First();
                GoToFrame(index);

                TasMovie newProject = CurrentTasMovie.ConvertToSaveRamAnchoredMovie(
                    SaveRamEmulator.CloneSaveRam());

                GlobalWin.MainForm.PauseEmulator();
                LoadFile(new FileInfo(newProject.Filename), true);
            }
        }
Esempio n. 14
0
		private void EngageTastudio()
		{
			GlobalWin.MainForm.PauseOnFrame = null;
			GlobalWin.OSD.AddMessage("TAStudio engaged");
			_tas = Global.MovieSession.Movie as TasMovie;
			GlobalWin.MainForm.PauseEmulator();
			GlobalWin.MainForm.RelinquishControl(this);
			_originalRewindStatus = Global.Rewinder.RewindActive;
			_originalEndAction = Global.Config.MovieEndAction;
			MarkerControl.Markers = _tas.Markers;
			GlobalWin.MainForm.EnableRewind(false);
			Global.Config.MovieEndAction = MovieEndAction.Record;
			GlobalWin.MainForm.SetMainformMovieInfo();
		}
Esempio n. 15
0
        private bool LoadFile(FileInfo file, bool startsFromSavestate = false)
        {
            if (!file.Exists)
            {
                Settings.RecentTas.HandleLoadError(file.FullName);
                return(false);
            }

            TasMovie newMovie = new TasMovie(startsFromSavestate, _saveBackgroundWorker);

            newMovie.TasStateManager.InvalidateCallback = GreenzoneInvalidated;
            newMovie.Filename = file.FullName;

            if (!HandleMovieLoadStuff(newMovie))
            {
                return(false);
            }

            Settings.RecentTas.Add(newMovie.Filename);             // only add if it did load

            if (TasView.AllColumns.Count() == 0 || file.Extension != "." + TasMovie.Extension)
            {
                SetUpColumns();
            }

            if (startsFromSavestate)
            {
                GoToFrame(0);
            }
            else
            {
                GoToFrame(CurrentTasMovie.Session.CurrentFrame);
            }

            CurrentTasMovie.PropertyChanged += new PropertyChangedEventHandler(this.TasMovie_OnPropertyChanged);
            CurrentTasMovie.CurrentBranch    = CurrentTasMovie.Session.CurrentBranch;

            // clear all selections
            TasView.DeselectAll();
            BookMarkControl.Restart();
            MarkerControl.Restart();

            RefreshDialog();
            return(true);
        }
Esempio n. 16
0
        private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e)
        {
            if (TasView.SelectedRows.Count() == 1 &&
                !CurrentTasMovie.StartsFromSavestate)
            {
                if (AskSaveChanges())
                {
                    int index = TasView.SelectedRows.First();
                    GoToFrame(index);

                    TasMovie newProject = CurrentTasMovie.ConvertToSavestateAnchoredMovie(
                        index, (byte[])StatableEmulator.SaveStateBinary().Clone());

                    GlobalWin.MainForm.PauseEmulator();
                    LoadFile(new FileInfo(newProject.Filename));
                }
            }
        }
Esempio n. 17
0
		public void LoadProject(string path)
		{
			if (AskSave())
			{
				var movie = new TasMovie
				{
					Filename = path
				};

				var file = new FileInfo(path);
				if (!file.Exists)
				{
					Global.Config.RecentTas.HandleLoadError(path);
				}

				GlobalWin.MainForm.StartNewMovie(movie, record: false);
				_tas = Global.MovieSession.Movie as TasMovie;
				Global.Config.RecentTas.Add(path);
				RefreshDialog();
			}
		}
Esempio n. 18
0
        public static TasMovie ToTasMovie(this IMovie old)
        {
            var newFilename = old.Filename + "." + TasMovie.Extension;
            var tas         = new TasMovie(newFilename);

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.SyncSettingsJson = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (var comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (var sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            tas.TextSavestate   = old.TextSavestate;
            tas.BinarySavestate = old.BinarySavestate;

            for (var i = 0; i < old.InputLogLength; i++)
            {
                var input = old.GetInputState(i);
                tas.AppendFrame(input);
            }

            return(tas);
        }
Esempio n. 19
0
        private bool LoadFile(FileInfo file)
        {
            if (!file.Exists)
            {
                Settings.RecentTas.HandleLoadError(file.FullName);
                return(false);
            }

            TasMovie newMovie = new TasMovie(false, _saveBackgroundWorker);

            newMovie.TasStateManager.InvalidateCallback = GreenzoneInvalidated;
            newMovie.Filename = file.FullName;

            Settings.RecentTas.Add(newMovie.Filename);

            if (!HandleMovieLoadStuff(newMovie))
            {
                return(false);
            }

            BookMarkControl.UpdateValues();
            RefreshDialog();
            return(true);
        }
        public static TasMovie ConvertToSavestateAnchoredMovie(this TasMovie old, int frame, byte[] savestate)
        {
            string newFilename = old.Filename + "." + TasMovie.Extension;

            if (File.Exists(newFilename))
            {
                int  fileNum      = 1;
                bool fileConflict = true;
                while (fileConflict)
                {
                    if (File.Exists(newFilename))
                    {
                        newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
                        fileNum++;
                    }
                    else
                    {
                        fileConflict = false;
                    }
                }
            }

            TasMovie tas = new TasMovie(newFilename, true);

            tas.BinarySavestate = savestate;
            tas.ClearLagLog();

            var entries = old.GetLogEntries();

            tas.CopyLog(entries.Skip(frame));
            tas.CopyVerificationLog(old.VerificationLog);
            tas.CopyVerificationLog(entries.Take(frame));

            // States can't be easily moved over, because they contain the frame number.
            // TODO? I'm not sure how this would be done.
            tas.TasStateManager.MountWriteAccess();
            old.TasStateManager.Clear();

            // Lag Log
            tas.TasLagLog.FromLagLog(old.TasLagLog);
            tas.TasLagLog.StartFromFrame(frame);

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.StartsFromSavestate = true;
            tas.SyncSettingsJson    = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (string comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (Subtitle sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            foreach (TasMovieMarker marker in old.Markers)
            {
                if (marker.Frame > frame)
                {
                    tas.Markers.Add(new TasMovieMarker(marker.Frame - frame, marker.Message));
                }
            }

            tas.TasStateManager.Settings = old.TasStateManager.Settings;

            tas.Save();
            return(tas);
        }
        public static TasMovie ConvertToSaveRamAnchoredMovie(this TasMovie old, byte[] saveRam)
        {
            string newFilename = old.Filename;

            if (old.Filename.Contains("tasproj"))
            {
                newFilename = newFilename.Remove(newFilename.Length - 7, 7);
                newFilename = $"{newFilename}nfsr.{TasMovie.Extension}";
            }
            else
            {
                newFilename = $"{old.Filename}.{TasMovie.Extension}";
            }

            if (File.Exists(newFilename))
            {
                int  fileNum      = 1;
                bool fileConflict = true;
                while (fileConflict)
                {
                    if (File.Exists(newFilename))
                    {
                        newFilename = $"{old.Filename} ({fileNum}).{TasMovie.Extension}";
                        fileNum++;
                    }
                    else
                    {
                        fileConflict = false;
                    }
                }
            }

            var tas = new TasMovie(newFilename, true)
            {
                SaveRam = saveRam
            };

            tas.TasStateManager.Clear();
            tas.ClearLagLog();

            var entries = old.GetLogEntries();

            tas.CopyVerificationLog(old.VerificationLog);
            tas.CopyVerificationLog(entries);

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.StartsFromSaveRam   = true;
            tas.StartsFromSavestate = false;
            tas.SyncSettingsJson    = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (string comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (Subtitle sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            tas.TasStateManager.Settings = old.TasStateManager.Settings;

            tas.Save();
            return(tas);
        }
        public static TasMovie ConvertToSavestateAnchoredMovie(this TasMovie old, int frame, byte[] savestate)
        {
            string newFilename = old.Filename + "." + TasMovie.Extension;

            if (File.Exists(newFilename))
            {
                int fileNum = 1;
                bool fileConflict = true;
                while (fileConflict)
                {
                    if (File.Exists(newFilename))
                    {
                        newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
                        fileNum++;
                    }
                    else
                    {
                        fileConflict = false;
                    }
                }
            }

            var tas = new TasMovie(newFilename, true);
            tas.BinarySavestate = savestate;
            tas.TasStateManager.Clear();
            tas.ClearLagLog();

            var entries = old.GetLogEntries();

            tas.CopyLog(entries.Skip(frame));
            tas.CopyVerificationLog(entries.Take(frame));

            tas.HeaderEntries.Clear();
            foreach (var kvp in old.HeaderEntries)
            {
                tas.HeaderEntries[kvp.Key] = kvp.Value;
            }

            tas.StartsFromSavestate = true;
            tas.SyncSettingsJson = old.SyncSettingsJson;

            tas.Comments.Clear();
            foreach (var comment in old.Comments)
            {
                tas.Comments.Add(comment);
            }

            tas.Subtitles.Clear();
            foreach (var sub in old.Subtitles)
            {
                tas.Subtitles.Add(sub);
            }

            foreach(var marker in old.Markers)
            {
                if (marker.Frame > 0)
                {
                    tas.Markers.Add(marker);
                }
            }

            tas.TasStateManager.Settings = old.TasStateManager.Settings;

            tas.Save();
            return tas;
        }
Esempio n. 23
0
 public TasMovieMarkerList(TasMovie movie)
 {
     _movie = movie;
 }
		public static TasMovie ConvertToSavestateAnchoredMovie(this TasMovie old, int frame, byte[] savestate)
		{
			string newFilename = old.Filename + "." + TasMovie.Extension;

			if (File.Exists(newFilename))
			{
				int fileNum = 1;
				bool fileConflict = true;
				while (fileConflict)
				{
					if (File.Exists(newFilename))
					{
						newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
						fileNum++;
					}
					else
					{
						fileConflict = false;
					}
				}
			}

			TasMovie tas = new TasMovie(newFilename, true);
			tas.BinarySavestate = savestate;
			tas.ClearLagLog();

			var entries = old.GetLogEntries();

			tas.CopyLog(entries.Skip(frame));
			tas.CopyVerificationLog(old.VerificationLog);
			tas.CopyVerificationLog(entries.Take(frame));

			// States can't be easily moved over, because they contain the frame number.
			// TODO? I'm not sure how this would be done.
			tas.TasStateManager.MountWriteAccess();
			old.TasStateManager.Clear();

			// Lag Log
			tas.TasLagLog.FromLagLog(old.TasLagLog);
			tas.TasLagLog.StartFromFrame(frame);

			tas.HeaderEntries.Clear();
			foreach (var kvp in old.HeaderEntries)
			{
				tas.HeaderEntries[kvp.Key] = kvp.Value;
			}

			tas.StartsFromSavestate = true;
			tas.SyncSettingsJson = old.SyncSettingsJson;

			tas.Comments.Clear();
			foreach (string comment in old.Comments)
			{
				tas.Comments.Add(comment);
			}

			tas.Subtitles.Clear();
			foreach (Subtitle sub in old.Subtitles)
			{
				tas.Subtitles.Add(sub);
			}

			foreach (TasMovieMarker marker in old.Markers)
			{
				if (marker.Frame > frame)
					tas.Markers.Add(new TasMovieMarker(marker.Frame - frame, marker.Message));
			}

			tas.TasStateManager.Settings = old.TasStateManager.Settings;

			tas.Save();
			return tas;
		}
		public static TasMovie ToTasMovie(this IMovie old, bool copy = false)
		{
			string newFilename = old.Filename + "." + TasMovie.Extension;

			if (File.Exists(newFilename))
			{
				int fileNum = 1;
				bool fileConflict = true;
				while (fileConflict)
				{
					if (File.Exists(newFilename))
					{
						newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
						fileNum++;
					}
					else
					{
						fileConflict = false;
					}
				}
			}

			var tas = new TasMovie(newFilename, old.StartsFromSavestate);
			tas.TasStateManager.MountWriteAccess();

			for (var i = 0; i < old.InputLogLength; i++)
			{
				var input = old.GetInputState(i);
				tas.AppendFrame(input);
			}

			if (!copy)
			{
				old.Truncate(0); // Trying to minimize ram usage
			}

			tas.HeaderEntries.Clear();
			foreach (var kvp in old.HeaderEntries)
			{
				tas.HeaderEntries[kvp.Key] = kvp.Value;
			}

			tas.SyncSettingsJson = old.SyncSettingsJson;

			tas.Comments.Clear();
			foreach (var comment in old.Comments)
			{
				tas.Comments.Add(comment);
			}

			tas.Subtitles.Clear();
			foreach (var sub in old.Subtitles)
			{
				tas.Subtitles.Add(sub);
			}

			tas.TextSavestate = old.TextSavestate;
			tas.BinarySavestate = old.BinarySavestate;
			tas.SaveRam = old.SaveRam;

			return tas;
		}