BizHawk/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs

371 lines
8.8 KiB
C#
Raw Normal View History

using System;
using System.IO;
using System.Linq;
using BizHawk.Emulation.Common;
2014-07-19 23:24:43 +00:00
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
using BizHawk.Emulation.Cores.Nintendo.SubNESHawk;
using BizHawk.Emulation.Cores.Sega.MasterSystem;
using BizHawk.Emulation.Common.IEmulatorExtensions;
2016-02-28 15:21:18 +00:00
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
2017-07-09 15:56:18 +00:00
using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive;
namespace BizHawk.Client.Common.MovieConversionExtensions
{
public static class MovieConversionExtensions
{
public static TasMovie ToTasMovie(this IMovie old, bool copy = false)
{
2019-03-20 05:01:12 +00:00
string newFilename = $"{old.Filename}.{TasMovie.Extension}";
if (File.Exists(newFilename))
{
int fileNum = 1;
bool fileConflict = true;
while (fileConflict)
{
if (File.Exists(newFilename))
{
2019-03-20 05:01:12 +00:00
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;
}
public static Bk2Movie ToBk2(this IMovie old, bool copy = false, bool backup = false)
{
var bk2 = new Bk2Movie(old.Filename.Replace(old.PreferredExtension, Bk2Movie.Extension));
for (var i = 0; i < old.InputLogLength; i++)
{
var input = old.GetInputState(i);
bk2.AppendFrame(input);
}
if (!copy)
{
old.Truncate(0); // Trying to minimize ram usage
}
bk2.HeaderEntries.Clear();
foreach (var kvp in old.HeaderEntries)
{
bk2.HeaderEntries[kvp.Key] = kvp.Value;
}
bk2.SyncSettingsJson = old.SyncSettingsJson;
bk2.Comments.Clear();
foreach (var comment in old.Comments)
{
bk2.Comments.Add(comment);
}
bk2.Subtitles.Clear();
foreach (var sub in old.Subtitles)
{
bk2.Subtitles.Add(sub);
}
bk2.TextSavestate = old.TextSavestate;
bk2.BinarySavestate = old.BinarySavestate;
bk2.SaveRam = old.SaveRam;
if (!backup)
{
bk2.Save();
}
return bk2;
}
public static TasMovie ConvertToSavestateAnchoredMovie(this TasMovie old, int frame, byte[] savestate)
{
string newFilename = old.Filename;
if (old.Filename.Contains("tasproj"))
{
newFilename = newFilename.Remove(newFilename.Length - 7, 7);
2019-03-20 05:01:12 +00:00
newFilename = $"{newFilename}nfn.{TasMovie.Extension}";
}
else
{
2019-03-20 05:01:12 +00:00
newFilename = $"{old.Filename}.{TasMovie.Extension}";
}
if (File.Exists(newFilename))
{
int fileNum = 1;
bool fileConflict = true;
while (fileConflict)
{
if (File.Exists(newFilename))
{
2019-03-20 05:01:12 +00:00
newFilename = $"{old.Filename} ({fileNum}).{TasMovie.Extension}";
fileNum++;
}
else
{
fileConflict = false;
}
}
}
2017-05-18 16:36:38 +00:00
var tas = new TasMovie(newFilename, true) { 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();
2018-02-20 16:28:54 +00:00
old.TasStateManager.ClearStateHistory();
// 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);
2019-03-20 05:01:12 +00:00
newFilename = $"{newFilename}nfsr.{TasMovie.Extension}";
}
else
{
2019-03-20 05:01:12 +00:00
newFilename = $"{old.Filename}.{TasMovie.Extension}";
}
if (File.Exists(newFilename))
{
int fileNum = 1;
bool fileConflict = true;
while (fileConflict)
{
if (File.Exists(newFilename))
{
2019-03-20 05:01:12 +00:00
newFilename = $"{old.Filename} ({fileNum}).{TasMovie.Extension}";
fileNum++;
}
else
{
fileConflict = false;
}
}
}
2017-05-18 16:36:38 +00:00
var tas = new TasMovie(newFilename, true) { SaveRam = saveRam };
2018-02-20 16:28:54 +00:00
tas.TasStateManager.ClearStateHistory();
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;
}
// TODO: This doesn't really belong here, but not sure where to put it
public static void PopulateWithDefaultHeaderValues(this IMovie movie, string author = null)
{
movie.Author = author ?? Global.Config.DefaultAuthor;
movie.EmulatorVersion = VersionInfo.GetEmuVersion();
2014-07-19 21:41:47 +00:00
movie.SystemID = Global.Emulator.SystemId;
var settable = new SettingsAdapter(Global.Emulator);
if (settable.HasSyncSettings)
{
movie.SyncSettingsJson = ConfigService.SaveWithType(settable.GetSyncSettings());
}
if (Global.Game != null)
{
movie.GameName = PathManager.FilesystemSafeName(Global.Game);
movie.Hash = Global.Game.Hash;
if (Global.Game.FirmwareHash != null)
{
movie.FirmwareHash = Global.Game.FirmwareHash;
}
}
else
{
movie.GameName = "NULL";
}
if (Global.Emulator.HasBoardInfo())
{
movie.BoardName = Global.Emulator.AsBoardInfo().BoardName;
}
if (Global.Emulator.HasRegions())
{
var region = Global.Emulator.AsRegionable().Region;
if (region == Emulation.Common.DisplayType.PAL)
{
movie.HeaderEntries.Add(HeaderKeys.PAL, "1");
}
}
if (Global.FirmwareManager.RecentlyServed.Any())
{
foreach (var firmware in Global.FirmwareManager.RecentlyServed)
{
2019-03-20 05:01:12 +00:00
var key = $"{firmware.SystemId}_Firmware_{firmware.FirmwareId}";
if (!movie.HeaderEntries.ContainsKey(key))
{
movie.HeaderEntries.Add(key, firmware.Hash);
}
}
}
2014-07-19 23:24:43 +00:00
if (Global.Emulator is Gameboy && (Global.Emulator as Gameboy).IsCGBMode())
{
movie.HeaderEntries.Add("IsCGBMode", "1");
}
if (Global.Emulator is SMS && (Global.Emulator as SMS).IsSG1000)
{
movie.HeaderEntries.Add("IsSGMode", "1");
}
2017-07-09 16:11:33 +00:00
if (Global.Emulator is SMS && (Global.Emulator as SMS).IsGameGear)
{
movie.HeaderEntries.Add("IsGGMode", "1");
}
if (Global.Emulator is GPGX && (Global.Emulator as GPGX).IsMegaCD)
2016-02-28 15:21:18 +00:00
{
movie.HeaderEntries.Add("IsSegaCDMode", "1");
}
2017-07-09 17:27:13 +00:00
if (Global.Emulator is PicoDrive && Global.Game["32X"])
2017-07-09 17:08:10 +00:00
{
movie.HeaderEntries.Add("Is32X", "1");
}
if (Global.Emulator is SubNESHawk)
{
movie.HeaderEntries.Add("VBlankCount", "0");
}
movie.Core = ((CoreAttribute)Attribute
.GetCustomAttribute(Global.Emulator.GetType(), typeof(CoreAttribute)))
.CoreName;
}
}
}