convert YMV importing to new way, and also fix it, it's been broken for a long time, if it ever worked

This commit is contained in:
adelikat 2019-11-10 12:14:50 -06:00
parent c1516de259
commit c5ecba326f
4 changed files with 136 additions and 95 deletions

View File

@ -158,6 +158,7 @@
<Compile Include="movie\import\LsmvImport.cs" />
<Compile Include="movie\import\Mc2Import.cs" />
<Compile Include="movie\import\PxmImport.cs" />
<Compile Include="movie\import\YmvImport.cs" />
<Compile Include="movie\tasproj\IStateManager.cs" />
<Compile Include="movie\tasproj\StateManagerDecay.cs" />
<Compile Include="movie\tasproj\TasBranch.cs" />

View File

@ -4,7 +4,6 @@ using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using BizHawk.Common;
using BizHawk.Common.BufferExtensions;
using BizHawk.Common.IOExtensions;
@ -154,9 +153,6 @@ namespace BizHawk.Client.Common
case ".VBM":
m = ImportVbm(path, out errorMsg, out warningMsg);
break;
case ".YMV":
m = ImportYmv(path, out errorMsg, out warningMsg);
break;
case ".BKM":
m.Filename = path;
m.Load(false);
@ -197,7 +193,7 @@ namespace BizHawk.Client.Common
{
string[] extensions =
{
"BKM", "FMV", "GMV", "MMV", "SMV", "VBM", "YMV"
"BKM", "FMV", "GMV", "MMV", "SMV", "VBM"
};
return extensions.Any(ext => extension.ToUpper() == $".{ext}");
}
@ -245,96 +241,6 @@ namespace BizHawk.Client.Common
return m;
}
// YMV file format: https://code.google.com/p/yabause-rr/wiki/YMVfileformat
private static BkmMovie ImportYmv(string path, out string errorMsg, out string warningMsg)
{
errorMsg = warningMsg = "";
var m = new BkmMovie(path);
var file = new FileInfo(path);
var sr = file.OpenText();
var emulator = "Yabause";
var platform = "Sega Saturn";
m.Header[HeaderKeys.PLATFORM] = platform;
int lineNum = 0;
string line;
while ((line = sr.ReadLine()) != null)
{
lineNum++;
if (line == "")
{
continue;
}
if (line[0] == '|')
{
m = ImportTextFrame(line, lineNum, m, path, platform, ref warningMsg);
if (errorMsg != "")
{
sr.Close();
return null;
}
}
else if (line.ToLower().StartsWith("emuversion"))
{
m.Comments.Add($"{EMULATIONORIGIN} {emulator} version {ParseHeader(line, "emuVersion")}");
}
else if (line.ToLower().StartsWith("version"))
{
string version = ParseHeader(line, "version");
m.Comments.Add($"{MOVIEORIGIN} {Path.GetExtension(path)} version {version}");
}
else if (line.ToLower().StartsWith("romfilename"))
{
m.Header[HeaderKeys.GAMENAME] = ParseHeader(line, "romFilename");
}
else if (line.ToLower().StartsWith("comment author"))
{
m.Header[HeaderKeys.AUTHOR] = ParseHeader(line, "comment author");
}
else if (line.ToLower().StartsWith("rerecordcount"))
{
int rerecordCount;
// Try to parse the re-record count as an integer, defaulting to 0 if it fails.
try
{
rerecordCount = int.Parse(ParseHeader(line, "rerecordCount"));
}
catch
{
rerecordCount = 0;
}
m.Rerecords = (ulong)rerecordCount;
}
else if (line.ToLower().StartsWith("startsfromsavestate"))
{
// If this movie starts from a savestate, we can't support it.
if (ParseHeader(line, "StartsFromSavestate") == "1")
{
errorMsg = "Movies that begin with a savestate are not supported.";
sr.Close();
return null;
}
}
else if (line.ToLower().StartsWith("ispal"))
{
bool pal = ParseHeader(line, "isPal") == "1";
m.Header[HeaderKeys.PAL] = pal.ToString();
}
else
{
// Everything not explicitly defined is treated as a comment.
m.Comments.Add(line);
}
}
sr.Close();
return m;
}
// Get the content for a particular header.
private static string ParseHeader(string line, string headerName)
{

View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Consoles.Sega.Saturn;
namespace BizHawk.Client.Common.movie.import
{
// https://code.google.com/archive/p/yabause-rr/wikis/YMVfileformat.wiki
// ReSharper disable once UnusedMember.Global
[ImportExtension(".ymv")]
public class YmvImport : MovieImporter
{
protected override void RunImport()
{
Result.Movie.HeaderEntries[HeaderKeys.PLATFORM] = "SAT";
var ss = new Saturnus.SyncSettings
{
Port1 = SaturnusControllerDeck.Device.Gamepad,
Port2 = SaturnusControllerDeck.Device.None
};
using var sr = SourceFile.OpenText();
string line;
while ((line = sr.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
if (line[0] == '|')
{
ImportTextFrame(line);
}
else if (line.ToLower().StartsWith("emuversion"))
{
Result.Movie.Comments.Add($"{EmulationOrigin} Yabause version {ParseHeader(line, "emuVersion")}");
}
else if (line.ToLower().StartsWith("version"))
{
string version = ParseHeader(line, "version");
Result.Movie.Comments.Add($"{MovieOrigin} .ymv version {version}");
}
else if (line.ToLower().StartsWith("cdGameName"))
{
Result.Movie.HeaderEntries[HeaderKeys.GAMENAME] = ParseHeader(line, "romFilename");
}
else if (line.ToLower().StartsWith("rerecordcount"))
{
int rerecordCount;
// Try to parse the re-record count as an integer, defaulting to 0 if it fails.
try
{
rerecordCount = int.Parse(ParseHeader(line, "rerecordCount"));
}
catch
{
rerecordCount = 0;
}
Result.Movie.Rerecords = (ulong)rerecordCount;
}
else if (line.ToLower().StartsWith("startsfromsavestate"))
{
// If this movie starts from a savestate, we can't support it.
if (ParseHeader(line, "StartsFromSavestate") == "1")
{
Result.Errors.Add("Movies that begin with a savestate are not supported.");
}
}
else if (line.ToLower().StartsWith("ispal"))
{
bool pal = ParseHeader(line, "isPal") == "1";
Result.Movie.HeaderEntries[HeaderKeys.PAL] = pal.ToString();
}
else
{
// Everything not explicitly defined is treated as a comment.
Result.Movie.Comments.Add(line);
}
}
Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(ss);
}
private void ImportTextFrame(string line)
{
// Yabause only supported 1 controller
var controllers = new SimpleController
{
Definition = new ControllerDefinition
{
Name = "Saturn Controller",
BoolButtons = new List<string>
{
"Reset", "Power", "Previous Disk", "Next Disk", "P1 Left", "P1 Right", "P1 Up", "P1 Down", "P1 Start", "P1 A", "P1 B", "P1 C", "P1 X", "P1 Y", "P1 Z", "P1 L", "P1 R"
}
}
};
// Split up the sections of the frame.
string[] sections = line.Split(new [] { "|" }, StringSplitOptions.RemoveEmptyEntries);
if (sections.Length != 2)
{
Result.Errors.Add("Unsupported input configuration");
return;
}
if (sections[0][0] == '1')
{
controllers["Reset"] = true;
}
var buttonNames = controllers.Definition.ControlsOrdered.Skip(1).First().ToList();
// Only count lines with that have the right number of buttons and are for valid players.
if (sections[1].Length == buttonNames.Count)
{
for (int button = 0; button < buttonNames.Count; button++)
{
// Consider the button pressed so long as its spot is not occupied by a ".".
controllers[buttonNames[button]] = sections[1][button] != '.';
}
}
// Convert the data for the controllers to a mnemonic and add it as a frame.
Result.Movie.AppendFrame(controllers);
}
}
}

View File

@ -270,6 +270,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=resizer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rewinder/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=samp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Saturnus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=saveram/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=savestate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=savestates/@EntryIndexedValue">True</s:Boolean>