Finish up Movie Header refactor

This commit is contained in:
adelikat 2013-11-30 02:20:34 +00:00
parent ec11efb784
commit 4cb01d8ed4
13 changed files with 464 additions and 473 deletions

View File

@ -132,6 +132,7 @@
<Compile Include="movie\MovieMnemonics.cs" />
<Compile Include="movie\MovieSession.cs" />
<Compile Include="movie\MultitrackRecording.cs" />
<Compile Include="movie\PlatformFrameRates.cs" />
<Compile Include="movie\Subtitle.cs" />
<Compile Include="movie\SubtitleList.cs" />
<Compile Include="NESGameGenieEncoderDecoder.cs" />

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace BizHawk.Client.Common
{
@ -24,36 +21,30 @@ namespace BizHawk.Client.Common
public const string PAL = "PAL";
public const string BOARDNAME = "BoardName";
//Gameboy Settings that affect sync
// Gameboy Settings that affect sync
public const string GB_FORCEDMG = "Force_DMG_Mode";
public const string GB_GBA_IN_CGB = "GBA_In_CGB";
public const string SGB = "SGB"; //a snes movie will set this to indicate that it's actually SGB
public const string SGB = "SGB"; // A snes movie will set this to indicate that it's actually SGB
//BIO skipping setting (affects sync)
// BIO skipping setting (affects sync)
public const string SKIPBIOS = "Skip_Bios";
//Plugin Settings
// Plugin Settings
public const string VIDEOPLUGIN = "VideoPlugin";
//Board properties
// Board properties
public const string BOARDPROPERTIES = "BoardProperty";
public static string NewGuid
{
get
{
return Guid.NewGuid().ToString();
}
get { return Guid.NewGuid().ToString(); }
}
public static bool Contains(string val)
{
var keys = new List<string>();
foreach (FieldInfo field in typeof(HeaderKeys).GetFields())
{
keys.Add(field.GetValue(null).ToString());
}
var keys = typeof(HeaderKeys).GetFields()
.Select(field => field.GetValue(null).ToString())
.ToList();
return keys.Contains(val);
}
}

View File

@ -16,9 +16,8 @@ namespace BizHawk.Client.Common
bool IsFinished { get; }
bool Changes { get; }
bool Loaded { get; }
bool StartsFromSavestate { get; }
int Rerecords { get; set; }
ulong Rerecords { get; set; }
#endregion
@ -35,14 +34,13 @@ namespace BizHawk.Client.Common
/// <summary>
/// Tells the movie to start recording from the beginning.
/// This will clear sram, and the movie log
/// This will clear SRAM, and the movie log
/// </summary>
/// <param name="truncate"></param>
void StartNewRecording();
/// <summary>
/// Tells the movie to start playback from the beginning
/// This will clear sram
/// This will clear SRAM
/// </summary>
void StartNewPlayback();
@ -50,18 +48,18 @@ namespace BizHawk.Client.Common
/// Sets the movie to inactive (note that it will still be in memory)
/// The saveChanges flag will tell the movie to save its contents to disk
/// </summary>
/// <param name="saveChanges"></param>
/// <param name="saveChanges">if true, will save to disk</param>
void Stop(bool saveChanges = true);
/// <summary>
/// Switches to record mode
/// Does not change the movie log or clear sram
/// Does not change the movie log or clear SRAM
/// </summary>
void SwitchToRecord();
/// <summary>
/// Switches to playback mode
/// Does not change the movie log or clear sram
/// Does not change the movie log or clear SRAM
/// </summary>
void SwitchToPlay();
@ -93,7 +91,6 @@ namespace BizHawk.Client.Common
IMovieHeader Header { get; } // Expose IMovieHEader instead
MovieLog LogDump { get; } // Don't expose this!!!
//SubtitleList Subtitles { get; } // Don't expose this!!!
#endregion
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace BizHawk.Client.Common
{
@ -9,27 +6,20 @@ namespace BizHawk.Client.Common
{
SubtitleList Subtitles { get; }
Dictionary<string, string> BoardProperties { get; }
List<string> Comments { get; }
#region Dubious, should reconsider
List<string> Comments { get; } // Consider making this a readonly list, or custom object, to control editing api
Dictionary<string, string> Parameters { get; } //rename to Parameters, make a custom object, that controls what params are valid
ulong Rerecords { get; set; }
bool StartsFromSavestate { get; set; }
/// <summary>
/// Adds the key value pair to header params. If key already exists, value will be updated
/// Receives a line and attempts to add as a header
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
void AddHeaderLine(string key, string value); // delete in favor of AddHeaderFromLine
//TODO: replace Movie Preload & Load functions with this
/// <summary>
/// Receives a line and attempts to add as a header, returns false if not a useable header line
/// </summary>
/// <param name="line"></param>
/// <returns></returns>
bool AddHeaderFromLine(string line); // rename to AddFromString, should be a property of HeaderParams
#endregion
/// <param name="line">
/// The line of text loaded from a movie file.
/// </param>
/// <returns>
/// returns false if not a useable header line
/// </returns>
bool ParseLineFromFile(string line);
}
}

View File

