From 59173e4e445a243b71101e14fc2ee586b2bd210b Mon Sep 17 00:00:00 2001 From: "andres.delikat" Date: Sun, 12 Jun 2011 14:42:50 +0000 Subject: [PATCH] Some virtual pad progress, virtual pad dumps input into movie file when recording, currently doesn't feed it to the core though (lol). Virtualpad object set up for a nes controller --- BizHawk.MultiClient/MainForm.cs | 5 +- BizHawk.MultiClient/movie/Movie.cs | 1083 +++++++++++++------------ BizHawk.MultiClient/tools/Pad.cs | 74 +- BizHawk.MultiClient/tools/TAStudio.cs | 21 +- 4 files changed, 629 insertions(+), 554 deletions(-) diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index 5454ae4a4b..a81f36f3f6 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -1162,7 +1162,8 @@ namespace BizHawk.MultiClient UnpauseEmulator(); } } - wasPressed = Global.ActiveController.GetControllersAsMnemonic(); + + wasPressed = (TAStudio1.Enabled) ? TAStudio1.GetMnemonic() : Global.ActiveController.GetControllersAsMnemonic(); PressFrameAdvance = false; } else @@ -1236,7 +1237,9 @@ namespace BizHawk.MultiClient Global.ActiveController.MovieMode = false; } else + { Global.ActiveController.SetControllersAsMnemonic(UserMovie.GetInputFrame(Global.Emulator.Frame) + 1); + } } if (UserMovie.GetMovieMode() == MOVIEMODE.FINISHED) diff --git a/BizHawk.MultiClient/movie/Movie.cs b/BizHawk.MultiClient/movie/Movie.cs index f68f7c7caf..6a9cc16682 100644 --- a/BizHawk.MultiClient/movie/Movie.cs +++ b/BizHawk.MultiClient/movie/Movie.cs @@ -6,601 +6,604 @@ using System.IO; namespace BizHawk.MultiClient { - public enum MOVIEMODE { INACTIVE, PLAY, RECORD, FINISHED }; - public class Movie - { - private MovieHeader Header = new MovieHeader(); - private MovieLog Log = new MovieLog(); + public enum MOVIEMODE { INACTIVE, PLAY, RECORD, FINISHED }; + public class Movie + { + private MovieHeader Header = new MovieHeader(); + private MovieLog Log = new MovieLog(); - private bool IsText = true; - private string Filename; + private bool IsText = true; + private string Filename; - private MOVIEMODE MovieMode = new MOVIEMODE(); + private MOVIEMODE MovieMode = new MOVIEMODE(); - public int Frames = 0; - public int lastLog; - public int rerecordCount; + public int Frames = 0; + public int lastLog; + public int rerecordCount; - //TODO: - //Author field, needs to be passed in by a record or play dialog + //TODO: + //Author field, needs to be passed in by a record or play dialog - public Movie(string filename, MOVIEMODE m) - { - Filename = filename; //TODO: Validate that file is writable - MovieMode = m; - lastLog = 0; - rerecordCount = 0; - } + public Movie(string filename, MOVIEMODE m) + { + Filename = filename; //TODO: Validate that file is writable + MovieMode = m; + lastLog = 0; + rerecordCount = 0; + } - public Movie() - { - Filename = ""; //Note: note this must be populated before playing movie - MovieMode = MOVIEMODE.INACTIVE; - } + public Movie() + { + Filename = ""; //Note: note this must be populated before playing movie + MovieMode = MOVIEMODE.INACTIVE; + } - public string GetFilePath() - { - return Filename; - } + public string GetFilePath() + { + return Filename; + } - public string GetSysID() - { - return Header.GetHeaderLine(MovieHeader.PLATFORM); - } + public string GetSysID() + { + return Header.GetHeaderLine(MovieHeader.PLATFORM); + } - public string GetGameName() - { - return Header.GetHeaderLine(MovieHeader.GAMENAME); - } + public string GetGameName() + { + return Header.GetHeaderLine(MovieHeader.GAMENAME); + } - public void StopMovie() - { - if (MovieMode == MOVIEMODE.RECORD) - WriteMovie(); - MovieMode = MOVIEMODE.INACTIVE; - } + public void StopMovie() + { + if (MovieMode == MOVIEMODE.RECORD) + WriteMovie(); + MovieMode = MOVIEMODE.INACTIVE; + } - public void StartNewRecording() - { - MovieMode = MOVIEMODE.RECORD; - Log.Clear(); - Header = new MovieHeader(MainForm.EMUVERSION, MovieHeader.MovieVersion, Global.Emulator.SystemId, Global.Game.Name, "", 0); - } + public void StartNewRecording() + { + MovieMode = MOVIEMODE.RECORD; + Log.Clear(); + Header = new MovieHeader(MainForm.EMUVERSION, MovieHeader.MovieVersion, Global.Emulator.SystemId, Global.Game.Name, "", 0); + } - public void StartPlayback() - { - MovieMode = MOVIEMODE.PLAY; - } + public void StartPlayback() + { + MovieMode = MOVIEMODE.PLAY; + } - public MOVIEMODE GetMovieMode() - { - return MovieMode; - } + public MOVIEMODE GetMovieMode() + { + return MovieMode; + } - public void GetMnemonic() - { - if (MovieMode == MOVIEMODE.RECORD) - { - if (Global.Emulator.Frame < Log.Length()) - { - Log.Truncate(Global.Emulator.Frame); - } - Log.AddFrame(Global.ActiveController.GetControllersAsMnemonic()); - } - } + public void GetMnemonic() + { + if (MovieMode == MOVIEMODE.RECORD) + { + if (Global.Emulator.Frame < Log.Length()) + { + Log.Truncate(Global.Emulator.Frame); + } + if (Global.MainForm.TAStudio1.Engaged) + Log.AddFrame(Global.MainForm.TAStudio1.GetMnemonic()); + else + Log.AddFrame(Global.ActiveController.GetControllersAsMnemonic()); + } + } - public string GetInputFrame(int frame) - { - lastLog = frame; - if (frame < Log.GetMovieLength()) - return Log.GetFrame(frame); - else - return ""; - } + public string GetInputFrame(int frame) + { + lastLog = frame; + if (frame < Log.GetMovieLength()) + return Log.GetFrame(frame); + else + return ""; + } - //Movie editing tools may like to have something like this - public void AddFrame(string record) - { - Log.AddFrame(record); - } + //Movie editing tools may like to have something like this + public void AddFrame(string record) + { + Log.AddFrame(record); + } - public void AddFrameAt(string record, int frame) - { - Log.AddFrameAt(record, frame); - } + public void AddFrameAt(string record, int frame) + { + Log.AddFrameAt(record, frame); + } - public void WriteMovie() - { + public void WriteMovie() + { Directory.CreateDirectory(new FileInfo(Filename).Directory.FullName); - if (IsText) - WriteText(); - else - WriteBinary(); - } + if (IsText) + WriteText(); + else + WriteBinary(); + } - private void WriteText() - { - if (Filename.Length == 0) return; //Nothing to write - int length = Log.GetMovieLength(); - - using (StreamWriter sw = new StreamWriter(Filename)) - { - foreach (KeyValuePair kvp in Header.HeaderParams) - { - sw.WriteLine(kvp.Key + " " + kvp.Value); - } + private void WriteText() + { + if (Filename.Length == 0) return; //Nothing to write + int length = Log.GetMovieLength(); - - for (int x = 0; x < length; x++) - { - sw.WriteLine(Log.GetFrame(x)); - } - } - } + using (StreamWriter sw = new StreamWriter(Filename)) + { + foreach (KeyValuePair kvp in Header.HeaderParams) + { + sw.WriteLine(kvp.Key + " " + kvp.Value); + } - private void WriteBinary() - { - } + for (int x = 0; x < length; x++) + { + sw.WriteLine(Log.GetFrame(x)); + } + } + } - 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; - } + private void WriteBinary() + { - private bool LoadText() - { - 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; - } - 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); - } - else if (str.Contains(MovieHeader.RERECORDS)) - { - str = ParseHeader(str, MovieHeader.RERECORDS); - Header.AddHeaderLine(MovieHeader.RERECORDS, str); - try - { - rerecordCount = int.Parse(str); - } - catch - { - rerecordCount = 0; - } - } - else if (str.Contains(MovieHeader.AUTHOR)) - { - str = ParseHeader(str, MovieHeader.AUTHOR); - Header.AddHeaderLine(MovieHeader.AUTHOR, str); - } - else if (str[0] == '|') - { - Log.AddFrame(str); - } - else - { - Header.Comments.Add(str); - } - } - } + 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; + } - return true; - - } + private bool LoadText() + { + var file = new FileInfo(Filename); - public bool PreLoadText() - { - var file = new FileInfo(Filename); - - if (file.Exists == false) - return false; - else - { - Header.Clear(); - Log.Clear(); - } + if (file.Exists == false) + return false; + else + { + Header.Clear(); + Log.Clear(); + } - using (StreamReader sr = file.OpenText()) - { - string str = ""; - int length = 0; - while ((str = sr.ReadLine()) != null) - { - length += str.Length + 1; - if (str == "") - { - continue; - } - //TODO: don't reiterate this entire if chain, make a function called by this and loadmovie - 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); - } - 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); - } - else if (str[0] == '|') - { - int line = str.Length + 1; - length -= line; - int lines = (int)file.Length - length; - this.Frames = lines / line; - break; - } - else - { - Header.Comments.Add(str); - } - } - sr.Close(); - } - - return true; - }//Also this method is never called, can delete? What is purpose? + using (StreamReader sr = file.OpenText()) + { + string str = ""; - private bool LoadBinary() - { - return true; - } + while ((str = sr.ReadLine()) != null) + { + if (str == "") + { + continue; + } + 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); + } + else if (str.Contains(MovieHeader.RERECORDS)) + { + str = ParseHeader(str, MovieHeader.RERECORDS); + Header.AddHeaderLine(MovieHeader.RERECORDS, str); + try + { + rerecordCount = int.Parse(str); + } + catch + { + rerecordCount = 0; + } + } + else if (str.Contains(MovieHeader.AUTHOR)) + { + str = ParseHeader(str, MovieHeader.AUTHOR); + Header.AddHeaderLine(MovieHeader.AUTHOR, str); + } + else if (str[0] == '|') + { + Log.AddFrame(str); + } + else + { + Header.Comments.Add(str); + } + } + } - 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(); - } + return true; - public int GetMovieLength() - { - return Log.GetMovieLength(); - } + } - 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 bool PreLoadText() + { + var file = new FileInfo(Filename); - public void LoadLogFromSavestateText(TextReader reader) - { - //We are in record mode so replace the movie log with the one from the savestate - Log.Clear(); - while (true) - { - string line = reader.ReadLine(); - if (line == null) break; - if (line.Trim() == "") continue; - if (line == "[Input]") continue; - if (line == "[/Input]") break; - if (line[0] == '|') - Log.AddFrame(line); - } - //TODO: we can truncate the movie down to the current frame now (in case the savestate has a larger input log) - //However, VBA will load it all, then truncate on the next frame, do we want that? - IncrementRerecordCount(); - } + if (file.Exists == false) + return false; + else + { + Header.Clear(); + Log.Clear(); + } - public void IncrementRerecordCount() - { - rerecordCount++; - Header.UpdateRerecordCount(rerecordCount); - } + using (StreamReader sr = file.OpenText()) + { + string str = ""; + int length = 0; + while ((str = sr.ReadLine()) != null) + { + length += str.Length + 1; + if (str == "") + { + continue; + } + //TODO: don't reiterate this entire if chain, make a function called by this and loadmovie + 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); + } + 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); + } + else if (str[0] == '|') + { + int line = str.Length + 1; + length -= line; + int lines = (int)file.Length - length; + this.Frames = lines / line; + break; + } + else + { + Header.Comments.Add(str); + } + } + sr.Close(); + } - public int GetRerecordCount() - { - return rerecordCount; - } + return true; + }//Also this method is never called, can delete? What is purpose? - public Dictionary GetHeaderInfo() - { - return Header.HeaderParams; - } + private bool LoadBinary() + { + return true; + } - public void SetMovieFinished() - { - if (MovieMode == MOVIEMODE.PLAY) - MovieMode = MOVIEMODE.FINISHED; - } + 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(); + } - public void SetHeaderLine(string key, string value) - { - Header.SetHeaderLine(key, value); - } + public int GetMovieLength() + { + return Log.GetMovieLength(); + } - public string GetTime(bool preLoad) - { - string time = ""; - - double seconds; - if (preLoad) - seconds = GetSeconds(Frames); - else - seconds = GetSeconds(Log.Length()); - int hours = ((int)seconds) / 3600; - int minutes = (((int)seconds) / 60) % 60; - double sec = seconds % 60; - if (hours > 0) - time += MakeDigits(hours) + ":"; - time += MakeDigits(minutes) + ":"; - time += Math.Round((decimal)sec, 2).ToString(); - return time; - } + public void DumpLogIntoSavestateText(TextWriter writer) + { + writer.WriteLine("[Input]"); + for (int x = 0; x < Log.Length(); x++) + writer.WriteLine(Log.GetFrame(x)); + writer.WriteLine("[/Input]"); + } - private string MakeDigits(decimal num) - { - if (num < 10) - return "0" + num.ToString(); - else - return num.ToString(); - } + public void LoadLogFromSavestateText(TextReader reader) + { + //We are in record mode so replace the movie log with the one from the savestate + Log.Clear(); + while (true) + { + string line = reader.ReadLine(); + if (line == null) break; + if (line.Trim() == "") continue; + if (line == "[Input]") continue; + if (line == "[/Input]") break; + if (line[0] == '|') + Log.AddFrame(line); + } + //TODO: we can truncate the movie down to the current frame now (in case the savestate has a larger input log) + //However, VBA will load it all, then truncate on the next frame, do we want that? + IncrementRerecordCount(); + } - private string MakeDigits(int num) - { - if (num < 10) - return "0" + num.ToString(); - else - return num.ToString(); - } + public void IncrementRerecordCount() + { + rerecordCount++; + Header.UpdateRerecordCount(rerecordCount); + } - private double GetSeconds(int frameCount) - { //Should these be placed somewhere more accessible? Perhaps as a public dictionary object in MainForm? - const double NES_PAL = 50.006977968268290849; - const double NES_NTSC = (double)60.098813897440515532; - const double PCE = (7159090.90909090 / 455 / 263); //~59.826 - const double SMS_NTSC = (3579545 / 262.0 / 228.0); - const double SMS_PAL = (3546893 / 313.0 / 228.0); - const double NGP = (6144000.0 / (515 * 198)); - const double VBOY = (20000000 / (259 * 384 * 4)); //~50.273 - const double LYNX = 59.8; - const double WSWAN = (3072000.0 / (159 * 256)); - double seconds = 0; - double frames = (double)frameCount; - if (frames < 1) - return seconds; + public int GetRerecordCount() + { + return rerecordCount; + } - bool pal = false; //TODO: pal flag + public Dictionary GetHeaderInfo() + { + return Header.HeaderParams; + } - switch (Header.GetHeaderLine(MovieHeader.PLATFORM)) - { - case "GG": - case "SG": - case "SMS": - if (pal) - return frames / SMS_PAL; - else - return frames / SMS_NTSC; - case "FDS": - case "NES": - case "SNES": - if (pal) - return frames / NES_PAL; - else - return frames / NES_NTSC; - case "PCE": - return frames / PCE; - - //One Day! - case "VBOY": - return frames / VBOY; - case "NGP": - return frames / NGP; - case "LYNX": - return frames / LYNX; - case "WSWAN": - return frames / WSWAN; - //******** + public void SetMovieFinished() + { + if (MovieMode == MOVIEMODE.PLAY) + MovieMode = MOVIEMODE.FINISHED; + } - case "": - default: - if (pal) - return frames / 50.0; - else - return frames / 60.0; - } - } + public void SetHeaderLine(string key, string value) + { + Header.SetHeaderLine(key, value); + } - public int CheckTimeLines(StreamReader reader) - { - //This function will compare the movie data to the savestate movie data to see if they match - //TODO: Will eventually check header data too such as GUI - MovieLog l = new MovieLog(); - string line; - while (true) - { - line = reader.ReadLine(); - if (line.Trim() == "") continue; - else if (line == "[Input]") continue; - else if (line == "[/Input]") break; - else if (line[0] == '|') - l.AddFrame(line); - } + public string GetTime(bool preLoad) + { + string time = ""; - for (int x = 0; x < Log.Length(); x++) - { - string xs = Log.GetFrame(x); - string ys = l.GetFrame(x); - //if (Log.GetFrame(x) != l.GetFrame(x)) - if (xs != ys) - return x; - } - return -1; - } + double seconds; + if (preLoad) + seconds = GetSeconds(Frames); + else + seconds = GetSeconds(Log.Length()); + int hours = ((int)seconds) / 3600; + int minutes = (((int)seconds) / 60) % 60; + double sec = seconds % 60; + if (hours > 0) + time += MakeDigits(hours) + ":"; + time += MakeDigits(minutes) + ":"; + time += Math.Round((decimal)sec, 2).ToString(); + return time; + } - public int CompareTo(Movie Other, string parameter) - { - int compare = 0; - if (parameter == "File") - { - compare = CompareFileName(Other); - if (compare == 0) - { - compare = CompareSysID(Other); - if (compare == 0) - { - compare = CompareGameName(Other); - if (compare == 0) - compare = CompareLength(Other); - } - } - } - else if (parameter == "SysID") - { - compare = CompareSysID(Other); - if (compare == 0) - { - compare = CompareFileName(Other); - if (compare == 0) - { - compare = CompareGameName(Other); - if (compare == 0) - compare = CompareLength(Other); - } - } - } - else if (parameter == "Game") - { - compare = CompareGameName(Other); - if (compare == 0) - { - compare = CompareFileName(Other); - if (compare == 0) - { - compare = CompareSysID(Other); - if (compare == 0) - compare = CompareLength(Other); - } - } - } - else if (parameter == "Length") - { - compare = CompareLength(Other); - if (compare == 0) - { - compare = CompareFileName(Other); - if (compare == 0) - { - compare = CompareSysID(Other); - if (compare == 0) - compare = CompareGameName(Other); - } - } - } - return compare; - } + private string MakeDigits(decimal num) + { + if (num < 10) + return "0" + num.ToString(); + else + return num.ToString(); + } - private int CompareFileName(Movie Other) - { - string otherName = Path.GetFileName(Other.GetFilePath()); - string thisName = Path.GetFileName(this.Filename); + private string MakeDigits(int num) + { + if (num < 10) + return "0" + num.ToString(); + else + return num.ToString(); + } - return thisName.CompareTo(otherName); - } + private double GetSeconds(int frameCount) + { //Should these be placed somewhere more accessible? Perhaps as a public dictionary object in MainForm? + const double NES_PAL = 50.006977968268290849; + const double NES_NTSC = (double)60.098813897440515532; + const double PCE = (7159090.90909090 / 455 / 263); //~59.826 + const double SMS_NTSC = (3579545 / 262.0 / 228.0); + const double SMS_PAL = (3546893 / 313.0 / 228.0); + const double NGP = (6144000.0 / (515 * 198)); + const double VBOY = (20000000 / (259 * 384 * 4)); //~50.273 + const double LYNX = 59.8; + const double WSWAN = (3072000.0 / (159 * 256)); + double seconds = 0; + double frames = (double)frameCount; + if (frames < 1) + return seconds; - private int CompareSysID(Movie Other) - { - string otherSysID = Other.GetSysID(); - string thisSysID = this.GetSysID(); + bool pal = false; //TODO: pal flag - if (thisSysID == null && otherSysID == null) - return 0; - else if (thisSysID == null) - return -1; - else if (otherSysID == null) - return 1; - else - return thisSysID.CompareTo(otherSysID); - } + switch (Header.GetHeaderLine(MovieHeader.PLATFORM)) + { + case "GG": + case "SG": + case "SMS": + if (pal) + return frames / SMS_PAL; + else + return frames / SMS_NTSC; + case "FDS": + case "NES": + case "SNES": + if (pal) + return frames / NES_PAL; + else + return frames / NES_NTSC; + case "PCE": + return frames / PCE; - private int CompareGameName(Movie Other) - { - string otherGameName = Other.GetGameName(); - string thisGameName = this.GetGameName(); + //One Day! + case "VBOY": + return frames / VBOY; + case "NGP": + return frames / NGP; + case "LYNX": + return frames / LYNX; + case "WSWAN": + return frames / WSWAN; + //******** - if (thisGameName == null && otherGameName == null) - return 0; - else if (thisGameName == null) - return -1; - else if (otherGameName == null) - return 1; - else - return thisGameName.CompareTo(otherGameName); - } + case "": + default: + if (pal) + return frames / 50.0; + else + return frames / 60.0; + } + } - private int CompareLength(Movie Other) - { - int otherLength = Other.Frames; - int thisLength = this.Frames; + public int CheckTimeLines(StreamReader reader) + { + //This function will compare the movie data to the savestate movie data to see if they match + //TODO: Will eventually check header data too such as GUI + MovieLog l = new MovieLog(); + string line; + while (true) + { + line = reader.ReadLine(); + if (line.Trim() == "") continue; + else if (line == "[Input]") continue; + else if (line == "[/Input]") break; + else if (line[0] == '|') + l.AddFrame(line); + } - if (thisLength < otherLength) - return -1; - else if (thisLength > otherLength) - return 1; - else - return 0; - } - } + for (int x = 0; x < Log.Length(); x++) + { + string xs = Log.GetFrame(x); + string ys = l.GetFrame(x); + //if (Log.GetFrame(x) != l.GetFrame(x)) + if (xs != ys) + return x; + } + return -1; + } + + public int CompareTo(Movie Other, string parameter) + { + int compare = 0; + if (parameter == "File") + { + compare = CompareFileName(Other); + if (compare == 0) + { + compare = CompareSysID(Other); + if (compare == 0) + { + compare = CompareGameName(Other); + if (compare == 0) + compare = CompareLength(Other); + } + } + } + else if (parameter == "SysID") + { + compare = CompareSysID(Other); + if (compare == 0) + { + compare = CompareFileName(Other); + if (compare == 0) + { + compare = CompareGameName(Other); + if (compare == 0) + compare = CompareLength(Other); + } + } + } + else if (parameter == "Game") + { + compare = CompareGameName(Other); + if (compare == 0) + { + compare = CompareFileName(Other); + if (compare == 0) + { + compare = CompareSysID(Other); + if (compare == 0) + compare = CompareLength(Other); + } + } + } + else if (parameter == "Length") + { + compare = CompareLength(Other); + if (compare == 0) + { + compare = CompareFileName(Other); + if (compare == 0) + { + compare = CompareSysID(Other); + if (compare == 0) + compare = CompareGameName(Other); + } + } + } + return compare; + } + + private int CompareFileName(Movie Other) + { + string otherName = Path.GetFileName(Other.GetFilePath()); + string thisName = Path.GetFileName(this.Filename); + + return thisName.CompareTo(otherName); + } + + private int CompareSysID(Movie Other) + { + string otherSysID = Other.GetSysID(); + string thisSysID = this.GetSysID(); + + if (thisSysID == null && otherSysID == null) + return 0; + else if (thisSysID == null) + return -1; + else if (otherSysID == null) + return 1; + else + return thisSysID.CompareTo(otherSysID); + } + + private int CompareGameName(Movie Other) + { + string otherGameName = Other.GetGameName(); + string thisGameName = this.GetGameName(); + + if (thisGameName == null && otherGameName == null) + return 0; + else if (thisGameName == null) + return -1; + else if (otherGameName == null) + return 1; + else + return thisGameName.CompareTo(otherGameName); + } + + private int CompareLength(Movie Other) + { + int otherLength = Other.Frames; + int thisLength = this.Frames; + + if (thisLength < otherLength) + return -1; + else if (thisLength > otherLength) + return 1; + else + return 0; + } + } } diff --git a/BizHawk.MultiClient/tools/Pad.cs b/BizHawk.MultiClient/tools/Pad.cs index 28a02c2fc9..13921bf98f 100644 --- a/BizHawk.MultiClient/tools/Pad.cs +++ b/BizHawk.MultiClient/tools/Pad.cs @@ -10,6 +10,10 @@ namespace BizHawk.MultiClient { public class VirtualPad : Panel { + public enum ControllerType { NES, SMS, PCE } + Point[] NESPoints = new Point[8]; + public ControllerType Controller; + public CheckBox PU; public CheckBox PD; public CheckBox PL; @@ -18,9 +22,23 @@ namespace BizHawk.MultiClient public CheckBox B2; public CheckBox B3; public CheckBox B4; + public CheckBox B5; + public CheckBox B6; + public CheckBox B7; + public CheckBox B8; public VirtualPad() { + Controller = ControllerType.NES; //Default + NESPoints[0] = new Point(14, 2); + NESPoints[1] = new Point(14, 46); + NESPoints[2] = new Point(2, 24); + NESPoints[3] = new Point(24, 24); + NESPoints[4] = new Point(52, 24); + NESPoints[5] = new Point(74, 24); + NESPoints[6] = new Point(122, 24); + NESPoints[7] = new Point(146, 24); + SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.DoubleBuffer, true); @@ -35,7 +53,7 @@ namespace BizHawk.MultiClient this.PU.AutoSize = true; this.PU.Image = global::BizHawk.MultiClient.Properties.Resources.BlueUp; this.PU.ImageAlign = System.Drawing.ContentAlignment.BottomRight; - this.PU.Location = new System.Drawing.Point(14, 2); + this.PU.Location = NESPoints[0]; this.PU.TabIndex = 1; this.PU.UseVisualStyleBackColor = true; ; @@ -44,7 +62,7 @@ namespace BizHawk.MultiClient this.PD.AutoSize = true; this.PD.Image = global::BizHawk.MultiClient.Properties.Resources.BlueDown; this.PD.ImageAlign = System.Drawing.ContentAlignment.BottomRight; - this.PD.Location = new System.Drawing.Point(14, 46); + this.PD.Location = NESPoints[1]; this.PD.TabIndex = 4; this.PD.UseVisualStyleBackColor = true; @@ -53,7 +71,7 @@ namespace BizHawk.MultiClient this.PR.AutoSize = true; this.PR.Image = global::BizHawk.MultiClient.Properties.Resources.Forward; this.PR.ImageAlign = System.Drawing.ContentAlignment.BottomRight; - this.PR.Location = new System.Drawing.Point(24, 24); + this.PR.Location = NESPoints[3]; this.PR.TabIndex = 3; this.PR.UseVisualStyleBackColor = true; @@ -62,14 +80,14 @@ namespace BizHawk.MultiClient this.PL.AutoSize = true; this.PL.Image = global::BizHawk.MultiClient.Properties.Resources.Back; this.PL.ImageAlign = System.Drawing.ContentAlignment.BottomRight; - this.PL.Location = new System.Drawing.Point(2, 24); + this.PL.Location = NESPoints[2]; this.PL.TabIndex = 2; this.PL.UseVisualStyleBackColor = true; this.B1 = new CheckBox(); this.B1.Appearance = System.Windows.Forms.Appearance.Button; this.B1.AutoSize = true; - this.B1.Location = new System.Drawing.Point(52, 24); + this.B1.Location = NESPoints[4]; this.B1.TabIndex = 5; this.B1.Text = "s"; this.B1.TextAlign = System.Drawing.ContentAlignment.BottomCenter; @@ -78,7 +96,7 @@ namespace BizHawk.MultiClient this.B2 = new CheckBox(); this.B2.Appearance = System.Windows.Forms.Appearance.Button; this.B2.AutoSize = true; - this.B2.Location = new System.Drawing.Point(74, 24); + this.B2.Location = NESPoints[5]; this.B2.TabIndex = 6; this.B2.Text = "S"; this.B2.TextAlign = System.Drawing.ContentAlignment.BottomCenter; @@ -87,7 +105,7 @@ namespace BizHawk.MultiClient this.B3 = new CheckBox(); this.B3.Appearance = System.Windows.Forms.Appearance.Button; this.B3.AutoSize = true; - this.B3.Location = new System.Drawing.Point(122, 24); + this.B3.Location = NESPoints[6]; this.B3.TabIndex = 7; this.B3.Text = "B"; this.B3.TextAlign = System.Drawing.ContentAlignment.BottomCenter; @@ -96,7 +114,7 @@ namespace BizHawk.MultiClient this.B4 = new CheckBox(); this.B4.Appearance = System.Windows.Forms.Appearance.Button; this.B4.AutoSize = true; - this.B4.Location = new System.Drawing.Point(146, 24); + this.B4.Location = NESPoints[7]; this.B4.TabIndex = 8; this.B4.Text = "A"; this.B4.TextAlign = System.Drawing.ContentAlignment.BottomCenter; @@ -142,5 +160,45 @@ namespace BizHawk.MultiClient { } + + public string GetMnemonic() + { + switch (Controller) + { + default: + case ControllerType.NES: + return GetMnemonicNES(); + case ControllerType.PCE: + return GetMnemonicPCE(); + case ControllerType.SMS: + return GetMnemonicSMS(); + } + } + + public string GetMnemonicNES() + { + StringBuilder input = new StringBuilder("|0|"); //TODO: Reset button + input.Append(PR.Checked ? "R" : "."); + input.Append(PL.Checked ? "L" : "."); + input.Append(PD.Checked ? "D" : "."); + input.Append(PU.Checked ? "U" : "."); + + input.Append(B2.Checked ? "S" : "."); + input.Append(B1.Checked ? "s" : "."); + input.Append(B3.Checked ? "B" : "."); + input.Append(B4.Checked ? "A" : "."); + input.Append("|"); + return input.ToString(); + } + + private string GetMnemonicPCE() + { + return ""; + } + + private string GetMnemonicSMS() + { + return ""; + } } } diff --git a/BizHawk.MultiClient/tools/TAStudio.cs b/BizHawk.MultiClient/tools/TAStudio.cs index e9969fc60f..5c3b4572a9 100644 --- a/BizHawk.MultiClient/tools/TAStudio.cs +++ b/BizHawk.MultiClient/tools/TAStudio.cs @@ -13,6 +13,8 @@ namespace BizHawk.MultiClient { int defaultWidth; //For saving the default size of the dialog, so the user can restore if desired int defaultHeight; + + public bool Engaged; //When engaged the Client will listen to TAStudio for input public TAStudio() { @@ -28,6 +30,14 @@ namespace BizHawk.MultiClient DisplayList(); } + public string GetMnemonic() + { + StringBuilder str = new StringBuilder(""); + str.Append(Pad1.GetMnemonic()); + //Loop through active controllers and append string data + return str.ToString(); + } + private void TASView_QueryItemBkColor(int index, int column, ref Color color) { if (index == Global.Emulator.Frame) @@ -51,6 +61,12 @@ namespace BizHawk.MultiClient private void TAStudio_Load(object sender, EventArgs e) { + //TODO: don't engage until new/open project + // + Engaged = true; + Global.RenderPanel.AddMessage("TAStudio engaged"); + // + LoadConfigSettings(); ReadOnlyCheckBox.Checked = Global.MainForm.ReadOnly; DisplayList(); @@ -170,10 +186,5 @@ namespace BizHawk.MultiClient if (Global.MainForm.ReadOnly) return; } - - private void Pad1_Paint(object sender, PaintEventArgs e) - { - - } } }