BizHawk/BizHawk.MultiClient/movie/MovieImport.cs

1444 lines
48 KiB
C#
Raw Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
#pragma warning disable 219
namespace BizHawk.MultiClient
{
public static class MovieImport
{
public const string EMULATIONORIGIN = "emuVersion";
public const string MOVIEORIGIN = "MovieOrigin";
// Attempt to import another type of movie file into a movie object.
public static Movie ImportFile(string path, out string errorMsg, out string warningMsg)
{
Movie m = new Movie();
errorMsg = "";
warningMsg = "";
try
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
switch (Path.GetExtension(path).ToUpper())
{
case ".FCM":
m = ImportFCM(path, out errorMsg, out warningMsg);
break;
case ".FM2":
m = ImportFM2(path, out errorMsg, out warningMsg);
break;
case ".FMV":
m = ImportFMV(path, out errorMsg, out warningMsg);
break;
case ".GMV":
m = ImportGMV(path, out errorMsg, out warningMsg);
break;
case ".NMV":
m = ImportNMV(path, out errorMsg, out warningMsg);
break;
case ".MCM":
m = ImportMCM(path, out errorMsg, out warningMsg);
break;
case ".MC2":
m = ImportMC2(path, out errorMsg, out warningMsg);
break;
case ".MMV":
m = ImportMMV(path, out errorMsg, out warningMsg);
break;
case ".SMV":
m = ImportSMV(path, out errorMsg, out warningMsg);
break;
case ".VBM":
m = ImportVBM(path, out errorMsg, out warningMsg);
break;
case ".VMV":
m = ImportVMV(path, out errorMsg, out warningMsg);
break;
}
if (errorMsg == "")
{
m.Header.SetHeaderLine(MovieHeader.MOVIEVERSION, MovieHeader.MovieVersion);
m.WriteMovie();
}
}
catch (Exception except)
{
errorMsg = except.ToString();
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
return m;
}
// Return whether or not the type of file provided can currently be imported.
public static bool IsValidMovieExtension(string extension)
{
string[] extensions = new string[11] {
"FCM", "FM2", "FMV", "GMV", "NMV", "MCM", "MC2", "MMV", "SMV", "VBM", "VMV"
};
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
foreach (string ext in extensions)
if (extension.ToUpper() == "." + ext)
return true;
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
return false;
}
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
// Import a text-based movie format. This works for .FM2 and .MC2.
private static Movie ImportText(string path, out string errorMsg, out string warningMsg)
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
errorMsg = "";
warningMsg = "";
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileInfo file = new FileInfo(path);
StreamReader sr = file.OpenText();
string[] buttons = new string[] { };
string controller = "";
string emulator = "";
string platform = "";
switch (Path.GetExtension(path).ToUpper())
{
case ".FM2":
buttons = new string[8] { "Right", "Left", "Down", "Up", "Start", "Select", "B", "A" };
controller = "NES Controller";
emulator = "FCEUX";
platform = "NES";
break;
case ".MC2":
buttons = new string[8] { "Up", "Down", "Left", "Right", "B1", "B2", "Run", "Select" };
controller = "PC Engine Controller";
emulator = "Mednafen/PCEjin";
platform = "PCE";
break;
}
m.Header.SetHeaderLine(MovieHeader.PLATFORM, platform);
int lineNum = 0;
string line = "";
while ((line = sr.ReadLine()) != null)
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
lineNum++;
if (line == "")
continue;
if (line.StartsWith("emuVersion"))
m.Header.Comments.Add(EMULATIONORIGIN + " " + emulator + " version " + ParseHeader(line, "emuVersion"));
else if (line.StartsWith("version"))
m.Header.Comments.Add(
MOVIEORIGIN + " " + Path.GetExtension(path) + " version " + ParseHeader(line, "version")
);
else if (line.StartsWith("romFilename"))
m.Header.SetHeaderLine(MovieHeader.GAMENAME, ParseHeader(line, "romFilename"));
else if (line.StartsWith("comment author"))
m.Header.SetHeaderLine(MovieHeader.AUTHOR, ParseHeader(line, "comment author"));
else if (line.StartsWith("rerecordCount"))
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
int rerecordCount;
// Try to parse the re-record count as an integer, defaulting to 0 if it fails.
try
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
rerecordCount = int.Parse(ParseHeader(line, "rerecordCount"));
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
catch
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
rerecordCount = 0;
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
m.SetRerecords(rerecordCount);
}
else if (line.StartsWith("guid"))
m.Header.SetHeaderLine(MovieHeader.GUID, ParseHeader(line, "GUID"));
else if (line.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.StartsWith("palFlag"))
{
bool pal;
// Try to parse the PAL setting as a bool, defaulting to false if it fails.
try
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
pal = Convert.ToBoolean(int.Parse(ParseHeader(line, "palFlag")));
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
catch
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
pal = false;
}
m.Header.SetHeaderLine("PAL", pal.ToString());
}
else if (line.StartsWith("fourscore"))
m.Header.SetHeaderLine(
MovieHeader.FOURSCORE,
Convert.ToBoolean(
int.Parse(ParseHeader(line, "fourscore"))
).ToString()
);
else if (line.StartsWith("sub"))
{
Subtitle s = new Subtitle();
// The header name, frame, and message are separated by a space.
int first = line.IndexOf(' ');
int second = line.IndexOf(' ', first + 1);
if (first != -1 && second != -1)
{
// Concatenate the frame and message with default values for the additional fields.
string frame = line.Substring(first + 1, second - first - 1);
string message = line.Substring(second + 1, line.Length - second - 1);
m.Subtitles.AddSubtitle("subtitle " + frame + " 0 0 200 FFFFFFFF " + message);
}
}
else if (line[0] == '|')
{
// Handle a frame of input.
ArrayList frame = new ArrayList();
// Split up the sections of the frame.
string[] sections = line.Split('|');
// Start building the data for the controllers.
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = controller;
// Get the first invalid command warning message that arises.
if (Path.GetExtension(path).ToUpper() == ".FM2" && warningMsg == "" && sections[1].Length != 0)
{
switch (sections[1][0])
{
case '0':
break;
case '1':
controllers["Reset"] = true;
break;
case '2':
if (m.Length() != 0)
{
warningMsg = "hard reset";
}
break;
case '4':
warningMsg = "FDS Insert";
break;
case '8':
warningMsg = "FDS Select Side";
break;
default:
warningMsg = "unknown";
break;
}
if (warningMsg != "")
warningMsg = "Unable to import " + warningMsg + " command on line " + lineNum + ".";
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
/*
Skip the first two sections of the split, which consist of everything before the starting | and the
command. Do not use the section after the last |. In other words, get the sections for the players.
*/
for (int section = 2; section < sections.Length - 1; section++)
{
// The player number is one less than the section number for the reasons explained above.
int player = section - 1;
// Only count lines with that have the right number of buttons and are for valid players.
if (
sections[section].Length == buttons.Length &&
player <= Global.PLAYERS[controllers.Type.Name]
)
for (int button = 0; button < buttons.Length; button++)
// Consider the button pressed so long as its spot is not occupied by a ".".
controllers["P" + (player).ToString() + " " + buttons[button]] = (
sections[section][button] != '.'
);
}
// Convert the data for the controllers to a mnemonic and add it as a frame.
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic());
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
else
// Everything not explicitly defined is treated as a comment.
m.Header.Comments.Add(line);
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
sr.Close();
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
return m;
}
// Get the content for a particular header.
private static string ParseHeader(string line, string headerName)
{
string str;
int x = line.LastIndexOf(headerName) + headerName.Length;
str = line.Substring(x + 1, line.Length - x - 1);
return str;
}
// Remove the NULL characters from a string.
private static string RemoveNull(string original)
{
string translated = "";
for (int character = 0; character < original.Length; character++)
if (original[character] != '\0')
translated += original[character];
return translated;
}
// FCM file format: http://code.google.com/p/fceu/wiki/FCM
private static Movie ImportFCM(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 4-byte signature: 46 43 4D 1A "FCM\x1A"
string signature = r.ReadStringFixedAscii(4);
if (signature != "FCM\x1A")
{
errorMsg = "This is not a valid .FCM file.";
r.Close();
fs.Close();
return null;
}
// 004 4-byte little-endian unsigned int: version number, must be 2
uint version = r.ReadUInt32();
if (version != 2)
{
errorMsg = ".FCM movie version must always be 2.";
r.Close();
fs.Close();
return null;
}
m.Header.Comments.Add(MOVIEORIGIN + " .FCM version " + version);
// 008 1-byte flags
byte flags = r.ReadByte();
// bit 0: reserved, set to 0
/*
bit 1:
* if "0", movie begins from an embedded "quicksave" snapshot
* if "1", movie begins from reset or power-on[1]
*/
if ((flags & 2) == 0)
{
errorMsg = "Movies that begin with a savestate are not supported.";
r.Close();
fs.Close();
return null;
}
/*
bit 2:
* if "0", NTSC timing
* if "1", PAL timing
* see notes below
*/
bool pal = ((flags & 4) != 0);
// other: reserved, set to 0
/*
Starting with version 0.98.12 released on September 19, 2004, a PAL flag was added to the header but
unfortunately it is not reliable - the emulator does not take the PAL setting from the ROM, but from a user
preference. This means that this site cannot calculate movie lengths reliably.
*/
m.Header.SetHeaderLine("PAL", pal.ToString());
bool movieSyncHackOn = ((flags & 16) != 0);
m.Header.Comments.Add("SyncHack " + movieSyncHackOn.ToString());
/*
009 1-byte flags: reserved, set to 0
00A 1-byte flags: reserved, set to 0
00B 1-byte flags: reserved, set to 0
*/
r.ReadBytes(3);
// 00C 4-byte little-endian unsigned int: number of frames
uint frameCount = r.ReadUInt32();
// 010 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.SetRerecords((int)rerecordCount);
// 014 4-byte little-endian unsigned int: length of controller data in bytes
uint movieDataSize = r.ReadUInt32();
/*
018 4-byte little-endian unsigned int: offset to the savestate inside file
The savestate offset is <header_size + length_of_metadata_in_bytes + padding>. The savestate offset should be
4-byte aligned. At the savestate offset there is a savestate file. The savestate exists even if the movie is
reset-based.
*/
r.ReadUInt32();
// 01C 4-byte little-endian unsigned int: offset to the controller data inside file
uint firstFrameOffset = r.ReadUInt32();
// 020 16-byte md5sum of the ROM used
byte[] MD5 = r.ReadBytes(16);
m.Header.SetHeaderLine("MD5", BizHawk.Util.BytesToHexString(MD5).ToLower());
// 030 4-byte little-endian unsigned int: version of the emulator used
uint emuVersion = r.ReadUInt32();
m.Header.Comments.Add(EMULATIONORIGIN + " FCEU " + emuVersion.ToString());
// 034 name of the ROM used - UTF8 encoded nul-terminated string.
List<byte> gameBytes = new List<byte>();
while (r.PeekChar() != 0)
gameBytes.Add(r.ReadByte());
// Advance past null byte.
r.ReadByte();
string gameName = System.Text.Encoding.UTF8.GetString(gameBytes.ToArray());
m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName);
/*
After the header comes "metadata", which is UTF8-coded movie title string. The metadata begins after the ROM
name and ends at the savestate offset. This string is displayed as "Author Info" in the Windows version of the
emulator.
*/
List<byte> authorBytes = new List<byte>();
while (r.PeekChar() != 0)
authorBytes.Add(r.ReadByte());
// Advance past null byte.
r.ReadByte();
string author = System.Text.Encoding.UTF8.GetString(authorBytes.ToArray());
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author);
// Advance to first byte of input data.
r.BaseStream.Position = firstFrameOffset;
string[] buttons = new string[8] { "A", "B", "Select", "Start", "Up", "Down", "Left", "Right" };
bool fourscore = false;
int frame = 1;
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = "NES Controller";
while (frame <= frameCount)
{
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
string mnemonic = mg.GetControllersAsMnemonic();
byte update = r.ReadByte();
// aa: Number of delta bytes to follow
int delta = (update >> 5) & 3;
int frames = 0;
/*
The delta byte(s) indicate the number of emulator frames between this update and the next update. It is
encoded in little-endian format and its size depends on the magnitude of the delta:
Delta of: Number of bytes:
0 0
1-255 1
256-65535 2
65536-(2^24-1) 3
*/
for (int b = 0; b < delta; b++)
frames += r.ReadByte() * (int)Math.Pow(2, b * 8);
while (frames > 0)
{
m.AppendFrame(mnemonic);
if (controllers["Reset"])
{
controllers["Reset"] = false;
mnemonic = mg.GetControllersAsMnemonic();
}
frame++;
frames--;
}
if ((int)(update & 0x80) != 0)
{
// Control update: 1aabbbbb
bool reset = false;
int command = update & 0x1F;
// bbbbb:
if (warningMsg == "")
{
switch (command)
{
// Do nothing
case 0:
break;
// Reset
case 1:
reset = !controllers["Reset"];
controllers["Reset"] = reset;
break;
// Power cycle
case 2:
reset = true;
if (frame != 1)
warningMsg = "hard reset";
break;
// VS System Insert Coin
case 7:
warningMsg = "VS System Insert Coin";
break;
// VS System Dipswitch 0 Toggle
case 8:
warningMsg = "VS System Dipswitch 0 Toggle";
break;
// FDS Insert
case 24:
warningMsg = "FDS Insert";
break;
// FDS Eject
case 25:
warningMsg = "FDS Eject";
break;
// FDS Select Side
case 26:
warningMsg = "FDS Select Side";
break;
default:
warningMsg = "unknown";
break;
}
if (warningMsg != "")
warningMsg = "Unable to import " + warningMsg + " command at frame " + frame + ".";
}
/*
1 Even if the header says "movie begins from reset", the file still contains a quicksave, and the
quicksave is actually loaded. This flag can't therefore be trusted. To check if the movie actually
begins from reset, one must analyze the controller data and see if the first non-idle command in the
file is a Reset or Power Cycle type control command.
*/
if (!reset && frame == 1)
{
errorMsg = "Movies that begin with a savestate are not supported.";
r.Close();
fs.Close();
return null;
}
}
else
{
/*
Controller update: 0aabbccc
* bb: Gamepad number minus one (?)
*/
int player = ((update >> 3) & 3) + 1;
/*
ccc:
* 0 A
* 1 B
* 2 Select
* 3 Start
* 4 Up
* 5 Down
* 6 Left
* 7 Right
*/
int button = update & 7;
/*
The controller update toggles the affected input. Controller update data is emitted to the movie file
only when the state of the controller changes.
*/
controllers["P" + player + " " + buttons[button]] = !controllers["P" + player + " " + buttons[button]];
}
}
m.Header.SetHeaderLine(MovieHeader.FOURSCORE, fourscore.ToString());
r.Close();
fs.Close();
return m;
}
// FM2 file format: http://www.fceux.com/web/FM2.html
private static Movie ImportFM2(string path, out string errorMsg, out string warningMsg)
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
errorMsg = "";
warningMsg = "";
Movie m = ImportText(path, out errorMsg, out warningMsg);
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
return m;
}
// FMV file format: http://tasvideos.org/FMV.html
private static Movie ImportFMV(string path, out string errorMsg, out string warningMsg)
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
errorMsg = "";
warningMsg = "";
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 4-byte signature: 46 4D 56 1A "FMV\x1A"
string signature = r.ReadStringFixedAscii(4);
if (signature != "FMV\x1A")
{
errorMsg = "This is not a valid .FMV file.";
r.Close();
fs.Close();
return null;
}
// 004 1-byte flags:
byte flags = r.ReadByte();
// bit 7: 0=reset-based, 1=savestate-based
if ((flags & 0x80) != 0)
{
errorMsg = "Movies that begin with a savestate are not supported.";
r.Close();
fs.Close();
return null;
}
// other bits: unknown, set to 0
// 005 1-byte flags:
flags = r.ReadByte();
// bit 5: is a FDS recording
bool FDS;
if ((flags & 0x20) != 0)
{
FDS = true;
m.Header.SetHeaderLine(MovieHeader.PLATFORM, "FDS");
}
else
{
FDS = false;
m.Header.SetHeaderLine(MovieHeader.PLATFORM, "NES");
}
// bit 6: uses controller 2
bool controller2 = ((flags & 0x40) != 0);
// bit 7: uses controller 1
bool controller1 = ((flags & 0x80) != 0);
// other bits: unknown, set to 0
// 006 4-byte little-endian unsigned int: unknown, set to 00000000
r.ReadInt32();
// 00A 4-byte little-endian unsigned int: rerecord count minus 1
uint rerecordCount = r.ReadUInt32();
/*
The rerecord count stored in the file is the number of times a savestate was loaded. If a savestate was never
loaded, the number is 0. Famtasia however displays "1" in such case. It always adds 1 to the number found in
the file.
*/
m.SetRerecords(((int)rerecordCount) + 1);
// 00E 2-byte little-endian unsigned int: unknown, set to 0000
r.ReadInt16();
// 010 64-byte zero-terminated emulator identifier string
string emuVersion = RemoveNull(r.ReadStringFixedAscii(64));
m.Header.Comments.Add(EMULATIONORIGIN + " Famtasia version " + emuVersion);
// 050 64-byte zero-terminated movie title string
string gameName = RemoveNull(r.ReadStringFixedAscii(64));
m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName);
if (!controller1 && !controller2 && !FDS)
{
warningMsg = "No input recorded.";
r.Close();
fs.Close();
return m;
}
/*
The file format has no means of identifying NTSC/PAL. It is always assumed that the game is NTSC - that is, 60
fps.
*/
m.Header.SetHeaderLine("PAL", "False");
/*
090 frame data begins here
The file has no terminator byte or frame count. The number of frames is the <filesize minus 144> divided by
<number of bytes per frame>.
*/
int bytesPerFrame = 0;
if (controller1)
bytesPerFrame++;
if (controller2)
bytesPerFrame++;
if (FDS)
bytesPerFrame++;
long frames = (fs.Length - 144) / bytesPerFrame;
/*
* 01 Right
* 02 Left
* 04 Up
* 08 Down
* 10 B
* 20 A
* 40 Select
* 80 Start
*/
string[] buttons = new string[8] { "Right", "Left", "Up", "Down", "B", "A", "Select", "Start" };
for (long frame = 1; frame <= frames; frame++)
{
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = "NES Controller";
/*
Each frame consists of 1 or more bytes. Controller 1 takes 1 byte, controller 2 takes 1 byte, and the FDS
data takes 1 byte. If all three exist, the frame is 3 bytes. For example, if the movie is a regular NES game
with only controller 1 data, a frame is 1 byte.
*/
int player = 1;
while (player <= 3)
{
if (player == 1 && !controller1)
player++;
if (player == 2 && !controller2)
player++;
if (player != 3)
{
byte controllerState = r.ReadByte();
byte and = 0x1;
for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = ((int)(controllerState & and) != 0);
and <<= 1;
}
}
else if (FDS)
{
// TODO: FDS data handling here.
byte command = r.ReadByte();
}
player++;
}
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic());
}
r.Close();
fs.Close();
return m;
}
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
// GMV file format: http://code.google.com/p/gens-rerecording/wiki/GMV
private static Movie ImportGMV(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 16-byte signature and format version: "Gens Movie TEST9"
string signature = r.ReadStringFixedAscii(15);
if (signature != "Gens Movie TEST")
{
errorMsg = "This is not a valid .GMV file.";
r.Close();
fs.Close();
return null;
}
// 00F ASCII-encoded GMV file format version. The most recent is 'A'. (?)
string emuVersion = r.ReadStringFixedAscii(1);
m.Header.Comments.Add(EMULATIONORIGIN + " Gens version " + emuVersion);
// 010 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.SetRerecords((int)rerecordCount);
// 014 ASCII-encoded controller config for player 1. '3' or '6'.
string player1Config = r.ReadStringFixedAscii(1);
// 015 ASCII-encoded controller config for player 2. '3' or '6'.
string player2Config = r.ReadStringFixedAscii(1);
if (player1Config == "6" || player2Config == "6")
{
errorMsg = "6 button controllers are not supported.";
r.Close();
fs.Close();
return null;
}
// 016 special flags (Version A and up only)
byte MovieFlags = r.ReadByte();
/*
bit 7 (most significant): if "1", movie runs at 50 frames per second; if "0", movie runs at 60 frames per second
*/
// bit 6: if "1", movie requires a savestate.
if (((MovieFlags >> 6) & 1) == 1)
{
errorMsg = "Movies that begin with a savestate are not supported.";
r.Close();
fs.Close();
return null;
}
// bit 5: if "1", movie is 3-player movie; if "0", movie is 2-player movie
bool twoPlayerMovie = ((MovieFlags >> 5) & 1) == 0;
// Unknown.
r.ReadByte();
// 018 40-byte zero-terminated ASCII movie name string
string movieName = RemoveNull(r.ReadStringFixedAscii(40));
/*
040 frame data
For controller bytes, each value is determined by OR-ing together values for whichever of the following are left
unpressed:
* 0x01 Up
* 0x02 Down
* 0x04 Left
* 0x08 Right
* 0x10 A
* 0x20 B
* 0x40 C
* 0x80 Start
*/
string[] stdButtons = new string[8] { "Up", "Down", "Left", "Right", "A", "B", "C", "Start" };
/*
For XYZ-mode, each value is determined by OR-ing together values for whichever of the following are left
unpressed:
* 0x01 Controller 1 X
* 0x02 Controller 1 Y
* 0x04 Controller 1 Z
* 0x08 Controller 1 Mode
* 0x10 Controller 2 X
* 0x20 Controller 2 Y
* 0x40 Controller 2 Z
* 0x80 Controller 2 Mode
*/
string[] xyzButtons = new string[4] { "X", "Y", "Z", "Mode" };
int frame = 1;
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = "Genesis 3-Button Controller";
while (true)
{
// Each frame consists of 3 bytes.
byte controller1Data;
byte controller2Data;
byte starData;
try
{
controller1Data = r.ReadByte();
}
catch (EndOfStreamException)
{
// Valid end of file reached.
break;
}
try
{
controller2Data = r.ReadByte();
starData = r.ReadByte();
}
catch (EndOfStreamException)
{
errorMsg = "Unexpected end of file.";
r.Close();
fs.Close();
return null;
}
for (int button = 0; button < stdButtons.Length; button++)
{
controllers["P1 " + stdButtons[button]] = ((controller1Data >> button) & 1) == 0;
controllers["P2 " + stdButtons[button]] = ((controller2Data >> button) & 1) == 0;
}
// * is controller 3 if a 3-player movie, or XYZ-mode if a 2-player movie.
if (!twoPlayerMovie)
for (int button = 0; button < stdButtons.Length; button++)
controllers["P3 " + stdButtons[button]] = ((starData >> button) & 1) == 0;
else
for (int i = 0; i < 4; i++)
{
if (player1Config == "6")
controllers["P1 " + xyzButtons[i]] = ((starData >> i) & 1) == 0;
if (player2Config == "6")
controllers["P2 " + xyzButtons[i]] = ((starData >> (i+4)) & 1) == 0;
}
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic());
frame++;
}
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
return m;
}
// NMV file format: http://tasvideos.org/NMV.html
private static Movie ImportNMV(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 4-byte signature: 4E 53 53 1A "NSS\x1A"
string signature = r.ReadStringFixedAscii(4);
if (signature != "NSS\x1A")
{
errorMsg = "This is not a valid .NMV file.";
r.Close();
fs.Close();
return null;
}
r.Close();
fs.Close();
return m;
}
// MCM file format: http://code.google.com/p/mednafen-rr/wiki/MCM
2012-03-09 09:24:47 +00:00
// Mednafen-rr switched to MC2 from r261, so see r260 for details.
private static Movie ImportMCM(string path, out string errorMsg, out string warningMsg)
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
2012-03-09 09:24:47 +00:00
const string SIGNATURE = "MDFNMOVI";
const int MOVIE_VERSION = 1;
const string CONSOLE_PCE = "pce";
const string CTRL_TYPE_PCE = "PC Engine Controller";
string[] CTRL_BUTTONS = {
"B1", "B2", "Select", "Run", "Up", "Right", "Down", "Left"
};
const int INPUT_SIZE_PCE = 11;
const int INPUT_PORT_COUNT = 5;
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
errorMsg = "";
warningMsg = "";
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
2012-03-09 09:24:47 +00:00
// Unless otherwise noted, all values are little-endian.
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 8-byte signature: 4D 44 46 4E 4D 4F 56 49 "MDFNMOVI"
string signature = r.ReadStringFixedAscii(SIGNATURE.Length);
if (signature != SIGNATURE)
{
errorMsg = "This is not a valid .MCM file.";
goto FAIL;
}
// 008 uint32: emulator version, current is 0x0000080A
uint emuVersion = r.ReadUInt32();
m.Header.Comments.Add(EMULATIONORIGIN + " Mednafen " + emuVersion.ToString());
// 00C uint32: movie format version, must be 1
uint version = r.ReadUInt32();
if (version != MOVIE_VERSION)
{
errorMsg = ".MCM movie version must always be 1.";
goto FAIL;
}
m.Header.Comments.Add(MOVIEORIGIN + " .MCM version " + version);
// 010 32-byte (actually, 16-byte) md5sum of the ROM used
byte[] MD5 = r.ReadBytes(16);
r.ReadBytes(16); // discard
m.Header.SetHeaderLine("MD5", BizHawk.Util.BytesToHexString(MD5).ToLower());
// 030 64-byte filename of ROM used (with extension)
string gameName = RemoveNull(r.ReadStringFixedAscii(64));
m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName);
// 070 uint32: re-record count
uint rerecordCount = r.ReadUInt32();
m.SetRerecords((int)rerecordCount);
// 074 5-byte console indicator (pce, ngp, pcfx, wswan)
string console = RemoveNull(r.ReadStringFixedAscii(5));
if (console != CONSOLE_PCE) // for now, bizhawk does not support ngp, pcfx, wswan
{
errorMsg = "Only PCE movies are supported.";
goto FAIL;
}
string platform = "PCE";
m.Header.SetHeaderLine(MovieHeader.PLATFORM, platform);
// 079 32-byte author name
string author = RemoveNull(r.ReadStringFixedAscii(32));
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author);
// 099 103-byte padding 0s
r.ReadBytes(103); // discard
// 100 variable: input data
// For PCE, BizHawk does not have any control command. So I ignore any command.
for (byte[] input = r.ReadBytes(INPUT_SIZE_PCE);
input.Length == INPUT_SIZE_PCE;
input = r.ReadBytes(INPUT_SIZE_PCE))
{
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = CTRL_TYPE_PCE;
for (int player = 1; player <= INPUT_PORT_COUNT; ++player)
{
byte pad = input[1+2*(player-1)];
for(int i = 0; i < 8; ++i)
{
if ((pad & (1<<i)) != 0)
controllers["P" + player + " " + CTRL_BUTTONS[i]] = true;
}
}
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic());
}
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
return m;
2012-03-09 09:24:47 +00:00
FAIL:
r.Close();
fs.Close();
return null;
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
}
// MC2 file format: http://code.google.com/p/pcejin/wiki/MC2
private static Movie ImportMC2(string path, out string errorMsg, out string warningMsg)
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
{
errorMsg = "";
warningMsg = "";
Movie m = ImportText(path, out errorMsg, out warningMsg);
-Began working on the importer. --Created ImportFile to decide what function to use for each filetype. ---It currently automatically writes to a .TAS file, but that option will eventually only be applied when specified in the GUI, hopefully completely external from this class. --Made IsValidMovieExtension work. --Created LoadText to do the majority of the work that both .FM2 and .MC2 need to be done. --.MC2 seems to work perfectly, not that it was a hard conversion! --.FM2 seems to convert most headers correct, except for subtitles, which replaces the beginning portions of each subtitle's text with 0 0 120 4294967295. Not sure what that's about, though this sure feels like deja vu... --I still need to switch around the order of the buttons the frames are added, but I need to find out what way I can do this without reinventing the wheel. -Added the FixMnemonic function to Movie.cs. It currently does nothing, but my goal is to have it correct the mnemonic for all frames in a movie file based on the position of the characters. --As of right now, ImportFile uses this. -MainForm.IsValidMovieExtension only checks whether or not its .TAS or not now. TODO: -Fix the FM2 subtitles. -Shift around the FM2 buttons. --After completed, test a .FM2 file that should sync and see if it works, with and without FixMnemonic being used. -Make FixMnemonic actually do something. -Refactor code? I originally thought it'd be best to treat Movie.LoadText just like any other importer, but I think at this point it might just be best to keep these things completely separate. -Consider the possibility of working with the binary file importers. --Yes adelikat, I am somewhat interested, especially considering how useful it would be to have a working .FCM importer so I can compare old runs when TASing. I already was hoping to learn about .VBM and .SMV for my ButtonCount.lua script. By the way, might this be bundled with bizhawk as it is with FCEUX 2.1.6? :)
2012-02-15 06:54:09 +00:00
// TODO: PCECD equivalent.
return m;
}
// MMV file format: http://tasvideos.org/MMV.html
private static Movie ImportMMV(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 0000: 4-byte signature: "MMV\0"
string signature = r.ReadStringFixedAscii(4);
if (signature != "MMV\0")
{
errorMsg = "This is not a valid .MMV file.";
r.Close();
fs.Close();
return null;
}
// 0004: 4-byte little endian unsigned int: dega version
uint emuVersion = r.ReadUInt32();
m.Header.Comments.Add(EMULATIONORIGIN + " Dega version " + emuVersion.ToString());
// 0008: 4-byte little endian unsigned int: frame count
uint frameCount = r.ReadUInt32();
// 000c: 4-byte little endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.SetRerecords((int)rerecordCount);
// 0010: 4-byte little endian flag: begin from reset?
uint reset = r.ReadUInt32();
if (reset == 0)
{
errorMsg = "Movies that begin with a savestate are not supported.";
r.Close();
fs.Close();
return null;
}
// 0014: 4-byte little endian unsigned int: offset of state information
r.ReadUInt32();
// 0018: 4-byte little endian unsigned int: offset of input data
r.ReadUInt32();
// 001c: 4-byte little endian unsigned int: size of input packet
r.ReadUInt32();
// 0020-005f: string: author info (UTF-8)
string author = RemoveNull(r.ReadStringFixedAscii(64));
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author);
// 0060: 4-byte little endian flags
byte flags = r.ReadByte();
// bit 0: unused
// bit 1: PAL
bool pal = ((flags & 2) != 0);
m.Header.SetHeaderLine("PAL", pal.ToString());
bool japan = ((flags & 4) != 0);
// bit 2: Japan
m.Header.SetHeaderLine("Japan", japan.ToString());
// bit 3: Game Gear (version 1.16+)
bool gamegear;
if ((flags & 8) != 0)
{
gamegear = true;
m.Header.SetHeaderLine(MovieHeader.PLATFORM, "GG");
}
else
{
gamegear = false;
m.Header.SetHeaderLine(MovieHeader.PLATFORM, "SMS");
}
// bits 4-31: unused
r.ReadBytes(3);
// 0064-00e3: string: rom name (ASCII)
string gameName = RemoveNull(r.ReadStringFixedAscii(128));
m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName);
// 00e4-00f3: binary: rom MD5 digest
byte[] MD5 = r.ReadBytes(16);
m.Header.SetHeaderLine("MD5", String.Format("{0:x8}", BizHawk.Util.BytesToHexString(MD5).ToLower()));
/*
76543210
* bit 0 (0x01): up
* bit 1 (0x02): down
* bit 2 (0x04): left
* bit 3 (0x08): right
* bit 4 (0x10): 1
* bit 5 (0x20): 2
* bit 6 (0x40): start (Master System)
* bit 7 (0x80): start (Game Gear)
*/
string[] buttons = new string[6] { "Up", "Down", "Left", "Right", "B1", "B2" };
for (int frame = 1; frame <= frameCount; frame++)
{
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = "SMS Controller";
/*
Controller data is made up of one input packet per frame. Each packet currently consists of 2 bytes. The
first byte is for controller 1 and the second controller 2. The Game Gear only uses the controller 1 input
however both bytes are still present.
*/
for (int player = 1; player <= 2; player++)
{
byte controllerState = r.ReadByte();
byte and = 1;
for (int button = 0; button < buttons.Length; button++)
{
controllers["P" + player + " " + buttons[button]] = ((int)(controllerState & and) != 0);
and <<= 1;
}
if (player == 1)
controllers["Pause"] = (
((int)(controllerState & 0x40) != 0 && (!gamegear)) ||
((int)(controllerState & 0x80) != 0 && gamegear)
);
}
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic());
}
r.Close();
fs.Close();
return m;
}
private static Movie ImportSMV(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
byte[] signatureBytes = new byte[4];
for (int x = 0; x < 4; x++)
signatureBytes[x] = r.ReadByte();
string signature = System.Text.Encoding.UTF8.GetString(signatureBytes);
if (signature.Substring(0, 3) != "SMV")
{
errorMsg = "This is not a valid .SMV file.";
r.Close();
fs.Close();
return null;
}
uint version = r.ReadUInt32();
switch (version)
{
case 1:
return ImportSMV143(r, path);
case 4:
return ImportSMV151(r, path);
case 5:
return ImportSMV152(r, path);
default:
{
errorMsg = "SMV version not recognized, 143, 151, and 152 are currently supported.";
r.Close();
fs.Close();
return null;
}
}
}
// SMV 1.43 file format: http://code.google.com/p/snes9x-rr/wiki/SMV143
private static Movie ImportSMV143(BinaryReader r, string path)
{
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
uint GUID = r.ReadUInt32();
m.Header.SetHeaderLine(MovieHeader.GUID, GUID.ToString()); //TODO: format to hex string
m.SetRerecords((int)r.ReadUInt32());
uint frameCount = r.ReadUInt32();
byte ControllerFlags = r.ReadByte();
int numControllers;
if ((ControllerFlags & 16) != 0)
numControllers = 5;
else if ((ControllerFlags & 8) != 0)
numControllers = 4;
else if ((ControllerFlags & 4) != 0)
numControllers = 3;
else if ((ControllerFlags & 2) != 0)
numControllers = 2;
else
numControllers = 1;
byte MovieFlags = r.ReadByte();
if ((MovieFlags & 1) == 0)
return null; //TODO: Savestate movies not supported error
if ((MovieFlags & 2) != 0)
{
m.Header.SetHeaderLine("PAL", "True");
}
byte SyncOptions = r.ReadByte();
byte SyncOptions2 = r.ReadByte();
//TODO: these
uint SavestateOffset = r.ReadUInt32();
uint FrameDataOffset = r.ReadUInt32();
//TODO: get extra rom info
r.BaseStream.Position = FrameDataOffset;
for (int frame = 1; frame <= frameCount; frame++)
{
//TODO: FF FF for all controllers = Reset
//string frame = "|0|";
for (int controller = 1; controller <= numControllers; controller++)
{
ushort fd = r.ReadUInt16();
}
}
return m;
}
// SMV 1.51 file format: http://code.google.com/p/snes9x-rr/wiki/SMV151
private static Movie ImportSMV151(BinaryReader r, string path)
{
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
return m;
}
private static Movie ImportSMV152(BinaryReader r, string path)
{
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
uint GUID = r.ReadUInt32();
return m;
}
//VBM file format: http://code.google.com/p/vba-rerecording/wiki/VBM
private static Movie ImportVBM(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 4-byte signature: 56 42 4D 1A "VBM\x1A"
string signature = r.ReadStringFixedAscii(4);
if (signature != "VBM\x1A")
{
errorMsg = "This is not a valid .VBM file.";
r.Close();
fs.Close();
return null;
}
// 004 4-byte little-endian unsigned int: major version number, must be "1"
uint majorVersion = r.ReadUInt32();
if (majorVersion != 1)
{
errorMsg = ".VBM major movie version must be 1.";
r.Close();
fs.Close();
return null;
}
/*
008 4-byte little-endian integer: movie "uid" - identifies the movie-savestate relationship, also used as the
recording time in Unix epoch format
*/
uint uid = r.ReadUInt32();
m.Header.SetHeaderLine(MovieHeader.GUID, String.Format("{0:x8}", uid) + "-0000-0000-0000-000000000000");
// 00C 4-byte little-endian unsigned int: number of frames
uint frameCount = r.ReadUInt32();
// 010 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.SetRerecords((int)rerecordCount);
// 014 1-byte flags: (movie start flags)
byte flags = r.ReadByte();
// bit 0: if "1", movie starts from an embedded "quicksave" snapshot
bool startfromquicksave = ((flags & 1) != 0);
// bit 1: if "1", movie starts from reset with an embedded SRAM
bool startfromsram = ((flags & 2) != 0);
// other: reserved, set to 0
// We can't start from either save option.
if (startfromquicksave || startfromsram)
{
errorMsg = "Movies that begin with a save are not supported.";
// (If both bits 0 and 1 are "1", the movie file is invalid)
if (startfromquicksave && startfromsram)
errorMsg = "The movie file is invalid.";
r.Close();
fs.Close();
return null;
}
//015 1-byte flags: controller flags
flags = r.ReadByte();
// TODO: Handle the additional controllers.
int players = 0;
// bit 0: controller 1 in use
if ((flags & 1) != 0)
players++;
else
{
errorMsg = "Controller 1 must be in use.";
r.Close();
fs.Close();
return null;
}
// bit 1: controller 2 in use (SGB games can be 2-player multiplayer)
if ((flags & 2) != 0)
players++;
// bit 2: controller 3 in use (SGB games can be 3- or 4-player multiplayer with multitap)
if ((flags & 4) != 0)
players++;
// bit 3: controller 4 in use (SGB games can be 3- or 4-player multiplayer with multitap)
if ((flags & 8) != 0)
players++;
// other: reserved
// 016 1-byte flags: system flags (game always runs at 60 frames/sec)
flags = r.ReadByte();
// bit 0: if "1", movie is for the GBA system
bool is_gba = ((flags & 1) != 0);
// bit 1: if "1", movie is for the GBC system
bool is_gbc = ((flags & 2) != 0);
// bit 2: if "1", movie is for the SGB system
bool is_sgb = ((flags & 4) != 0);
// other: reserved, set to 0
// (At most one of bits 0, 1, 2 can be "1")
if (!(is_gba ^ is_gbc ^ is_sgb) && (is_gba || is_gbc || is_sgb))
{
errorMsg = "This is not a valid .VBM file.";
r.Close();
fs.Close();
return null;
}
// (If all 3 of these bits are "0", it is for regular GB.)
string platform = "GB";
if (is_gba)
platform = "GBA";
if (is_gbc)
platform = "GBC";
if (is_sgb)
platform = "SGB";
m.Header.SetHeaderLine(MovieHeader.PLATFORM, platform);
// 017 1-byte flags: (values of some boolean emulator options)
flags = r.ReadByte();
/*
* bit 0: (useBiosFile) if "1" and the movie is of a GBA game, the movie was made using a GBA BIOS file.
* bit 1: (skipBiosFile) if "0" and the movie was made with a GBA BIOS file, the BIOS intro is included in the
* movie.
* bit 2: (rtcEnable) if "1", the emulator "real time clock" feature was enabled.
*/
// bit 3: (unsupported) must be "0" or the movie file is considered invalid (legacy).
if ((flags & 8) != 0)
{
errorMsg = "This is not a valid .VBM file.";
r.Close();
fs.Close();
return null;
}
/*
* bit 4: (lagReduction) if "0" and the movie is of a GBA game, the movie was made using the old excessively
* laggy GBA timing.
* bit 5: (gbcHdma5Fix) if "0" and the movie is of a GBC game, the movie was made using the old buggy HDMA5
* timing.
* bit 6: (echoRAMFix) if "1" and the movie is of a GB, GBC, or SGB game, the movie was made with Echo RAM Fix
* on, otherwise it was made with Echo RAM Fix off.
* bit 7: reserved, set to 0.
*/
/*
018 4-byte little-endian unsigned int: theApp.winSaveType (value of that emulator option)
01C 4-byte little-endian unsigned int: theApp.winFlashSize (value of that emulator option)
020 4-byte little-endian unsigned int: gbEmulatorType (value of that emulator option)
*/
r.ReadBytes(12);
/*
024 12-byte character array: the internal game title of the ROM used while recording, not necessarily
null-terminated (ASCII?)
*/
string gameName = RemoveNull(r.ReadStringFixedAscii(12));
m.Header.SetHeaderLine(MovieHeader.GAMENAME, gameName);
// 030 1-byte unsigned char: minor version/revision number of current VBM version, the latest is "1"
byte minorVersion = r.ReadByte();
m.Header.Comments.Add(MOVIEORIGIN + " .VBM version " + majorVersion + "." + minorVersion);
/*
031 1-byte unsigned char: the internal CRC of the ROM used while recording
032 2-byte little-endian unsigned short: the internal Checksum of the ROM used while recording, or a calculated
CRC16 of the BIOS if GBA
034 4-byte little-endian unsigned int: the Game Code of the ROM used while recording, or the Unit Code if not
GBA
038 4-byte little-endian unsigned int: offset to the savestate or SRAM inside file, set to 0 if unused
*/
r.ReadBytes(11);
// 03C 4-byte little-endian unsigned int: offset to the controller data inside file
uint firstFrameOffset = r.ReadUInt32();
// After the header is 192 bytes of text. The first 64 of these 192 bytes are for the author's name (or names).
string author = RemoveNull(r.ReadStringFixedAscii(64));
m.Header.SetHeaderLine(MovieHeader.AUTHOR, author);
// The following 128 bytes are for a description of the movie. Both parts must be null-terminated.
string movieDescription = RemoveNull(r.ReadStringFixedAscii(128));
m.Header.Comments.Add("comment " + movieDescription);
/*
TODO: implement start data. There are no specifics on the googlecode page as to how long the SRAM or savestate
should be.
*/
// If there is no "Start Data", this will probably begin at byte 0x100 in the file, but this is not guaranteed.
r.BaseStream.Position = firstFrameOffset;
/*
* 01 00 A
* 02 00 B
* 04 00 Select
* 08 00 Start
* 10 00 Right
* 20 00 Left
* 40 00 Up
* 80 00 Down
*/
string[] buttons = new string[8] { "A", "B", "Select", "Start", "Right", "Left", "Up", "Down" };
/*
* 00 01 R
* 00 02 L
* 00 04 Reset (old timing)
* 00 08 Reset (new timing since version 1.1)
* 00 10 Left motion sensor
* 00 20 Right motion sensor
* 00 40 Down motion sensor
* 00 80 Up motion sensor
*/
string[] other = new string[8] {
"R", "L", "Reset (old timing)" , "Reset (new timing since version 1.1)", "Left motion sensor",
"Right motion sensor", "Down motion sensor", "Up motion sensor"
};
for (int frame = 1; frame <= frameCount; frame++)
{
/*
A stream of 2-byte bitvectors which indicate which buttons are pressed at each point in time. They will come
in groups of however many controllers are active, in increasing order.
*/
ushort controllerState = r.ReadUInt16();
SimpleController controllers = new SimpleController();
controllers.Type = new ControllerDefinition();
controllers.Type.Name = "Gameboy Controller";
ushort and = 0x1;
for (int button = 0; button < buttons.Length; button++)
{
controllers[buttons[button]] = ((int)(controllerState & and) != 0);
and <<= 1;
}
MnemonicsGenerator mg = new MnemonicsGenerator();
mg.SetSource(controllers);
m.AppendFrame(mg.GetControllersAsMnemonic());
// TODO: Handle the other buttons.
and = 0x100;
if (warningMsg == "")
{
for (int button = 0; button < other.Length; button++)
{
if ((controllerState & and) != 0)
{
warningMsg = other[button];
break;
}
and <<= 1;
}
if (warningMsg != "")
warningMsg = "Unable to import " + warningMsg + " at frame " + frame + ".";
}
// TODO: Handle the additional controllers.
r.ReadBytes((players - 1) * 2);
}
r.Close();
fs.Close();
return m;
}
// VMV file format: http://tasvideos.org/VMV.html
private static Movie ImportVMV(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
Movie m = new Movie(Path.ChangeExtension(path, ".tas"), MOVIEMODE.PLAY);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
// 000 12-byte signature: "VirtuaNES MV"
string signature = r.ReadStringFixedAscii(12);
if (signature != "VirtuaNES MV")
{
errorMsg = "This is not a valid .VMV file.";
r.Close();
fs.Close();
return null;
}
r.Close();
fs.Close();
return m;
}
}
2012-03-09 09:24:47 +00:00
}