@ -1,9 +1,10 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using System.Collections.Generic;
namespace BizHawk.Client.Common
{
@ -24,7 +25,8 @@ namespace BizHawk.Client.Common
Header = new MovieHeader();
Filename = String.Empty;
_preloadFramecount = 0;
StartsFromSavestate = startsFromSavestate;
Header.StartsFromSavestate = startsFromSavestate;
IsCountingRerecords = true;
_mode = Moviemode.Inactive;
IsText = true;
@ -43,24 +45,20 @@ namespace BizHawk.Client.Common
public bool Loaded { get; private set; }
public bool IsText { get; private set; }
public int Rerecords
public ulong Rerecords
{
get { return _rerecords; }
set
{
_rerecords = value;
Header.Parameters[HeaderKeys.RERECORDS] = Rerecords.ToString();
}
get { return Header.Rerecords; }
set { Header.Rerecords = value; }
}
public string SysID
{
get { return Header.Parameters[HeaderKeys.PLATFORM]; }
get { return Header[HeaderKeys.PLATFORM]; }
}
public string GameName
{
get { return Header.Parameters[HeaderKeys.GAMENAME]; }
get { return Header[HeaderKeys.GAMENAME]; }
}
public int RawFrames
@ -90,26 +88,13 @@ namespace BizHawk.Client.Common
}
}
public bool StartsFromSavestate
{
get { return _startsfromsavestate; }
private set
{
_startsfromsavestate = value;
if (value)
{
Header.AddHeaderLine(HeaderKeys.STARTSFROMSAVESTATE, "1");
}
else
{
Header.Parameters.Remove(HeaderKeys.STARTSFROMSAVESTATE);
}
}
}
public bool StateCapturing
{
get { return _statecapturing; }
get
{
return _statecapturing;
}
set
{
_statecapturing = value;
@ -157,6 +142,7 @@ namespace BizHawk.Client.Common
SaveAs();
MakeBackup = false;
}
_log.Clear();
}
@ -186,6 +172,7 @@ namespace BizHawk.Client.Common
Save();
}
}
_changes = false;
_mode = Moviemode.Inactive;
}
@ -211,9 +198,13 @@ namespace BizHawk.Client.Common
{
return;
}
var directory_info = new FileInfo(Filename).Directory;
if (directory_info != null) Directory.CreateDirectory(directory_info.FullName);
if (directory_info != null)
{
Directory.CreateDirectory(directory_info.FullName);
}
if (IsText)
{
WriteText(Filename);
@ -242,61 +233,64 @@ namespace BizHawk.Client.Common
return;
}
string BackupName = Filename;
BackupName = BackupName.Insert(Filename.LastIndexOf("."), String.Format(".{0:yyyy-MM-dd HH.mm.ss}", DateTime.Now));
BackupName = Path.Combine(Global.Config.PathEntries["Global", "Movie backups"].Path, Path.GetFileName(BackupName) ?? String.Empty);
var backupName = Filename;
backupName = backupName.Insert(Filename.LastIndexOf("."), String.Format(".{0:yyyy-MM-dd HH.mm.ss}", DateTime.Now));
backupName = Path.Combine(Global.Config.PathEntries["Global", "Movie backups"].Path, Path.GetFileName(backupName) ?? String.Empty);
var directory_info = new FileInfo(BackupName).Directory;
if (directory_info != null) Directory.CreateDirectory(directory_info.FullName);
var directory_info = new FileInfo(backupName).Directory;
if (directory_info != null)
{
Directory.CreateDirectory(directory_info.FullName);
}
if (IsText)
{
WriteText(BackupName);
WriteText(backupName);
}
else
{
WriteBinary(BackupName);
WriteBinary(backupName);
}
}
/// <summary>
/// Load Header information only for displaying file information in dialogs such as play movie
/// </summary>
/// <returns></returns>
public bool PreLoadText(HawkFile hawkFile)
{
Loaded = false;
var file = new FileInfo(hawkFile.CanonicalFullPath);
if (file.Exists == false)
{
return false;
}
else
{
Header.Clear();
_log.Clear();
}
long origStreamPosn = hawkFile.GetStream().Position;
hawkFile.GetStream().Position = 0; //Reset to start
StreamReader sr = new StreamReader(hawkFile.GetStream()); //No using block because we're sharing the stream and need to give it back undisposed.
if(!sr.EndOfStream)
var origStreamPosn = hawkFile.GetStream().Position;
hawkFile.GetStream().Position = 0; // Reset to start
var sr = new StreamReader(hawkFile.GetStream());
// No using block because we're sharing the stream and need to give it back undisposed.
if (!sr.EndOfStream)
{
string str;
while ((str = sr.ReadLine()) != null)
string line;
while ((line = sr.ReadLine()) != null)
{
if (String.IsNullOrWhiteSpace(str) || Header.AddHeaderFromLine(str))
if (String.IsNullOrWhiteSpace(line) || Header.ParseLineFromFile(line))
{
continue;
}
if (str.StartsWith("subtitle") || str.StartsWith("sub"))
if (line.StartsWith("|"))
{
Header.Subtitles.AddFromString(str);
}
else if (str[0] == '|')
{
string frames = sr.ReadToEnd();
int length = str.Length;
var frames = sr.ReadToEnd();
var length = line.Length;
// Account for line breaks of either size.
if (frames.IndexOf("\r\n") != -1)
{
@ -304,16 +298,16 @@ namespace BizHawk.Client.Common
}
length++;
// Count the remaining frames and the current one.
_preloadFramecount = (frames.Length/length) + 1;
_preloadFramecount = (frames.Length / length) + 1; // Count the remaining frames and the current one.
break;
}
else
{
Header.Comments.Add(str);
Header.Comments.Add(line);
}
}
}
hawkFile.GetStream().Position = origStreamPosn;
return true;
@ -433,19 +427,19 @@ namespace BizHawk.Client.Common
public void CommitFrame(int frameNum, IController source)
{
//Note: Truncation here instead of loadstate will make VBA style loadstates
//(Where an entire movie is loaded then truncated on the next frame
//this allows users to restore a movie with any savestate from that "timeline"
// Note: Truncation here instead of loadstate will make VBA style loadstates
// (Where an entire movie is loaded then truncated on the next frame
// this allows users to restore a movie with any savestate from that "timeline"
if (Global.Config.VBAStyleMovieLoadState)
{
if (Global.Emulator.Frame < _log.Length)
{
_log.TruncateMovie(Global.Emulator.Frame);
_log .TruncateStates(Global.Emulator.Frame);
}
}
_changes = true;
MnemonicsGenerator mg = new MnemonicsGenerator();
var mg = new MnemonicsGenerator();
mg.SetSource(source);
_log.SetFrameAt(frameNum, mg.GetControllersAsMnemonic());
}
@ -453,11 +447,11 @@ namespace BizHawk.Client.Common
public void DumpLogIntoSavestateText(TextWriter writer)
{
writer.WriteLine("[Input]");
writer.WriteLine(HeaderKeys.GUID + " " + Header.Parameters[HeaderKeys.GUID]);
writer.WriteLine(HeaderKeys.GUID + " " + Header[HeaderKeys.GUID]);
for (int x = 0; x < _log.Length; x++)
for (var i = 0; i < _log.Length; i++)
{
writer.WriteLine(_log[x]);
writer.WriteLine(_log[i]);
}
writer.WriteLine("[/Input]");
@ -466,7 +460,8 @@ namespace BizHawk.Client.Common
public void LoadLogFromSavestateText(TextReader reader, bool isMultitracking)
{
int? stateFrame = null;
//We are in record mode so replace the movie log with the one from the savestate
// We are in record mode so replace the movie log with the one from the savestate
if (!isMultitracking)
{
if (Global.Config.EnableBackupMovies && MakeBackup && _log.Length > 0)
@ -474,26 +469,39 @@ namespace BizHawk.Client.Common
SaveAs();
MakeBackup = false;
}
_log.Clear();
while (true)
{
string line = reader.ReadLine();
if (line == null) break;
else if (line.Trim() == "") continue;
else if (line == "[Input]") continue;
else if (line == "[/Input]") break;
else if (line.Contains("Frame 0x")) //NES stores frame count in hex, yay
var line = reader.ReadLine();
if (line == null)
{
string[] strs = line.Split('x');
break;
}
else if (line.Trim() == String.Empty)
{
continue;
}
else if (line == "[Input]")
{
continue;
}
else if (line == "[/Input]")
{
break;
}
else if (line.Contains("Frame 0x")) // NES stores frame count in hex, yay
{
var strs = line.Split('x');
try
{
stateFrame = int.Parse(strs[1], NumberStyles.HexNumber);
}
catch { } //TODO: message?
catch { } // TODO: message?
}
else if (line.Contains("Frame "))
{
string[] strs = line.Split(' ');
var strs = line.Split(' ');
try
{
stateFrame = int.Parse(strs[1]);
@ -511,39 +519,55 @@ namespace BizHawk.Client.Common
int i = 0;
while (true)
{
string line = reader.ReadLine();
if (line == null) break;
else if (line.Trim() == "") continue;
else if (line == "[Input]") continue;
else if (line == "[/Input]") break;
else if (line.Contains("Frame 0x")) //NES stores frame count in hex, yay
var line = reader.ReadLine();
if (line == null)
{
string[] strs = line.Split('x');
break;
}
else if (line.Trim() == string.Empty)
{
continue;
}
else if (line == "[Input]")
{
continue;
}
else if (line == "[/Input]")
{
break;
}
else if (line.Contains("Frame 0x")) // NES stores frame count in hex, yay
{
var strs = line.Split('x');
try
{
stateFrame = int.Parse(strs[1], NumberStyles.HexNumber);
}
catch { } //TODO: message?
catch { } // TODO: message?
}
else if (line.Contains("Frame "))
{
string[] strs = line.Split(' ');
var strs = line.Split(' ');
try
{
stateFrame = int.Parse(strs[1]);
}
catch { } //TODO: message?
catch { } // TODO: message?
}
if (line[0] == '|')
else if (line.StartsWith("|"))
{
_log.SetFrameAt(i, line);
i++;
}
}
}
if (stateFrame == null)
{
throw new Exception("Couldn't find stateFrame");
int stateFramei = (int)stateFrame;
}
var stateFramei = (int)stateFrame;
if (stateFramei > 0 && stateFramei < _log.Length)
{
@ -553,32 +577,28 @@ namespace BizHawk.Client.Common
_log.TruncateMovie(stateFramei);
}
}
else if (stateFramei > _log.Length) //Post movie savestate
else if (stateFramei > _log.Length) // Post movie savestate
{
if (!Global.Config.VBAStyleMovieLoadState)
{
_log.TruncateStates(_log.Length);
_log.TruncateMovie(_log.Length);
}
_mode = Moviemode.Finished;
}
if (IsCountingRerecords)
{
Rerecords++;
}
}
public string GetTime(bool preLoad)
{
string time = String.Empty;
var time = String.Empty;
double seconds;
if (preLoad)
{
seconds = GetSeconds(_preloadFramecount);
}
else
{
seconds = GetSeconds(_log.Length);
}
double seconds = GetSeconds(preLoad ? _preloadFramecount : _log.Length);
int hours = ((int)seconds) / 3600;
int minutes = (((int)seconds) / 60) % 60;
@ -590,7 +610,7 @@ namespace BizHawk.Client.Common
time += MakeDigits(minutes) + ":";
if (sec < 10) //Kludge
if (sec < 10) // Kludge
{
time += "0";
}
@ -602,25 +622,25 @@ namespace BizHawk.Client.Common
public LoadStateResult CheckTimeLines(TextReader reader, bool onlyGuid, bool ignoreGuidMismatch, out string errorMessage)
{
//This function will compare the movie data to the savestate movie data to see if they match
// This function will compare the movie data to the savestate movie data to see if they match
errorMessage = String.Empty;
var log = new MovieLog();
int stateFrame = 0;
while (true)
{
string line = reader.ReadLine();
var line = reader.ReadLine();
if (line == null)
{
return LoadStateResult.EmptyLog;
}
else if (line.Trim() == "")
else if (line.Trim() == string.Empty)
{
continue;
}
else if (line.Contains("GUID"))
{
string guid = ParseHeader(line, HeaderKeys.GUID);
if (Header.Parameters[HeaderKeys.GUID] != guid)
var guid = line.Split(new[] { ' ' }, 2)[1];
if (Header[HeaderKeys.GUID] != guid)
{
if (!ignoreGuidMismatch)
{
@ -628,9 +648,9 @@ namespace BizHawk.Client.Common
}
}
}
else if (line.Contains("Frame 0x")) //NES stores frame count in hex, yay
else if (line.Contains("Frame 0x")) // NES stores frame count in hex, yay
{
string[] strs = line.Split('x');
var strs = line.Split('x');
try
{
stateFrame = int.Parse(strs[1], NumberStyles.HexNumber);
@ -643,7 +663,7 @@ namespace BizHawk.Client.Common
}
else if (line.Contains("Frame "))
{
string[] strs = line.Split(' ');
var strs = line.Split(' ');
try
{
stateFrame = int.Parse(strs[1]);
@ -654,8 +674,14 @@ namespace BizHawk.Client.Common
return LoadStateResult.MissingFrameNumber;
}
}
else if (line == "[Input]") continue;
else if (line == "[/Input]") break;
else if (line == "[Input]")
{
continue;
}
else if (line == "[/Input]")
{
break;
}
else if (line[0] == '|')
{
log.AppendFrame(line);
@ -669,8 +695,9 @@ namespace BizHawk.Client.Common
if (stateFrame == 0)
{
stateFrame = log.Length; //In case the frame count failed to parse, revert to using the entire state input log
stateFrame = log.Length; // In case the frame count failed to parse, revert to using the entire state input log
}
if (_log.Length < stateFrame)
{
if (IsFinished)
@ -680,24 +707,25 @@ namespace BizHawk.Client.Common
else
{
errorMessage = "The savestate is from frame "
+ log.Length.ToString()
+ log.Length
+ " which is greater than the current movie length of "
+ _log.Length.ToString();
+ _log.Length;
return LoadStateResult.FutureEventError;
}
}
for (int i = 0; i < stateFrame; i++)
for (var i = 0; i < stateFrame; i++)
{
if (_log[i] != log[i])
{
errorMessage = "The savestate input does not match the movie input at frame "
+ (i + 1).ToString()
+ (i + 1)
+ ".";
return LoadStateResult.TimeLineError;
}
}
if (stateFrame > log.Length) //stateFrame is greater than state input log, so movie finished mode
if (stateFrame > log.Length) // stateFrame is greater than state input log, so movie finished mode
{
if (_mode == Moviemode.Play || _mode == Moviemode.Finished)
{
@ -706,7 +734,7 @@ namespace BizHawk.Client.Common
}
else
{
return LoadStateResult.NotInRecording; //TODO: For now throw an error if recording, ideally what should happen is that the state gets loaded, and the movie set to movie finished, the movie at its current state is preserved and the state is loaded just fine. This should probably also only happen if checktimelines passes
return LoadStateResult.NotInRecording; // TODO: For now throw an error if recording, ideally what should happen is that the state gets loaded, and the movie set to movie finished, the movie at its current state is preserved and the state is loaded just fine. This should probably also only happen if checktimelines passes
}
}
else if (_mode == Moviemode.Finished)
@ -725,9 +753,7 @@ namespace BizHawk.Client.Common
private enum Moviemode { Inactive, Play, Record, Finished };
private Moviemode _mode = Moviemode.Inactive;
private bool _statecapturing;
private bool _startsfromsavestate;
private int _preloadFramecount; //Not a a reliable number, used for preloading (when no log has yet been loaded), this is only for quick stat compilation for dialogs such as play movie
private int _rerecords;
private int _preloadFramecount; // Not a a reliable number, used for preloading (when no log has yet been loaded), this is only for quick stat compilation for dialogs such as play movie
private bool _changes;
private int? _loopOffset;
@ -738,13 +764,17 @@ namespace BizHawk.Client.Common
private void WriteText(string fn)
{
using (var fs = new FileStream(fn, FileMode.Create, FileAccess.Write, FileShare.Read))
{
WriteText(fs);
}
}
private void WriteBinary(string fn)
{
using (var fs = new FileStream(fn, FileMode.Create, FileAccess.Write, FileShare.Read))
{
WriteBinary(fs);
}
}
private void WriteText(Stream stream)
@ -756,11 +786,9 @@ namespace BizHawk.Client.Common
// TODO: clean this up
if (_loopOffset.HasValue)
{
sw.WriteLine("LoopOffset " + _loopOffset.ToString());
sw.WriteLine("LoopOffset " + _loopOffset);
}
sw.Write(Header.Subtitles.ToString());
for (int i = 0; i < _log.Length; i++)
{
sw.WriteLine(_log[i]);
@ -787,69 +815,45 @@ namespace BizHawk.Client.Common
_log.Clear();
}
using (StreamReader sr = file.OpenText())
using (var sr = file.OpenText())
{
string str;
string line;
while ((str = sr.ReadLine()) != null)
while ((line = sr.ReadLine()) != null)
{
if (str == "")
if (line == String.Empty)
{
continue;
}
if (str.Contains(HeaderKeys.RERECORDS))
if (line.Contains("LoopOffset"))
{
string rerecordStr = ParseHeader(str, HeaderKeys.RERECORDS);
try
{
Rerecords = int.Parse(rerecordStr);
_loopOffset = int.Parse(line.Split(new[] { ' ' }, 2)[1]);
}
catch
catch (Exception)
{
Rerecords = 0;
continue;
}
}
else if (str.Contains(HeaderKeys.STARTSFROMSAVESTATE))
{
str = ParseHeader(str, HeaderKeys.STARTSFROMSAVESTATE);
if (str == "1")
StartsFromSavestate = true;
}
else if (str.Contains("LoopOffset"))
{
str = ParseHeader(str, "LoopOffset");
try
{
_loopOffset = int.Parse(str);
}
catch
{
//Do nothing
}
}
else if (str.StartsWith("subtitle") || str.StartsWith("sub"))
{
Header.Subtitles.AddFromString(str);
}
else if (Header.AddHeaderFromLine(str))
else if (Header.ParseLineFromFile(line))
{
continue;
}
else if (str[0] == '|')
else if (line.StartsWith("|"))
{
_log.AppendFrame(str);
_log.AppendFrame(line);
}
else
{
Header.Comments.Add(str);
Header.Comments.Add(line);
}
}
}
Loaded = true;
return true;
}
private bool LoadBinary()
@ -857,16 +861,9 @@ namespace BizHawk.Client.Common
return true;
}
private string MakeDigits(int num)
private static string MakeDigits(int num)
{
if (num < 10)
{
return "0" + num.ToString();
}
else
{
return num.ToString();
}
return num < 10 ? "0" + num : num.ToString();
}
private double GetSeconds(int frameCount)
@ -878,86 +875,31 @@ namespace BizHawk.Client.Common
return 0;
}
string system = Header.Parameters[HeaderKeys.PLATFORM];
bool pal = Header.Parameters.ContainsKey(HeaderKeys.PAL) &&
Header.Parameters[HeaderKeys.PAL] == "1";
var system = Header[HeaderKeys.PLATFORM];
var pal = Header.ContainsKey(HeaderKeys.PAL) &&
Header[HeaderKeys.PAL] == "1";
return frames / _PlatformFrameRates[system, pal];
}
private static string ParseHeader(string line, string headerName)
{
int x = line.LastIndexOf(headerName) + headerName.Length;
return line.Substring(x + 1, line.Length - x - 1);
return frames / this.FrameRates[system, pal];
}
public double Fps
{
get
{
string system = Header.Parameters[HeaderKeys.PLATFORM];
bool pal = Header.Parameters.ContainsKey(HeaderKeys.PAL) &&
Header.Parameters[HeaderKeys.PAL] == "1";
var system = Header[HeaderKeys.PLATFORM];
var pal = Header.ContainsKey(HeaderKeys.PAL) &&
Header[HeaderKeys.PAL] == "1";
return _PlatformFrameRates[system, pal];
return FrameRates[system, pal];
}
}
#endregion
private PlatformFrameRates _platformFrameRates = new PlatformFrameRates();
public PlatformFrameRates _PlatformFrameRates
private readonly PlatformFrameRates _frameRates = new PlatformFrameRates();
public PlatformFrameRates FrameRates
{
get { return _platformFrameRates; }
}
public class PlatformFrameRates
{
public double this[string systemId, bool pal]
{
get
{
string key = systemId + (pal ? "_PAL" : String.Empty);
if (rates.ContainsKey(key))
{
return rates[key];
}
else
{
return 60.0;
}
}
}
private Dictionary<string, double> rates = new Dictionary<string, double>
{
{ "NES", 60.098813897440515532 },
{ "NES_PAL", 50.006977968268290849 },
{ "FDS", 60.098813897440515532 },
{ "FDS_PAL", 50.006977968268290849 },
{ "SNES", (double)21477272 / (4 * 341 * 262) },
{ "SNES_PAL", (double)21281370 / (4 * 341 * 312) },
{ "SGB", (double)21477272 / (4 * 341 * 262) },
{ "SGB_PAL", (double)21281370 / (4 * 341 * 312) },
{ "PCE", (7159090.90909090 / 455 / 263) }, //~59.826
{ "PCECD", (7159090.90909090 / 455 / 263) }, //~59.826
{ "SMS", (3579545 / 262.0 / 228.0) },
{ "SMS_PAL", (3546893 / 313.0 / 228.0) },
{ "GG", (3579545 / 262.0 / 228.0) },
{ "GG_PAL", (3546893 / 313.0 / 228.0) },
{ "SG", (3579545 / 262.0 / 228.0) },
{ "SG_PAL", (3546893 / 313.0 / 228.0) },
{ "NGP", (6144000.0 / (515 * 198)) },
{ "VBOY", (20000000 / (259 * 384 * 4)) }, //~50.273
{ "LYNX", 59.8 },
{ "WSWAN", (3072000.0 / (159 * 256)) },
{ "GB", 262144.0 / 4389.0 },
{ "GBC", 262144.0 / 4389.0 },
{ "GBA", 262144.0 / 4389.0 },
{ "A26", 59.9227510135505 },
{ "A78", 59.9227510135505 },
{ "Coleco", 59.9227510135505 }
};
get { return _frameRates; }
}
}
}

View File

@ -1,69 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using BizHawk.Common;
namespace BizHawk.Client.Common
{
using System.Linq;
public class MovieHeader : Dictionary<string, string>, IMovieHeader
{
//Required Header Params
//Emulation - Core version, will be 1.0.0 until there is a versioning system
//Movie - Versioning for the Movie code itself, or perhaps this could be changed client version?
//Platform - Must know what platform we are making a movie on!
//GameName - Which game
//TODO: checksum of game, other stuff
public Dictionary<string, string> Parameters { get; private set; }
public List<string> Comments { get; private set; }
public Dictionary<string, string> BoardProperties { get; private set; }
public SubtitleList Subtitles { get; private set; }
public MovieHeader() //All required fields will be set to default values
public MovieHeader()
{
Parameters = new Dictionary<string, string>(); //Platform specific options go here
BoardProperties = new Dictionary<string, string>();
Comments = new List<string>();
Subtitles = new SubtitleList();
BoardProperties = new Dictionary<string, string>();
Parameters.Add(HeaderKeys.EMULATIONVERSION, VersionInfo.GetEmuVersion());
Parameters.Add(HeaderKeys.MOVIEVERSION, HeaderKeys.MovieVersion);
Parameters.Add(HeaderKeys.PLATFORM, String.Empty);
Parameters.Add(HeaderKeys.GAMENAME, String.Empty);
Parameters.Add(HeaderKeys.AUTHOR, String.Empty);
Parameters.Add(HeaderKeys.RERECORDS, "0");
Parameters.Add(HeaderKeys.GUID, HeaderKeys.NewGuid);
this[HeaderKeys.EMULATIONVERSION] = VersionInfo.GetEmuVersion();
this[HeaderKeys.MOVIEVERSION] = HeaderKeys.MovieVersion;
this[HeaderKeys.PLATFORM] = String.Empty;
this[HeaderKeys.GAMENAME] = String.Empty;
this[HeaderKeys.AUTHOR] = String.Empty;
this[HeaderKeys.RERECORDS] = "0";
this[HeaderKeys.GUID] = HeaderKeys.NewGuid;
}
/// <summary>
/// Adds the key value pair to header params. If key already exists, value will be updated
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddHeaderLine(string key, string value)
public new string this[string key]
{
string temp;
if (!Parameters.TryGetValue(key, out temp)) //TODO: does a failed attempt mess with value?
Parameters.Add(key, value);
}
private void AddBoardProperty(string key, string value)
{
string temp;
if (!BoardProperties.TryGetValue(key, out temp))
get
{
BoardProperties.Add(key, value);
return this.ContainsKey(key) ? base[key] : String.Empty;
}
set
{
if (ContainsKey(key))
{
base[key] = value;
}
else
{
Add(key, value);
}
}
}
new public void Clear()
public new void Clear()
{
Parameters.Clear();
BoardProperties.Clear();
Comments.Clear();
Subtitles.Clear();
@ -74,7 +59,7 @@ namespace BizHawk.Client.Common
{
var sb = new StringBuilder();
foreach (var kvp in Parameters)
foreach (var kvp in this)
{
sb
.Append(kvp.Key)
@ -94,70 +79,102 @@ namespace BizHawk.Client.Common
.AppendLine();
}
foreach (string t in Comments)
{
sb.AppendLine(t);
}
//TOD: subtitles go here not wherever it is currently located
sb.Append(Subtitles);
Comments.ForEach(comment => sb.AppendLine(comment));
return sb.ToString();
}
public bool AddHeaderFromLine(string line)
public ulong Rerecords
{
get
{
if (!ContainsKey(HeaderKeys.RERECORDS))
{
this[HeaderKeys.RERECORDS] = "0";
}
return ulong.Parse(this[HeaderKeys.RERECORDS]);
}
set
{
this[HeaderKeys.RERECORDS] = value.ToString();
}
}
public bool StartsFromSavestate
{
get
{
if (ContainsKey(HeaderKeys.STARTSFROMSAVESTATE))
{
return bool.Parse(this[HeaderKeys.STARTSFROMSAVESTATE]);
}
else
{
return false;
}
}
set
{
if (value)
{
Add(HeaderKeys.STARTSFROMSAVESTATE, "True");
}
else
{
Remove(HeaderKeys.STARTSFROMSAVESTATE);
}
}
}
public bool ParseLineFromFile(string line)
{
if (!String.IsNullOrWhiteSpace(line))
{
var splitLine = line.Split(new char[] { ' ' }, 2);
var splitLine = line.Split(new[] { ' ' }, 2);
if (line.Contains(HeaderKeys.BOARDPROPERTIES))
{
var boardSplit = splitLine[1].Split(' ');
AddBoardProperty(boardSplit[0], boardSplit[1]);
if (!BoardProperties.ContainsKey(boardSplit[0]))
{
BoardProperties.Add(boardSplit[0], boardSplit[1]);
}
}
else if (HeaderKeys.Contains(splitLine[0]))
{
Parameters.Add(splitLine[0], splitLine[1]);
Add(splitLine[0], splitLine[1]);
}
else if (line.StartsWith("subtitle") || line.StartsWith("sub"))
{
return false;
Subtitles.AddFromString(line);
}
else if (line.StartsWith("comment"))
{
Comments.Add(line.Substring(8, line.Length - 8));
}
else if (line[0] == '|')
else if (line.StartsWith("|"))
{
return false;
}
else if (Parameters.ContainsKey(HeaderKeys.PLATFORM) && Parameters[HeaderKeys.PLATFORM] == "N64")
else if (ContainsKey(HeaderKeys.PLATFORM) && this[HeaderKeys.PLATFORM] == "N64"
&& ContainsKey(HeaderKeys.VIDEOPLUGIN))
{
if (Parameters.ContainsKey(HeaderKeys.VIDEOPLUGIN))
if (this[HeaderKeys.VIDEOPLUGIN] == "Rice")
{
if (Parameters[HeaderKeys.VIDEOPLUGIN] == "Rice")
if (Global.Config.RicePlugin.GetPluginSettings().Keys.Any(line.Contains))
{
ICollection<string> settings = Global.Config.RicePlugin.GetPluginSettings().Keys;
foreach (var setting in settings)
{
if (line.Contains(setting))
{
Parameters.Add(splitLine[0], splitLine[1]);
break;
}
}
Add(splitLine[0], splitLine[1]);
}
else if (Parameters[HeaderKeys.VIDEOPLUGIN] == "Glide64")
}
else if (this[HeaderKeys.VIDEOPLUGIN] == "Glide64")
{
if (Global.Config.GlidePlugin.GetPluginSettings().Keys.Any(line.Contains))
{
ICollection<string> settings = Global.Config.GlidePlugin.GetPluginSettings().Keys;
foreach (string setting in settings)
{
if (line.Contains(setting))
{
Parameters.Add(splitLine[0], splitLine[1]);
break;
}
}
Add(splitLine[0], splitLine[1]);
}
}
}

View File

@ -85,7 +85,7 @@ namespace BizHawk.Client.Common
}
if (errorMsg == String.Empty)
{
m.Header.Parameters[HeaderKeys.MOVIEVERSION] = HeaderKeys.MovieVersion;
m.Header[HeaderKeys.MOVIEVERSION] = HeaderKeys.MovieVersion;
}
}
catch (Exception except)
@ -304,7 +304,7 @@ namespace BizHawk.Client.Common
platform = "PCE";
break;
}
m.Header.Parameters[HeaderKeys.PLATFORM] = platform;
m.Header[HeaderKeys.PLATFORM] = platform;
int lineNum = 0;
string line;
while ((line = sr.ReadLine()) != null)
@ -348,7 +348,7 @@ namespace BizHawk.Client.Common
}
else if (line.ToLower().StartsWith("romfilename"))
{
m.Header.Parameters[HeaderKeys.GAMENAME] = ParseHeader(line, "romFilename");
m.Header[HeaderKeys.GAMENAME] = ParseHeader(line, "romFilename");
}
else if (line.ToLower().StartsWith("romchecksum"))
{
@ -356,7 +356,7 @@ namespace BizHawk.Client.Common
byte[] md5 = DecodeBlob(blob);
if (md5 != null && md5.Length == 16)
{
m.Header.Parameters[MD5] = Util.BytesToHexString(md5).ToLower();
m.Header[MD5] = Util.BytesToHexString(md5).ToLower();
}
else
{
@ -365,7 +365,7 @@ namespace BizHawk.Client.Common
}
else if (line.ToLower().StartsWith("comment author"))
{
m.Header.Parameters[HeaderKeys.AUTHOR] = ParseHeader(line, "comment author");
m.Header[HeaderKeys.AUTHOR] = ParseHeader(line, "comment author");
}
else if (line.ToLower().StartsWith("rerecordcount"))
{
@ -379,11 +379,11 @@ namespace BizHawk.Client.Common
{
rerecordCount = 0;
}
m.Rerecords = rerecordCount;
m.Rerecords = (ulong)rerecordCount;
}
else if (line.ToLower().StartsWith("guid"))
{
m.Header.Parameters[HeaderKeys.GUID] = ParseHeader(line, "guid");
m.Header[HeaderKeys.GUID] = ParseHeader(line, "guid");
}
else if (line.ToLower().StartsWith("startsfromsavestate"))
{
@ -398,12 +398,12 @@ namespace BizHawk.Client.Common
else if (line.ToLower().StartsWith("palflag"))
{
bool pal = (ParseHeader(line, "palFlag") == "1");
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
}
else if (line.ToLower().StartsWith("fourscore"))
{
bool fourscore = (ParseHeader(line, "fourscore") == "1");
m.Header.Parameters[HeaderKeys.FOURSCORE] = fourscore.ToString();
m.Header[HeaderKeys.FOURSCORE] = fourscore.ToString();
}
else
// Everything not explicitly defined is treated as a comment.
@ -515,7 +515,7 @@ namespace BizHawk.Client.Common
preference. This means that this site cannot calculate movie lengths reliably.
*/
bool pal = (((flags >> 2) & 0x1) != 0);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// other: reserved, set to 0
bool syncHack = (((flags >> 4) & 0x1) != 0);
m.Header.Comments.Add(SYNCHACK + " " + syncHack.ToString());
@ -529,7 +529,7 @@ namespace BizHawk.Client.Common
uint frameCount = r.ReadUInt32();
// 010 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = rerecordCount;
/*
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
@ -541,7 +541,7 @@ namespace BizHawk.Client.Common
uint firstFrameOffset = r.ReadUInt32();
// 020 16-byte md5sum of the ROM used
byte[] md5 = r.ReadBytes(16);
m.Header.Parameters[MD5] = Util.BytesToHexString(md5).ToLower();
m.Header[MD5] = 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());
@ -552,7 +552,7 @@ namespace BizHawk.Client.Common
// Advance past null byte.
r.ReadByte();
string gameName = Encoding.UTF8.GetString(gameBytes.ToArray());
m.Header.Parameters[HeaderKeys.GAMENAME] = gameName;
m.Header[HeaderKeys.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
@ -564,7 +564,7 @@ namespace BizHawk.Client.Common
// Advance past null byte.
r.ReadByte();
string author = Encoding.UTF8.GetString(authorBytes.ToArray());
m.Header.Parameters[HeaderKeys.AUTHOR] = author;
m.Header[HeaderKeys.AUTHOR] = author;
// Advance to first byte of input data.
r.BaseStream.Position = firstFrameOffset;
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "NES Controller"}};
@ -707,9 +707,9 @@ namespace BizHawk.Client.Common
controllers["P" + player + " " + buttons[button]] = !controllers["P" + player + " " + buttons[button]];
}
}
m.Header.Parameters[HeaderKeys.PLATFORM] = "NES";
if (fds) { m.Header.Parameters[HeaderKeys.BOARDNAME] = "FDS"; }
m.Header.Parameters[HeaderKeys.FOURSCORE] = fourscore.ToString();
m.Header[HeaderKeys.PLATFORM] = "NES";
if (fds) { m.Header[HeaderKeys.BOARDNAME] = "FDS"; }
m.Header[HeaderKeys.FOURSCORE] = fourscore.ToString();
r.Close();
fs.Close();
return m;
@ -755,7 +755,7 @@ namespace BizHawk.Client.Common
if (((flags >> 5) & 0x1) != 0)
{
FDS = true;
m.Header.Parameters[HeaderKeys.BOARDNAME] = "FDS";
m.Header[HeaderKeys.BOARDNAME] = "FDS";
}
else
{
@ -763,7 +763,7 @@ namespace BizHawk.Client.Common
}
m.Header.Parameters[HeaderKeys.PLATFORM] = "NES";
m.Header[HeaderKeys.PLATFORM] = "NES";
// bit 6: uses controller 2
bool controller2 = (((flags >> 6) & 0x1) != 0);
@ -779,7 +779,7 @@ namespace BizHawk.Client.Common
loaded, the number is 0. Famtasia however displays "1" in such case. It always adds 1 to the number found in
the file.
*/
m.Rerecords = ((int)rerecordCount) + 1;
m.Rerecords = rerecordCount + 1;
// 00E 2-byte little-endian unsigned int: unknown, set to 0000
r.ReadInt16();
// 010 64-byte zero-terminated emulator identifier string
@ -800,7 +800,7 @@ namespace BizHawk.Client.Common
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.Parameters[HeaderKeys.PAL] = "False";
m.Header[HeaderKeys.PAL] = "False";
// 090 frame data begins here
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "NES Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
@ -879,14 +879,14 @@ namespace BizHawk.Client.Common
fs.Close();
return null;
}
m.Header.Parameters[HeaderKeys.PLATFORM] = "Genesis";
m.Header[HeaderKeys.PLATFORM] = "Genesis";
// 00F ASCII-encoded GMV file format version. The most recent is 'A'. (?)
string version = r.ReadStringFixedAscii(1);
m.Header.Comments.Add(MOVIEORIGIN + " .GMV version " + version);
m.Header.Comments.Add(EMULATIONORIGIN + " Gens");
// 010 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = 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'.
@ -903,7 +903,7 @@ namespace BizHawk.Client.Common
header.
*/
bool pal = (((flags >> 7) & 0x1) != 0);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// bit 6: if "1", movie requires a savestate.
if (((flags >> 6) & 0x1) != 0)
{
@ -1035,7 +1035,7 @@ namespace BizHawk.Client.Common
{
author_list += author_last;
}
m.Header.Parameters[HeaderKeys.AUTHOR] = author_list;
m.Header[HeaderKeys.AUTHOR] = author_list;
hf.Unbind();
}
else if (item.name == "coreversion")
@ -1051,7 +1051,7 @@ namespace BizHawk.Client.Common
hf.BindArchiveMember(item.index);
var stream = hf.GetStream();
string gamename = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
m.Header.Parameters[HeaderKeys.GAMENAME] = gamename;
m.Header[HeaderKeys.GAMENAME] = gamename;
hf.Unbind();
}
else if (item.name == "gametype")
@ -1072,11 +1072,11 @@ namespace BizHawk.Client.Common
case "sgb_ntsc":
case "sgb_pal":
platform = "SNES";
m.Header.Parameters[HeaderKeys.SGB] = "True";
m.Header[HeaderKeys.SGB] = "True";
break;
}
bool pal = (gametype == "snes_pal" || gametype == "sgb_pal");
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
hf.Unbind();
}
else if (item.name == "input")
@ -1123,7 +1123,7 @@ namespace BizHawk.Client.Common
hf.BindArchiveMember(item.index);
var stream = hf.GetStream();
string port1 = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
m.Header.Parameters[PORT1] = port1;
m.Header[PORT1] = port1;
hf.Unbind();
}
else if (item.name == "port2")
@ -1131,7 +1131,7 @@ namespace BizHawk.Client.Common
hf.BindArchiveMember(item.index);
var stream = hf.GetStream();
string port2 = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
m.Header.Parameters[PORT2] = port2;
m.Header[PORT2] = port2;
hf.Unbind();
}
else if (item.name == "projectid")
@ -1139,7 +1139,7 @@ namespace BizHawk.Client.Common
hf.BindArchiveMember(item.index);
var stream = hf.GetStream();
string projectid = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
m.Header.Parameters[PROJECTID] = projectid;
m.Header[PROJECTID] = projectid;
hf.Unbind();
}
else if (item.name == "rerecords")
@ -1157,7 +1157,7 @@ namespace BizHawk.Client.Common
{
rerecordCount = 0;
}
m.Rerecords = rerecordCount;
m.Rerecords = (ulong)rerecordCount;
hf.Unbind();
}
else if (item.name.EndsWith(".sha256"))
@ -1167,7 +1167,7 @@ namespace BizHawk.Client.Common
string rom = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
int pos = item.name.LastIndexOf(".sha256");
string name = item.name.Substring(0, pos);
m.Header.Parameters[SHA256 + "_" + name] = rom;
m.Header[SHA256 + "_" + name] = rom;
hf.Unbind();
}
else if (item.name == "savestate")
@ -1193,7 +1193,7 @@ namespace BizHawk.Client.Common
hf.BindArchiveMember(item.index);
var stream = hf.GetStream();
string startSecond = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
m.Header.Parameters[STARTSECOND] = startSecond;
m.Header[STARTSECOND] = startSecond;
hf.Unbind();
}
else if (item.name == "starttime.subsecond")
@ -1201,7 +1201,7 @@ namespace BizHawk.Client.Common
hf.BindArchiveMember(item.index);
var stream = hf.GetStream();
string startSubSecond = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim();
m.Header.Parameters[STARTSUBSECOND] = startSubSecond;
m.Header[STARTSUBSECOND] = startSubSecond;
hf.Unbind();
}
else if (item.name == "systemid")
@ -1213,7 +1213,7 @@ namespace BizHawk.Client.Common
hf.Unbind();
}
}
m.Header.Parameters[HeaderKeys.PLATFORM] = platform;
m.Header[HeaderKeys.PLATFORM] = platform;
return m;
}
@ -1246,13 +1246,13 @@ namespace BizHawk.Client.Common
byte[] md5 = r.ReadBytes(16);
// Discard the second 16 bytes.
r.ReadBytes(16);
m.Header.Parameters[MD5] = Util.BytesToHexString(md5).ToLower();
m.Header[MD5] = Util.BytesToHexString(md5).ToLower();
// 030 64-byte Filename of the ROM used (with extension)
string gameName = NullTerminated(r.ReadStringFixedAscii(64));
m.Header.Parameters[HeaderKeys.GAMENAME] = gameName;
m.Header[HeaderKeys.GAMENAME] = gameName;
// 070 uint32 Re-record Count
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = (ulong)rerecordCount;
// 074 5-byte Console indicator (pce, ngp, pcfx, wswan)
string platform = NullTerminated(r.ReadStringFixedAscii(5));
Dictionary<string, Dictionary<string, object>> platforms = new Dictionary<string, Dictionary<string, object>>
@ -1285,10 +1285,10 @@ namespace BizHawk.Client.Common
return null;
}
string name = (string)platforms[platform]["name"];
m.Header.Parameters[HeaderKeys.PLATFORM] = name;
m.Header[HeaderKeys.PLATFORM] = name;
// 079 32-byte Author name
string author = NullTerminated(r.ReadStringFixedAscii(32));
m.Header.Parameters[HeaderKeys.AUTHOR] = author;
m.Header[HeaderKeys.AUTHOR] = author;
// 099 103-byte Padding 0s
r.ReadBytes(103);
// TODO: Verify if NTSC/"PAL" mode used for the movie can be detected or not.
@ -1367,7 +1367,7 @@ namespace BizHawk.Client.Common
uint frameCount = r.ReadUInt32();
// 000c: 4-byte little endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = rerecordCount;
// 0010: 4-byte little endian flag: begin from reset?
uint reset = r.ReadUInt32();
if (reset == 0)
@ -1385,36 +1385,36 @@ namespace BizHawk.Client.Common
r.ReadUInt32();
// 0020-005f: string: author info (UTF-8)
string author = NullTerminated(r.ReadStringFixedAscii(64));
m.Header.Parameters[HeaderKeys.AUTHOR] = author;
m.Header[HeaderKeys.AUTHOR] = author;
// 0060: 4-byte little endian flags
byte flags = r.ReadByte();
// bit 0: unused
// bit 1: "PAL"
bool pal = (((flags >> 1) & 0x1) != 0);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// bit 2: Japan
bool japan = (((flags >> 2) & 0x1) != 0);
m.Header.Parameters[JAPAN] = japan.ToString();
m.Header[JAPAN] = japan.ToString();
// bit 3: Game Gear (version 1.16+)
bool gamegear;
if (((flags >> 3) & 0x1) != 0)
{
gamegear = true;
m.Header.Parameters[HeaderKeys.PLATFORM] = "GG";
m.Header[HeaderKeys.PLATFORM] = "GG";
}
else
{
gamegear = false;
m.Header.Parameters[HeaderKeys.PLATFORM] = "SMS";
m.Header[HeaderKeys.PLATFORM] = "SMS";
}
// bits 4-31: unused
r.ReadBytes(3);
// 0064-00e3: string: rom name (ASCII)
string gameName = NullTerminated(r.ReadStringFixedAscii(128));
m.Header.Parameters[HeaderKeys.GAMENAME] = gameName;
m.Header[HeaderKeys.GAMENAME] = gameName;
// 00e4-00f3: binary: rom MD5 digest
byte[] md5 = r.ReadBytes(16);
m.Header.Parameters[MD5] = String.Format("{0:x8}", Util.BytesToHexString(md5).ToLower());
m.Header[MD5] = String.Format("{0:x8}", Util.BytesToHexString(md5).ToLower());
SimpleController controllers = new SimpleController {Type = new ControllerDefinition {Name = "SMS Controller"}};
MnemonicsGenerator mg = new MnemonicsGenerator();
/*
@ -1526,7 +1526,7 @@ namespace BizHawk.Client.Common
* 7 - Vs Unisystem Zapper (3 bytes)
*/
bool fourscore = (controller1 == 5);
m.Header.Parameters[HeaderKeys.FOURSCORE] = fourscore.ToString();
m.Header[HeaderKeys.FOURSCORE] = fourscore.ToString();
bool[] masks = new[] { false, false, false, false, false };
if (fourscore)
{
@ -1629,10 +1629,10 @@ namespace BizHawk.Client.Common
* if "1", "PAL" timing
*/
bool pal = (((data >> 7) & 0x1) != 0);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// 004 4-byte little-endian unsigned int: rerecord count
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = rerecordCount;
/*
008 4-byte little-endian unsigned int: length of movie description
00C (variable) null-terminated UTF-8 text, movie description (currently not implemented)
@ -1704,7 +1704,7 @@ namespace BizHawk.Client.Common
fs.Close();
return null;
}
m.Header.Parameters[HeaderKeys.PLATFORM] = "SNES";
m.Header[HeaderKeys.PLATFORM] = "SNES";
// 004 4-byte little-endian unsigned int: version number
uint versionNumber = r.ReadUInt32();
string version;
@ -1732,9 +1732,9 @@ namespace BizHawk.Client.Common
recording time in Unix epoch format
*/
uint uid = r.ReadUInt32();
m.Header.Parameters[HeaderKeys.GUID] = String.Format("{0:X8}", uid) + "-0000-0000-0000-000000000000";
m.Header[HeaderKeys.GUID] = String.Format("{0:X8}", uid) + "-0000-0000-0000-000000000000";
// 00C 4-byte little-endian unsigned int: rerecord count
m.Rerecords = (int)r.ReadUInt32();
m.Rerecords = r.ReadUInt32();
// 010 4-byte little-endian unsigned int: number of frames
uint frameCount = r.ReadUInt32();
// 014 1-byte flags "controller mask"
@ -1770,7 +1770,7 @@ namespace BizHawk.Client.Common
}
// bit 1: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps)
bool pal = (((movieFlags >> 1) & 0x1) != 0);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// other: reserved, set to 0
/*
016 1-byte flags "sync options":
@ -1830,17 +1830,17 @@ namespace BizHawk.Client.Common
string author = NullTerminated(Encoding.Unicode.GetString(metadata).Trim());
if (author != "")
{
m.Header.Parameters[HeaderKeys.AUTHOR] = author;
m.Header[HeaderKeys.AUTHOR] = author;
}
if (extraRomInfo == 30)
{
// 000 3 bytes of zero padding: 00 00 00 003 4-byte integer: CRC32 of the ROM 007 23-byte ascii string
r.ReadBytes(3);
int crc32 = r.ReadInt32();
m.Header.Parameters[CRC32] = crc32.ToString();
m.Header[CRC32] = crc32.ToString();
// the game name copied from the ROM, truncated to 23 bytes (the game name in the ROM is 21 bytes)
string gameName = NullTerminated(Encoding.UTF8.GetString(r.ReadBytes(23)));
m.Header.Parameters[HeaderKeys.GAMENAME] = gameName;
m.Header[HeaderKeys.GAMENAME] = gameName;
}
r.BaseStream.Position = firstFrameOffset;
/*
@ -1991,12 +1991,12 @@ namespace BizHawk.Client.Common
recording time in Unix epoch format
*/
uint uid = r.ReadUInt32();
m.Header.Parameters[HeaderKeys.GUID] = String.Format("{0:X8}", uid) + "-0000-0000-0000-000000000000";
m.Header[HeaderKeys.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.Rerecords = (int)rerecordCount;
m.Rerecords = rerecordCount;
// 014 1-byte flags: (movie start flags)
byte flags = r.ReadByte();
// bit 0: if "1", movie starts from an embedded "quicksave" snapshot
@ -2080,7 +2080,7 @@ namespace BizHawk.Client.Common
{
m.Header.Comments.Add(SUPERGAMEBOYMODE + " True");
}
m.Header.Parameters[HeaderKeys.PLATFORM] = platform;
m.Header[HeaderKeys.PLATFORM] = platform;
// 017 1-byte flags: (values of some boolean emulator options)
flags = r.ReadByte();
/*
@ -2117,7 +2117,7 @@ namespace BizHawk.Client.Common
null-terminated (ASCII?)
*/
string gameName = NullTerminated(r.ReadStringFixedAscii(12));
m.Header.Parameters[HeaderKeys.GAMENAME] = gameName;
m.Header[HeaderKeys.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);
@ -2136,13 +2136,13 @@ namespace BizHawk.Client.Common
uint gameCode_unitCode = r.ReadUInt32();
if (platform == "GBA")
{
m.Header.Parameters[CRC16] = checksum_crc16.ToString();
m.Header.Parameters[GAMECODE] = gameCode_unitCode.ToString();
m.Header[CRC16] = checksum_crc16.ToString();
m.Header[GAMECODE] = gameCode_unitCode.ToString();
}
else
{
m.Header.Parameters[INTERNALCHECKSUM] = checksum_crc16.ToString();
m.Header.Parameters[UNITCODE] = gameCode_unitCode.ToString();
m.Header[INTERNALCHECKSUM] = checksum_crc16.ToString();
m.Header[UNITCODE] = gameCode_unitCode.ToString();
}
// 038 4-byte little-endian unsigned int: offset to the savestate or SRAM inside file, set to 0 if unused
r.ReadBytes(4);
@ -2150,7 +2150,7 @@ namespace BizHawk.Client.Common
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 = NullTerminated(r.ReadStringFixedAscii(64));
m.Header.Parameters[HeaderKeys.AUTHOR] = author;
m.Header[HeaderKeys.AUTHOR] = author;
// The following 128 bytes are for a description of the movie. Both parts must be null-terminated.
string movieDescription = NullTerminated(r.ReadStringFixedAscii(128));
m.Header.Comments.Add(COMMENT + " " + movieDescription);
@ -2249,7 +2249,7 @@ namespace BizHawk.Client.Common
fs.Close();
return null;
}
m.Header.Parameters[HeaderKeys.PLATFORM] = "NES";
m.Header[HeaderKeys.PLATFORM] = "NES";
// 00C 2-byte little-endian integer: movie version 0x0400
ushort version = r.ReadUInt16();
m.Header.Comments.Add(MOVIEORIGIN + " .VMV version " + version);
@ -2271,7 +2271,7 @@ namespace BizHawk.Client.Common
controllersUsed[controller - 1] = (((flags >> (controller - 1)) & 0x1) != 0);
}
bool fourscore = (controllersUsed[2] || controllersUsed[3]);
m.Header.Parameters[HeaderKeys.FOURSCORE] = fourscore.ToString();
m.Header[HeaderKeys.FOURSCORE] = fourscore.ToString();
/*
bit 6: 1=reset-based, 0=savestate-based (movie version <= 0x300 is always savestate-based)
If the movie version is < 0x400, or the "from-reset" flag is not set, a savestate is loaded from the movie.
@ -2298,7 +2298,7 @@ namespace BizHawk.Client.Common
r.ReadBytes(2);
// 01C 4-byte little-endian integer: rerecord count
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = rerecordCount;
/*
020 BYTE RenderMethod
0=POST_ALL,1=PRE_ALL
@ -2312,7 +2312,7 @@ namespace BizHawk.Client.Common
r.ReadByte();
// 023 1-byte flag: 0=NTSC (60 Hz), 1="PAL" (50 Hz)
bool pal = (r.ReadByte() == 1);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// 024 8-bytes: reserved, set to 0
r.ReadBytes(8);
// 02C 4-byte little-endian integer: save state start offset
@ -2325,7 +2325,7 @@ namespace BizHawk.Client.Common
uint frameCount = r.ReadUInt32();
// 03C 4-byte little-endian integer: CRC (CRC excluding this data(to prevent cheating))
int crc32 = r.ReadInt32();
m.Header.Parameters[CRC32] = crc32.ToString();
m.Header[CRC32] = crc32.ToString();
if (!controllersUsed[0] && !controllersUsed[1] && !controllersUsed[2] && !controllersUsed[3])
{
warningMsg = "No input recorded.";
@ -2469,19 +2469,19 @@ namespace BizHawk.Client.Common
fs.Close();
return null;
}
m.Header.Parameters[HeaderKeys.PLATFORM] = "SNES";
m.Header[HeaderKeys.PLATFORM] = "SNES";
// 003 2-byte little-endian unsigned int: zsnes version number
short version = r.ReadInt16();
m.Header.Comments.Add(EMULATIONORIGIN + " ZSNES version " + version);
m.Header.Comments.Add(MOVIEORIGIN + " .ZMV");
// 005 4-byte little-endian integer: CRC32 of the ROM
int crc32 = r.ReadInt32();
m.Header.Parameters[CRC32] = crc32.ToString();
m.Header[CRC32] = crc32.ToString();
// 009 4-byte little-endian unsigned int: number of frames
uint frameCount = r.ReadUInt32();
// 00D 4-byte little-endian unsigned int: number of rerecords
uint rerecordCount = r.ReadUInt32();
m.Rerecords = (int)rerecordCount;
m.Rerecords = rerecordCount;
// 011 4-byte little-endian unsigned int: number of frames removed by rerecord
r.ReadBytes(4);
// 015 4-byte little-endian unsigned int: number of frames advanced step by step
@ -2558,7 +2558,7 @@ namespace BizHawk.Client.Common
// if "11", movie begins from power-on with SRAM clear
// bit 5: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps)
bool pal = (((movieFlags >> 5) & 0x1) != 0);
m.Header.Parameters[HeaderKeys.PAL] = pal.ToString();
m.Header[HeaderKeys.PAL] = pal.ToString();
// other: reserved, set to 0
/*
028 3-byte little-endian unsigned int: initial save state size, highest bit specifies compression, next 23
@ -2750,7 +2750,7 @@ namespace BizHawk.Client.Common
r.BaseStream.Position = r.BaseStream.Length - authorSize;
// Last in the file comes the author name field, which is an UTF-8 encoded text string.
string author = Encoding.UTF8.GetString(r.ReadBytes(authorSize));
m.Header.Parameters[HeaderKeys.AUTHOR] = author;
m.Header[HeaderKeys.AUTHOR] = author;
return m;
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
namespace BizHawk.Client.Common
{
public class PlatformFrameRates
{
public double this[string systemId, bool pal]
{
get
{
var key = systemId + (pal ? "_PAL" : String.Empty);
if (_rates.ContainsKey(key))
{
return _rates[key];
}
else
{
return 60.0;
}
}
}
private readonly Dictionary<string, double> _rates = new Dictionary<string, double>
{
{ "NES", 60.098813897440515532 },
{ "NES_PAL", 50.006977968268290849 },
{ "FDS", 60.098813897440515532 },
{ "FDS_PAL", 50.006977968268290849 },
{ "SNES", (double)21477272 / (4 * 341 * 262) },
{ "SNES_PAL", (double)21281370 / (4 * 341 * 312) },
{ "SGB", (double)21477272 / (4 * 341 * 262) },
{ "SGB_PAL", (double)21281370 / (4 * 341 * 312) },
{ "PCE", (7159090.90909090 / 455 / 263) }, // ~59.826
{ "PCECD", (7159090.90909090 / 455 / 263) }, // ~59.826
{ "SMS", (3579545 / 262.0 / 228.0) },
{ "SMS_PAL", (3546893 / 313.0 / 228.0) },
{ "GG", (3579545 / 262.0 / 228.0) },
{ "GG_PAL", (3546893 / 313.0 / 228.0) },
{ "SG", (3579545 / 262.0 / 228.0) },
{ "SG_PAL", (3546893 / 313.0 / 228.0) },
{ "NGP", (6144000.0 / (515 * 198)) },
{ "VBOY", (20000000 / (259 * 384 * 4)) }, // ~50.273
{ "LYNX", 59.8 },
{ "WSWAN", (3072000.0 / (159 * 256)) },
{ "GB", 262144.0 / 4389.0 },
{ "GBC", 262144.0 / 4389.0 },
{ "GBA", 262144.0 / 4389.0 },
{ "A26", 59.9227510135505 },
{ "A78", 59.9227510135505 },
{ "Coleco", 59.9227510135505 }
};
}
}

View File

@ -503,11 +503,11 @@ namespace BizHawk.Client.EmuHawk
{
if (Global.MovieSession.Movie.IsActive)
{
return "Rerecord Count: " + Global.MovieSession.Movie.Rerecords.ToString();
return "Rerecord Count: " + Global.MovieSession.Movie.Rerecords;
}
else
{
return "";
return String.Empty;
}
}

View File

@ -38,7 +38,7 @@ namespace BizHawk.Client.EmuHawk
LoadRom(GlobalWin.MainForm.CurrentlyOpenRom, true, !record);
Global.Config.RecentMovies.Add(m.Filename);
if (Global.MovieSession.Movie.StartsFromSavestate)
if (Global.MovieSession.Movie.Header.StartsFromSavestate)
{
LoadStateFile(Global.MovieSession.Movie.Filename, Path.GetFileName(Global.MovieSession.Movie.Filename));
Global.Emulator.ResetCounters();
@ -112,7 +112,7 @@ namespace BizHawk.Client.EmuHawk
if (Global.MovieSession.Movie.IsActive)
{
LoadRom(CurrentlyOpenRom, true, true);
if (Global.MovieSession.Movie.StartsFromSavestate)
if (Global.MovieSession.Movie.Header.StartsFromSavestate)
{
LoadStateFile(Global.MovieSession.Movie.Filename, Path.GetFileName(Global.MovieSession.Movie.Filename));
Global.Emulator.ResetCounters();
@ -136,7 +136,7 @@ namespace BizHawk.Client.EmuHawk
switch (Global.Emulator.SystemId)
{
case "Coleco":
string str = Global.MovieSession.Movie.Header.Parameters[HeaderKeys.SKIPBIOS];
string str = Global.MovieSession.Movie.Header[HeaderKeys.SKIPBIOS];
if (!String.IsNullOrWhiteSpace(str))
{
if (str.ToLower() == "true")

View File

@ -1829,9 +1829,9 @@ namespace BizHawk.Client.EmuHawk
{
var PluginToUse = String.Empty;
if (hasmovie && Global.MovieSession.Movie.Header.Parameters[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.Parameters.ContainsKey(HeaderKeys.VIDEOPLUGIN))
if (hasmovie && Global.MovieSession.Movie.Header[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.ContainsKey(HeaderKeys.VIDEOPLUGIN))
{
PluginToUse = Global.MovieSession.Movie.Header.Parameters[HeaderKeys.VIDEOPLUGIN];
PluginToUse = Global.MovieSession.Movie.Header[HeaderKeys.VIDEOPLUGIN];
}
if (PluginToUse == "" || (PluginToUse != "Rice" && PluginToUse != "Glide64"))
@ -1857,14 +1857,14 @@ namespace BizHawk.Client.EmuHawk
video_settings.Parameters = Global.Config.Glide64mk2Plugin.GetPluginSettings();
}
if (hasmovie && Global.MovieSession.Movie.Header.Parameters[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.Parameters.ContainsKey(HeaderKeys.VIDEOPLUGIN))
if (hasmovie && Global.MovieSession.Movie.Header[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.ContainsKey(HeaderKeys.VIDEOPLUGIN))
{
var settings = new List<string>(video_settings.Parameters.Keys);
foreach (var setting in settings)
{
if (Global.MovieSession.Movie.Header.Parameters.ContainsKey(setting))
if (Global.MovieSession.Movie.Header.ContainsKey(setting))
{
var Value = Global.MovieSession.Movie.Header.Parameters[setting];
var Value = Global.MovieSession.Movie.Header[setting];
if (video_settings.Parameters[setting] is bool)
{
try

View File

@ -174,7 +174,7 @@ namespace BizHawk.Client.EmuHawk
try
{
//Don't do this from browse
if (movie.Header.Parameters[HeaderKeys.GAMENAME] == Global.Game.Name ||
if (movie.Header[HeaderKeys.GAMENAME] == Global.Game.Name ||
Global.Config.PlayMovie_MatchGameName == false || force)
{
_movieList.Add(movie);
@ -333,9 +333,8 @@ namespace BizHawk.Client.EmuHawk
int firstIndex = MovieView.SelectedIndices[0];
MovieView.ensureVisible(firstIndex);
var headers = _movieList[firstIndex].Header.Parameters;
foreach (var kvp in headers)
foreach (var kvp in _movieList[firstIndex].Header)
{
var item = new ListViewItem(kvp.Key);
item.SubItems.Add(kvp.Value);

View File

@ -94,73 +94,73 @@ namespace BizHawk.Client.EmuHawk
}
//Header
_movieToRecord.Header.Parameters[HeaderKeys.AUTHOR] = AuthorBox.Text;
_movieToRecord.Header.Parameters[HeaderKeys.EMULATIONVERSION] = VersionInfo.GetEmuVersion();
_movieToRecord.Header.Parameters[HeaderKeys.MOVIEVERSION] = HeaderKeys.MovieVersion;
_movieToRecord.Header.Parameters[HeaderKeys.GUID] = HeaderKeys.NewGuid;
_movieToRecord.Header.Parameters[HeaderKeys.PLATFORM] = Global.Game.System;
_movieToRecord.Header[HeaderKeys.AUTHOR] = AuthorBox.Text;
_movieToRecord.Header[HeaderKeys.EMULATIONVERSION] = VersionInfo.GetEmuVersion();
_movieToRecord.Header[HeaderKeys.MOVIEVERSION] = HeaderKeys.MovieVersion;
_movieToRecord.Header[HeaderKeys.GUID] = HeaderKeys.NewGuid;
_movieToRecord.Header[HeaderKeys.PLATFORM] = Global.Game.System;
if (Global.Game != null)
{
_movieToRecord.Header.Parameters[HeaderKeys.GAMENAME] = PathManager.FilesystemSafeName(Global.Game);
_movieToRecord.Header.Parameters[HeaderKeys.SHA1] = Global.Game.Hash;
_movieToRecord.Header[HeaderKeys.GAMENAME] = PathManager.FilesystemSafeName(Global.Game);
_movieToRecord.Header[HeaderKeys.SHA1] = Global.Game.Hash;
if (Global.Game.FirmwareHash != null)
{
_movieToRecord.Header.Parameters[HeaderKeys.FIRMWARESHA1] = Global.Game.FirmwareHash;
_movieToRecord.Header[HeaderKeys.FIRMWARESHA1] = Global.Game.FirmwareHash;
}
}
else
{
_movieToRecord.Header.Parameters[HeaderKeys.GAMENAME] = "NULL";
_movieToRecord.Header[HeaderKeys.GAMENAME] = "NULL";
}
if (Global.Emulator.BoardName != null)
{
_movieToRecord.Header.Parameters[HeaderKeys.BOARDNAME] = Global.Emulator.BoardName;
_movieToRecord.Header[HeaderKeys.BOARDNAME] = Global.Emulator.BoardName;
}
if (Global.Emulator is Gameboy)
{
_movieToRecord.Header.Parameters[HeaderKeys.GB_FORCEDMG] = Global.Config.GB_ForceDMG.ToString();
_movieToRecord.Header.Parameters[HeaderKeys.GB_GBA_IN_CGB] = Global.Config.GB_GBACGB.ToString();
_movieToRecord.Header[HeaderKeys.GB_FORCEDMG] = Global.Config.GB_ForceDMG.ToString();
_movieToRecord.Header[HeaderKeys.GB_GBA_IN_CGB] = Global.Config.GB_GBACGB.ToString();
}
if (Global.Emulator is LibsnesCore)
{
_movieToRecord.Header.Parameters[HeaderKeys.SGB] = ((Global.Emulator) as LibsnesCore).IsSGB.ToString();
_movieToRecord.Header[HeaderKeys.SGB] = ((Global.Emulator) as LibsnesCore).IsSGB.ToString();
if ((Global.Emulator as LibsnesCore).DisplayType == DisplayType.PAL)
{
_movieToRecord.Header.Parameters[HeaderKeys.PAL] = "1";
_movieToRecord.Header[HeaderKeys.PAL] = "1";
}
}
else if (Global.Emulator is SMS)
{
if ((Global.Emulator as SMS).DisplayType == DisplayType.PAL)
{
_movieToRecord.Header.Parameters[HeaderKeys.PAL] = "1";
_movieToRecord.Header[HeaderKeys.PAL] = "1";
}
}
else if (Global.Emulator is NES)
{
if ((Global.Emulator as NES).DisplayType == DisplayType.PAL)
{
_movieToRecord.Header.Parameters[HeaderKeys.PAL] = "1";
_movieToRecord.Header[HeaderKeys.PAL] = "1";
}
}
else if (Global.Emulator is ColecoVision)
{
_movieToRecord.Header.Parameters[HeaderKeys.SKIPBIOS] = Global.Config.ColecoSkipBiosIntro.ToString();
_movieToRecord.Header[HeaderKeys.SKIPBIOS] = Global.Config.ColecoSkipBiosIntro.ToString();
}
else if (Global.Emulator is N64)
{
_movieToRecord.Header.Parameters[HeaderKeys.VIDEOPLUGIN] = Global.Config.N64VidPlugin;
_movieToRecord.Header[HeaderKeys.VIDEOPLUGIN] = Global.Config.N64VidPlugin;
if (Global.Config.N64VidPlugin == "Rice")
{
var rice_settings = Global.Config.RicePlugin.GetPluginSettings();
foreach(var setting in rice_settings)
{
_movieToRecord.Header.Parameters[setting.Key] = setting.Value.ToString();
_movieToRecord.Header[setting.Key] = setting.Value.ToString();
}
}
else if (Global.Config.N64VidPlugin == "Glide64")
@ -168,13 +168,13 @@ namespace BizHawk.Client.EmuHawk
var glide_settings = Global.Config.GlidePlugin.GetPluginSettings();
foreach (var setting in glide_settings)
{
_movieToRecord.Header.Parameters[setting.Key] = setting.Value.ToString();
_movieToRecord.Header[setting.Key] = setting.Value.ToString();
}
}
if ((Global.Emulator as N64).DisplayType == DisplayType.PAL)
{
_movieToRecord.Header.Parameters[HeaderKeys.PAL] = "1";
_movieToRecord.Header[HeaderKeys.PAL] = "1";
}
}