2011-02-24 22:25:53 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
2011-02-25 19:49:29 +00:00
|
|
|
|
using System.IO;
|
2011-02-24 22:25:53 +00:00
|
|
|
|
|
|
|
|
|
namespace BizHawk.MultiClient
|
|
|
|
|
{
|
2011-02-26 21:36:46 +00:00
|
|
|
|
public enum MOVIEMODE { INACTIVE, PLAY, RECORD, FINISHED };
|
2011-03-03 18:25:06 +00:00
|
|
|
|
public class Movie
|
2011-02-24 22:25:53 +00:00
|
|
|
|
{
|
|
|
|
|
private MovieHeader Header = new MovieHeader();
|
|
|
|
|
private MovieLog Log = new MovieLog();
|
|
|
|
|
|
2011-02-25 19:49:29 +00:00
|
|
|
|
private bool IsText = true;
|
|
|
|
|
private string Filename;
|
2011-02-24 22:25:53 +00:00
|
|
|
|
|
2011-02-26 21:36:46 +00:00
|
|
|
|
private MOVIEMODE MovieMode = new MOVIEMODE();
|
|
|
|
|
|
2011-03-03 20:01:36 +00:00
|
|
|
|
public int lastLog;
|
2011-05-12 17:29:34 +00:00
|
|
|
|
public int rerecordCount;
|
2011-03-03 20:01:36 +00:00
|
|
|
|
|
2011-05-10 00:38:20 +00:00
|
|
|
|
//TODO:
|
|
|
|
|
//Author field, needs to be passed in by a record or play dialog
|
|
|
|
|
|
2011-02-28 01:26:38 +00:00
|
|
|
|
public Movie(string filename, MOVIEMODE m)
|
2011-02-25 19:49:29 +00:00
|
|
|
|
{
|
|
|
|
|
Filename = filename; //TODO: Validate that file is writable
|
2011-02-28 01:26:38 +00:00
|
|
|
|
MovieMode = m;
|
2011-03-03 20:01:36 +00:00
|
|
|
|
lastLog = 0;
|
2011-05-12 17:29:34 +00:00
|
|
|
|
rerecordCount = 0;
|
2011-02-26 21:36:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-11 01:47:28 +00:00
|
|
|
|
public string GetFilePath()
|
|
|
|
|
{
|
|
|
|
|
return Filename;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetSysID()
|
|
|
|
|
{
|
|
|
|
|
return Header.GetHeaderLine(MovieHeader.PLATFORM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetGameName()
|
|
|
|
|
{
|
|
|
|
|
return Header.GetHeaderLine(MovieHeader.GAMENAME);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 21:36:46 +00:00
|
|
|
|
public void StopMovie()
|
|
|
|
|
{
|
2011-05-12 16:56:30 +00:00
|
|
|
|
if (MovieMode == MOVIEMODE.RECORD)
|
|
|
|
|
WriteMovie();
|
|
|
|
|
MovieMode = MOVIEMODE.INACTIVE;
|
2011-02-26 21:36:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StartNewRecording()
|
|
|
|
|
{
|
|
|
|
|
MovieMode = MOVIEMODE.RECORD;
|
|
|
|
|
Log.Clear();
|
2011-05-12 17:29:34 +00:00
|
|
|
|
Header = new MovieHeader("BizHawk v1.0.0", MovieHeader.MovieVersion, Global.Emulator.SystemId, Global.Game.Name, "", 0);
|
2011-02-26 21:36:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-27 22:33:25 +00:00
|
|
|
|
public void StartPlayback()
|
|
|
|
|
{
|
|
|
|
|
MovieMode = MOVIEMODE.PLAY;
|
|
|
|
|
//TODO:...something else should be done here
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 21:36:46 +00:00
|
|
|
|
public MOVIEMODE GetMovieMode()
|
|
|
|
|
{
|
|
|
|
|
return MovieMode;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 22:19:46 +00:00
|
|
|
|
public void GetMnemonic()
|
2011-02-26 21:36:46 +00:00
|
|
|
|
{
|
|
|
|
|
if (MovieMode == MOVIEMODE.RECORD)
|
2011-05-08 00:06:43 +00:00
|
|
|
|
Log.AddFrame(Global.ActiveController.GetControllersAsMnemonic());
|
2011-02-24 22:25:53 +00:00
|
|
|
|
}
|
2011-02-27 22:33:25 +00:00
|
|
|
|
|
|
|
|
|
public string GetInputFrame(int frame)
|
|
|
|
|
{
|
2011-03-03 20:01:36 +00:00
|
|
|
|
lastLog = frame;
|
2011-02-27 22:33:25 +00:00
|
|
|
|
if (frame < Log.GetMovieLength())
|
|
|
|
|
return Log.GetFrame(frame);
|
|
|
|
|
else
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2011-02-24 22:25:53 +00:00
|
|
|
|
|
2011-02-26 22:19:46 +00:00
|
|
|
|
//Movie editing tools may like to have something like this
|
|
|
|
|
public void AddMovieRecord(string record)
|
2011-02-24 22:25:53 +00:00
|
|
|
|
{
|
2011-02-26 22:19:46 +00:00
|
|
|
|
Log.AddFrame(record);
|
2011-02-24 22:25:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteMovie()
|
|
|
|
|
{
|
2011-02-25 19:49:29 +00:00
|
|
|
|
if (IsText)
|
|
|
|
|
WriteText();
|
|
|
|
|
else
|
|
|
|
|
WriteBinary();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void WriteText()
|
|
|
|
|
{
|
2011-05-11 01:47:28 +00:00
|
|
|
|
if (Filename.Length == 0) return; //Nothing to write
|
2011-02-25 19:49:29 +00:00
|
|
|
|
int length = Log.GetMovieLength();
|
|
|
|
|
|
|
|
|
|
using (StreamWriter sw = new StreamWriter(Filename))
|
|
|
|
|
{
|
|
|
|
|
foreach (KeyValuePair<string, string> kvp in Header.GetHeaderInfo())
|
|
|
|
|
{
|
2011-03-17 05:30:38 +00:00
|
|
|
|
sw.WriteLine(kvp.Key + " " + kvp.Value);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int x = 0; x < length; x++)
|
|
|
|
|
{
|
2011-03-17 05:30:38 +00:00
|
|
|
|
sw.WriteLine(Log.GetFrame(x));
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void WriteBinary()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-25 22:26:13 +00:00
|
|
|
|
private 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;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-25 19:49:29 +00:00
|
|
|
|
private bool LoadText()
|
|
|
|
|
{
|
|
|
|
|
var file = new FileInfo(Filename);
|
2011-02-25 22:26:13 +00:00
|
|
|
|
|
|
|
|
|
if (file.Exists == false)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Header.Clear();
|
|
|
|
|
Log.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-25 19:49:29 +00:00
|
|
|
|
using (StreamReader sr = file.OpenText())
|
|
|
|
|
{
|
|
|
|
|
string str = "";
|
|
|
|
|
|
|
|
|
|
while ((str = sr.ReadLine()) != null)
|
|
|
|
|
{
|
2011-02-25 22:26:13 +00:00
|
|
|
|
if (str == "")
|
2011-02-25 19:49:29 +00:00
|
|
|
|
{
|
2011-02-25 22:26:13 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.EMULATIONVERSION))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.EMULATIONVERSION);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.EMULATIONVERSION, str);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.MOVIEVERSION))
|
|
|
|
|
{
|
2011-02-25 22:26:13 +00:00
|
|
|
|
str = ParseHeader(str, MovieHeader.MOVIEVERSION);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.MOVIEVERSION, str);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.PLATFORM))
|
|
|
|
|
{
|
2011-02-25 22:26:13 +00:00
|
|
|
|
str = ParseHeader(str, MovieHeader.PLATFORM);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.PLATFORM, str);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.GAMENAME))
|
|
|
|
|
{
|
2011-02-25 22:26:13 +00:00
|
|
|
|
str = ParseHeader(str, MovieHeader.GAMENAME);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.GAMENAME, str);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
2011-05-12 21:00:04 +00:00
|
|
|
|
else if (str.Contains(MovieHeader.RERECORDS))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.RERECORDS);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.RERECORDS, str);
|
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.AUTHOR))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.AUTHOR);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.AUTHOR, str);
|
|
|
|
|
}
|
2011-02-25 19:49:29 +00:00
|
|
|
|
else if (str[0] == '|')
|
|
|
|
|
{
|
2011-05-08 01:00:13 +00:00
|
|
|
|
Log.AddFrame(str);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-05-08 01:00:13 +00:00
|
|
|
|
Header.Comments.Add(str);
|
2011-02-25 19:49:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-24 22:25:53 +00:00
|
|
|
|
|
2011-02-25 19:49:29 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-11 01:47:28 +00:00
|
|
|
|
public bool PreLoadText()
|
|
|
|
|
{
|
|
|
|
|
var file = new FileInfo(Filename);
|
|
|
|
|
|
|
|
|
|
if (file.Exists == false)
|
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Header.Clear();
|
|
|
|
|
Log.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (StreamReader sr = file.OpenText())
|
|
|
|
|
{
|
|
|
|
|
string str = "";
|
|
|
|
|
|
|
|
|
|
while ((str = sr.ReadLine()) != null)
|
|
|
|
|
{
|
|
|
|
|
if (str == "")
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2011-05-12 21:00:04 +00:00
|
|
|
|
//TODO: don't reiterate this entire if chain, make a function called by this and loadmovie
|
2011-05-11 01:47:28 +00:00
|
|
|
|
else if (str.Contains(MovieHeader.EMULATIONVERSION))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.EMULATIONVERSION);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.EMULATIONVERSION, str);
|
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.MOVIEVERSION))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.MOVIEVERSION);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.MOVIEVERSION, str);
|
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.PLATFORM))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.PLATFORM);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.PLATFORM, str);
|
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.GAMENAME))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.GAMENAME);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.GAMENAME, str);
|
|
|
|
|
}
|
2011-05-12 21:00:04 +00:00
|
|
|
|
else if (str.Contains(MovieHeader.RERECORDS))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.RERECORDS);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.RERECORDS, str);
|
|
|
|
|
}
|
|
|
|
|
else if (str.Contains(MovieHeader.AUTHOR))
|
|
|
|
|
{
|
|
|
|
|
str = ParseHeader(str, MovieHeader.AUTHOR);
|
|
|
|
|
Header.AddHeaderLine(MovieHeader.AUTHOR, str);
|
|
|
|
|
}
|
2011-05-11 01:47:28 +00:00
|
|
|
|
else if (str[0] == '|')
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Header.Comments.Add(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2011-05-12 01:33:51 +00:00
|
|
|
|
sr.Close();
|
2011-05-11 01:47:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-25 19:49:29 +00:00
|
|
|
|
private bool LoadBinary()
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool LoadMovie()
|
|
|
|
|
{
|
|
|
|
|
var file = new FileInfo(Filename);
|
|
|
|
|
if (file.Exists == false) return false; //TODO: methods like writemovie will fail, some internal flag needs to prevent this
|
|
|
|
|
//TODO: must determine if file is text or binary
|
|
|
|
|
return LoadText();
|
2011-02-24 22:25:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetMovieLength()
|
|
|
|
|
{
|
|
|
|
|
return Log.GetMovieLength();
|
|
|
|
|
}
|
2011-05-08 12:51:39 +00:00
|
|
|
|
|
|
|
|
|
public void DumpLogIntoSavestateText(TextWriter writer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteLine("[Input]");
|
|
|
|
|
for (int x = 0; x < Log.Length(); x++)
|
|
|
|
|
writer.WriteLine(Log.GetFrame(x));
|
|
|
|
|
writer.WriteLine("[/Input]");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void LoadLogFromSavestateText(TextReader reader)
|
|
|
|
|
{
|
|
|
|
|
Log.Clear();
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
string line = reader.ReadLine();
|
|
|
|
|
if (line.Trim() == "") continue;
|
|
|
|
|
if (line == "[Input]") continue;
|
|
|
|
|
if (line == "[/Input]") break;
|
|
|
|
|
if (line[0] == '|')
|
|
|
|
|
Log.AddFrame(line);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-12 21:00:04 +00:00
|
|
|
|
|
|
|
|
|
public void IncrementRerecordCount()
|
|
|
|
|
{
|
|
|
|
|
rerecordCount++;
|
2011-05-12 21:00:52 +00:00
|
|
|
|
Header.UpdateRerecordCount(rerecordCount);
|
2011-05-12 21:00:04 +00:00
|
|
|
|
}
|
2011-02-24 22:25:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|