diff --git a/BizHawk.MultiClient/BizHawk.MultiClient.csproj b/BizHawk.MultiClient/BizHawk.MultiClient.csproj
index cbc4444871..ba6997d78b 100644
--- a/BizHawk.MultiClient/BizHawk.MultiClient.csproj
+++ b/BizHawk.MultiClient/BizHawk.MultiClient.csproj
@@ -702,6 +702,7 @@
WatchEditor.cs
+
FFmpegWriterForm.cs
diff --git a/BizHawk.MultiClient/BizHawk.MultiClient_v4.5.csproj b/BizHawk.MultiClient/BizHawk.MultiClient_v4.5.csproj
index ec1746a5e4..7d23f5f1c2 100644
--- a/BizHawk.MultiClient/BizHawk.MultiClient_v4.5.csproj
+++ b/BizHawk.MultiClient/BizHawk.MultiClient_v4.5.csproj
@@ -704,6 +704,7 @@
WatchEditor.cs
+
FFmpegWriterForm.cs
diff --git a/BizHawk.MultiClient/tools/Watch/NewRamPoke.cs b/BizHawk.MultiClient/tools/Watch/NewRamPoke.cs
index e5dfe10fd8..8abdaf648f 100644
--- a/BizHawk.MultiClient/tools/Watch/NewRamPoke.cs
+++ b/BizHawk.MultiClient/tools/Watch/NewRamPoke.cs
@@ -65,6 +65,7 @@ namespace BizHawk.MultiClient
DisplayTypeLabel.Text = Watch.DisplayTypeToString(_watchList[0].Type);
BigEndianLabel.Text = _watchList[0].BigEndian ? "Big Endian" : "Little Endian";
SetTitle();
+ SetValueBoxProperties();
}
private void SetValueBoxProperties()
@@ -187,6 +188,13 @@ namespace BizHawk.MultiClient
e.Handled = true;
}
}
+ else if (e.KeyChar == '-')
+ {
+ if (ValueBox.Text.Contains('-'))
+ {
+ e.Handled = true;
+ }
+ }
switch(_watchList[0].Type)
{
diff --git a/BizHawk.MultiClient/tools/Watch/NewRamWatch.cs b/BizHawk.MultiClient/tools/Watch/NewRamWatch.cs
index ab72902cda..0e0463600c 100644
--- a/BizHawk.MultiClient/tools/Watch/NewRamWatch.cs
+++ b/BizHawk.MultiClient/tools/Watch/NewRamWatch.cs
@@ -1,8 +1,6 @@
using System;
-using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
-using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
@@ -21,8 +19,8 @@ namespace BizHawk.MultiClient
public const string DOMAIN = "DomainColumn";
public const string NOTES = "NotesColumn";
- private Dictionary DefaultColumnWidths = new Dictionary()
- {
+ private readonly Dictionary DefaultColumnWidths = new Dictionary
+ {
{ ADDRESS, 60 },
{ VALUE, 59 },
{ PREV, 59 },
@@ -34,8 +32,7 @@ namespace BizHawk.MultiClient
private int defaultWidth;
private int defaultHeight;
- private WatchList Watches = new WatchList(Global.Emulator.MainMemory);
- private string systemID = "NULL";
+ private readonly WatchList Watches = new WatchList(Global.Emulator.MainMemory);
private string _sortedColumn = "";
private bool _sortReverse = false;
@@ -465,7 +462,7 @@ namespace BizHawk.MultiClient
private void AddNewWatch()
{
- WatchEditor we = new WatchEditor()
+ WatchEditor we = new WatchEditor
{
InitialLocation = GetPromptPoint()
};
@@ -489,7 +486,7 @@ namespace BizHawk.MultiClient
if (indexes.Count > 0)
{
- WatchEditor we = new WatchEditor()
+ WatchEditor we = new WatchEditor
{
InitialLocation = GetPromptPoint(),
};
@@ -528,8 +525,8 @@ namespace BizHawk.MultiClient
{
if (SelectedWatches.Any())
{
- NewRamPoke poke = new NewRamPoke()
- {
+ NewRamPoke poke = new NewRamPoke
+ {
InitialLocation = GetPromptPoint()
};
@@ -568,32 +565,14 @@ namespace BizHawk.MultiClient
}
}
- private List SelectedIndexes
- {
- get
- {
- var selected = new List();
- ListView.SelectedIndexCollection indexes = WatchListView.SelectedIndices;
- if (indexes.Count > 0)
- {
- foreach (int index in indexes)
- {
- selected.Add(Watches[index]);
- }
- }
- return selected;
- }
- }
-
-
private void AddColumn(string columnName, bool enabled)
{
if (enabled)
{
if (WatchListView.Columns[columnName] == null)
{
- ColumnHeader column = new ColumnHeader()
- {
+ ColumnHeader column = new ColumnHeader
+ {
Name = columnName,
Text = columnName.Replace("Column", ""),
Width = GetColumnWidth(columnName),
@@ -1028,7 +1007,7 @@ namespace BizHawk.MultiClient
{
Size = new Size(defaultWidth, defaultHeight);
- Global.Config.RamWatchColumnIndexes = new Dictionary()
+ Global.Config.RamWatchColumnIndexes = new Dictionary
{
{ "AddressColumn", 0 },
{ "ValueColumn", 1 },
diff --git a/BizHawk.MultiClient/tools/Watch/Watch.cs b/BizHawk.MultiClient/tools/Watch/Watch.cs
index 85b26b5648..2037f3ef1c 100644
--- a/BizHawk.MultiClient/tools/Watch/Watch.cs
+++ b/BizHawk.MultiClient/tools/Watch/Watch.cs
@@ -1,11 +1,6 @@
using System;
-using System.Text;
using System.Globalization;
-using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.IO;
-using System.Windows.Forms;
namespace BizHawk.MultiClient
{
@@ -290,8 +285,6 @@ namespace BizHawk.MultiClient
public class SeparatorWatch : Watch
{
- public SeparatorWatch() { }
-
public static SeparatorWatch Instance
{
get { return new SeparatorWatch(); }
@@ -334,7 +327,7 @@ namespace BizHawk.MultiClient
public static List ValidTypes
{
- get { return new List() { DisplayType.Separator }; }
+ get { return new List { DisplayType.Separator }; }
}
public override DisplayType Type
@@ -390,7 +383,7 @@ namespace BizHawk.MultiClient
{
get
{
- return new List()
+ return new List
{
DisplayType.Unsigned, DisplayType.Signed, DisplayType.Hex, DisplayType.Binary
};
@@ -403,7 +396,7 @@ namespace BizHawk.MultiClient
{
default:
case DisplayType.Unsigned:
- return ((byte)val).ToString();
+ return val.ToString();
case DisplayType.Signed:
return ((sbyte)val).ToString();
case DisplayType.Hex:
@@ -567,7 +560,7 @@ namespace BizHawk.MultiClient
{
get
{
- return new List()
+ return new List
{
DisplayType.Unsigned, DisplayType.Signed, DisplayType.Hex, DisplayType.FixedPoint_12_4, DisplayType.Binary
};
@@ -596,7 +589,7 @@ namespace BizHawk.MultiClient
case DisplayType.Hex:
return String.Format("{0:X4}", val);
case DisplayType.FixedPoint_12_4:
- return String.Format("{0:F4}", ((double)val / 16.0));
+ return String.Format("{0:F4}", (val / 16.0));
case DisplayType.Binary:
return Convert.ToString(val, 2).PadLeft(16, '0').Insert(8, " ").Insert(4, " ").Insert(14, " ");
}
@@ -753,8 +746,8 @@ namespace BizHawk.MultiClient
{
get
{
- return new List()
- {
+ return new List
+ {
DisplayType.Unsigned, DisplayType.Signed, DisplayType.Hex, DisplayType.FixedPoint_20_12, DisplayType.Float
};
}
@@ -782,10 +775,10 @@ namespace BizHawk.MultiClient
case DisplayType.Hex:
return String.Format("{0:X8}", val);
case DisplayType.FixedPoint_20_12:
- return String.Format("{0:F5}", ((double)val / 4096.0));
+ return String.Format("{0:F5}", (val / 4096.0));
case DisplayType.Float:
byte[] bytes = BitConverter.GetBytes(val);
- float _float = System.BitConverter.ToSingle(bytes, 0);
+ float _float = BitConverter.ToSingle(bytes, 0);
return String.Format("{0:F6}", _float);
}
}
@@ -883,7 +876,7 @@ namespace BizHawk.MultiClient
public string Diff
{
- get { return FormatValue((uint)(_previous - _value)); }
+ get { return FormatValue(_previous - _value); }
}
public string Notes { get; set; }
@@ -916,576 +909,4 @@ namespace BizHawk.MultiClient
}
}
}
-
- public class WatchList : IEnumerable
- {
- private string _currentFilename = "";
-
- public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange };
-
- private List _watchList = new List();
- private MemoryDomain _domain = null;
-
- public WatchList(MemoryDomain domain)
- {
- _domain = domain;
- }
-
- public IEnumerator GetEnumerator()
- {
- return _watchList.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- public int Count
- {
- get { return _watchList.Count; }
- }
-
- public Watch this[int index]
- {
- get
- {
- return _watchList[index];
- }
- set
- {
- _watchList[index] = value;
- }
- }
-
- public int WatchCount
- {
- get
- {
- return _watchList.Count(w => !w.IsSeparator);
- }
- }
-
- public int ItemCount
- {
- get
- {
- return _watchList.Count;
- }
- }
-
- public void OrderWatches(string column, bool reverse)
- {
- switch (column)
- {
- case NewRamWatch.ADDRESS:
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => x.Address ?? 0)
- .ThenBy(x => x.Domain.Name)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ThenBy(x => x.BigEndian)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => x.Address ?? 0)
- .ThenBy(x => x.Domain.Name)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ThenBy(x => x.BigEndian)
- .ToList();
- }
- break;
- case NewRamWatch.VALUE:
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => x.Value ?? 0)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ThenBy(x => x.BigEndian)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => x.Value ?? 0)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ThenBy(x => x.BigEndian)
- .ToList();
- }
- break;
- case NewRamWatch.PREV: //Note: these only work if all entries are detailed objects!
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => (x as IWatchDetails).PreviousStr)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => (x as IWatchDetails).PreviousStr)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- break;
- case NewRamWatch.DIFF:
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => (x as IWatchDetails).Diff)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => (x as IWatchDetails).Diff)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- break;
- case NewRamWatch.CHANGES:
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => (x as IWatchDetails).ChangeCount)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => (x as IWatchDetails).ChangeCount)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- break;
- case NewRamWatch.DOMAIN:
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => x.Domain)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ThenBy(x => x.BigEndian)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => x.Domain)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ThenBy(x => x.BigEndian)
- .ToList();
- }
- break;
- case NewRamWatch.NOTES:
- if (reverse)
- {
- _watchList = _watchList
- .OrderByDescending(x => (x as IWatchDetails).Notes)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- else
- {
- _watchList = _watchList
- .OrderBy(x => (x as IWatchDetails).Notes)
- .ThenBy(x => x.Address ?? 0)
- .ThenBy(x => x.Size)
- .ThenBy(x => x.Type)
- .ToList();
- }
- break;
- }
- }
-
- public string AddressFormatStr
- {
- get
- {
- if (_domain != null)
- {
- return "{0:X" + IntHelpers.GetNumDigits(_domain.Size - 1).ToString() + "}";
- }
- else
- {
- return "";
- }
- }
- }
-
- public void Clear()
- {
- _watchList.Clear();
- Changes = false;
- _currentFilename = "";
- }
-
- public MemoryDomain Domain { get { return _domain; } set { _domain = value; } }
-
- public void UpdateValues()
- {
- var detailedWatches = _watchList.OfType().ToList();
- foreach (var watch in detailedWatches)
- {
- watch.Update();
- }
- }
-
- public void Add(Watch watch)
- {
- _watchList.Add(watch);
- Changes = true;
- }
-
- public void AddRange(IList watches)
- {
- _watchList.AddRange(watches);
- Changes = true;
- }
-
- public void Remove(Watch watch)
- {
- _watchList.Remove(watch);
- Changes = true;
- }
-
- public void Insert(int index, Watch watch)
- {
- _watchList.Insert(index, watch);
- }
-
- public void ClearChangeCounts()
- {
- var detailedWatches = _watchList.OfType().ToList();
- foreach (var watch in detailedWatches)
- {
- watch.ClearChangeCount();
- }
- }
-
- #region File handling logic - probably needs to be its own class
-
- public string CurrentFileName { get { return _currentFilename; } set { _currentFilename = value; } }
- public bool Changes { get; set; }
-
- public bool Save()
- {
- bool result = false;
- if (!String.IsNullOrWhiteSpace(CurrentFileName))
- {
- result = SaveFile();
- }
- else
- {
- result = SaveAs();
- }
-
- if (result)
- {
- Changes = false;
- }
-
- return result;
- }
-
- public bool Load(string path, bool details, bool append)
- {
- bool result = LoadFile(path, details, append);
-
- if (result)
- {
- if (append)
- {
- Changes = true;
- }
- else
- {
- CurrentFileName = path;
- Changes = false;
- }
- }
-
- return result;
- }
-
- public void Reload()
- {
- if (!String.IsNullOrWhiteSpace(CurrentFileName))
- {
- LoadFile(CurrentFileName, true, false);
- Changes = false;
- }
- }
-
- private bool SaveFile()
- {
- if (String.IsNullOrWhiteSpace(CurrentFileName))
- {
- return false;
- }
-
- using (StreamWriter sw = new StreamWriter(CurrentFileName))
- {
- StringBuilder sb = new StringBuilder();
- sb
- .Append("Domain ").AppendLine(_domain.Name)
- .Append("SystemID ").AppendLine(Global.Emulator.SystemId);
-
- foreach (Watch w in _watchList)
- {
- sb
- .Append(String.Format(AddressFormatStr, w.Address)).Append('\t')
- .Append(w.SizeAsChar).Append('\t')
- .Append(w.TypeAsChar).Append('\t')
- .Append(w.BigEndian ? '1' : '0').Append('\t')
- .Append(w.Domain.Name).Append('\t')
- .Append(w is IWatchDetails ? (w as IWatchDetails).Notes : String.Empty)
- .AppendLine();
- }
-
- sw.WriteLine(sb.ToString());
- }
-
- return true;
- }
-
- public bool SaveAs()
- {
- var file = WatchCommon.GetSaveFileFromUser(CurrentFileName);
- if (file != null)
- {
- CurrentFileName = file.FullName;
- return SaveFile();
- }
- else
- {
- return false;
- }
- }
-
- private bool LoadFile(string path, bool details, bool append)
- {
- string domain = "";
- var file = new FileInfo(path);
- if (file.Exists == false) return false;
- bool isBizHawkWatch = true; //Hack to support .wch files from other emulators
- bool isOldBizHawkWatch = false;
- using (StreamReader sr = file.OpenText())
- {
- string line;
-
- if (append == false)
- {
- Clear();
- }
-
- while ((line = sr.ReadLine()) != null)
- {
- //.wch files from other emulators start with a number representing the number of watch, that line can be discarded here
- //Any properly formatted line couldn't possibly be this short anyway, this also takes care of any garbage lines that might be in a file
- if (line.Length < 5)
- {
- isBizHawkWatch = false;
- continue;
- }
-
- if (line.Length >= 6 && line.Substring(0, 6) == "Domain")
- {
- domain = line.Substring(7, line.Length - 7);
- isBizHawkWatch = true;
- }
-
- if (line.Length >= 8 && line.Substring(0, 8) == "SystemID")
- {
- continue;
- }
-
- int numColumns = StringHelpers.HowMany(line, '\t');
- int startIndex;
- if (numColumns == 5)
- {
- //If 5, then this is a post 1.0.5 .wch file
- if (isBizHawkWatch)
- {
- //Do nothing here
- }
- else
- {
- startIndex = line.IndexOf('\t') + 1;
- line = line.Substring(startIndex, line.Length - startIndex); //5 digit value representing the watch position number
- }
- }
- else if (numColumns == 4)
- {
- isOldBizHawkWatch = true;
- }
- else //4 is 1.0.5 and earlier
- {
- continue; //If not 4, something is wrong with this line, ignore it
- }
-
-
-
- //Temporary, rename if kept
- int addr = 0;
- Watch.WatchSize size = Watch.WatchSize.Separator;
- Watch.DisplayType type = Watch.DisplayType.Unsigned;
- bool bigEndian = false;
- MemoryDomain memDomain = Global.Emulator.MainMemory;
- string notes;
-
- string temp = line.Substring(0, line.IndexOf('\t'));
- try
- {
- addr = Int32.Parse(temp, NumberStyles.HexNumber);
- }
- catch
- {
- continue;
- }
-
- startIndex = line.IndexOf('\t') + 1;
- line = line.Substring(startIndex, line.Length - startIndex); //Type
- size = Watch.SizeFromChar(line[0]);
-
-
- startIndex = line.IndexOf('\t') + 1;
- line = line.Substring(startIndex, line.Length - startIndex); //Signed
- type = Watch.DisplayTypeFromChar(line[0]);
-
- startIndex = line.IndexOf('\t') + 1;
- line = line.Substring(startIndex, line.Length - startIndex); //Endian
- try
- {
- startIndex = Int16.Parse(line[0].ToString());
- }
- catch
- {
- continue;
- }
- if (startIndex == 0)
- {
- bigEndian = false;
- }
- else
- {
- bigEndian = true;
- }
-
- if (isBizHawkWatch && !isOldBizHawkWatch)
- {
- startIndex = line.IndexOf('\t') + 1;
- line = line.Substring(startIndex, line.Length - startIndex); //Domain
- temp = line.Substring(0, line.IndexOf('\t'));
- memDomain = Global.Emulator.MemoryDomains[GetDomainPos(temp)];
- }
-
- startIndex = line.IndexOf('\t') + 1;
- notes = line.Substring(startIndex, line.Length - startIndex); //User notes
-
- Watch w = Watch.GenerateWatch(memDomain, addr, size, details);
- w.BigEndian = bigEndian;
- w.Type = type;
- if (w is IWatchDetails)
- {
- (w as IWatchDetails).Notes = notes;
- }
-
- _watchList.Add(w);
- _domain = Global.Emulator.MemoryDomains[GetDomainPos(domain)];
- }
- }
-
- return true;
- }
-
- private static int GetDomainPos(string name)
- {
- //Attempts to find the memory domain by name, if it fails, it defaults to index 0
- for (int x = 0; x < Global.Emulator.MemoryDomains.Count; x++)
- {
- if (Global.Emulator.MemoryDomains[x].Name == name)
- return x;
- }
- return 0;
- }
-
- public static FileInfo GetFileFromUser(string currentFile)
- {
- var ofd = new OpenFileDialog();
- if (currentFile.Length > 0)
- ofd.FileName = Path.GetFileNameWithoutExtension(currentFile);
- ofd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.WatchPath, null);
- ofd.Filter = "Watch Files (*.wch)|*.wch|All Files|*.*";
- ofd.RestoreDirectory = true;
-
- Global.Sound.StopSound();
- var result = ofd.ShowDialog();
- Global.Sound.StartSound();
- if (result != DialogResult.OK)
- return null;
- var file = new FileInfo(ofd.FileName);
- return file;
- }
-
- public static FileInfo GetSaveFileFromUser(string currentFile)
- {
- var sfd = new SaveFileDialog();
- if (currentFile.Length > 0)
- {
- sfd.FileName = Path.GetFileNameWithoutExtension(currentFile);
- sfd.InitialDirectory = Path.GetDirectoryName(currentFile);
- }
- else if (!(Global.Emulator is NullEmulator))
- {
- sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
- sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.WatchPath, null);
- }
- else
- {
- sfd.FileName = "NULL";
- sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.WatchPath, null);
- }
- sfd.Filter = "Watch Files (*.wch)|*.wch|All Files|*.*";
- sfd.RestoreDirectory = true;
- Global.Sound.StopSound();
- var result = sfd.ShowDialog();
- Global.Sound.StartSound();
- if (result != DialogResult.OK)
- return null;
- var file = new FileInfo(sfd.FileName);
- return file;
- }
-
- #endregion
- }
}
diff --git a/BizHawk.MultiClient/tools/Watch/WatchEditor.cs b/BizHawk.MultiClient/tools/Watch/WatchEditor.cs
index 20db7124c2..632256689f 100644
--- a/BizHawk.MultiClient/tools/Watch/WatchEditor.cs
+++ b/BizHawk.MultiClient/tools/Watch/WatchEditor.cs
@@ -10,7 +10,7 @@ namespace BizHawk.MultiClient
{
public enum Mode { New, Duplicate, Edit };
- private List _watchList = new List();
+ private readonly List _watchList = new List();
private Mode _mode = Mode.New;
private bool _loading = true;
private string _addressFormatStr = "{0:X2}";
@@ -102,13 +102,13 @@ namespace BizHawk.MultiClient
switch(_mode)
{
default:
- case WatchEditor.Mode.New:
+ case Mode.New:
Text = "New Watch";
break;
- case WatchEditor.Mode.Edit:
+ case Mode.Edit:
Text = "Edit Watch" + (_watchList.Count > 1 ? "es" : "");
break;
- case WatchEditor.Mode.Duplicate:
+ case Mode.Duplicate:
Text = "Duplicate Watch";
break;
}
@@ -194,12 +194,9 @@ namespace BizHawk.MultiClient
}
}
- var domain = Global.Emulator.MemoryDomains.FirstOrDefault(d => d.Name == DomainDropDown.SelectedItem.ToString());
- if (domain == null)
- {
- domain = Global.Emulator.MainMemory;
- }
- BigEndianCheckBox.Checked = domain.Endian == Endian.Big ? true : false;
+ var domain = Global.Emulator.MemoryDomains.FirstOrDefault(d => d.Name == DomainDropDown.SelectedItem.ToString()) ??
+ Global.Emulator.MainMemory;
+ BigEndianCheckBox.Checked = domain.Endian == Endian.Big;
}
@@ -220,7 +217,7 @@ namespace BizHawk.MultiClient
default:
case Mode.New:
var domain = Global.Emulator.MemoryDomains.FirstOrDefault(d => d.Name == DomainDropDown.SelectedItem.ToString());
- var address = (AddressBox as HexTextBox).ToInt();
+ var address = AddressBox.ToInt();
var notes = NotesBox.Text;
var type = Watch.StringToDisplayType(DisplayTypeDropDown.SelectedItem.ToString());
var bigendian = BigEndianCheckBox.Checked;
@@ -283,7 +280,7 @@ namespace BizHawk.MultiClient
(_watchList[0] as IWatchDetails).Notes = NotesBox.Text;
}
- if (_changedSize = true)
+ if (_changedSize)
{
for(int i = 0; i < _watchList.Count; i++)
{
@@ -313,7 +310,7 @@ namespace BizHawk.MultiClient
{
_watchList.ForEach(x => x.Type = Watch.StringToDisplayType(DisplayTypeDropDown.SelectedItem.ToString()));
}
- if (!(BigEndianCheckBox.CheckState == CheckState.Indeterminate))
+ if (BigEndianCheckBox.CheckState != CheckState.Indeterminate)
{
_watchList.ForEach(x => x.BigEndian = BigEndianCheckBox.Checked);
}
diff --git a/BizHawk.MultiClient/tools/Watch/WatchList.cs b/BizHawk.MultiClient/tools/Watch/WatchList.cs
new file mode 100644
index 0000000000..67893ff526
--- /dev/null
+++ b/BizHawk.MultiClient/tools/Watch/WatchList.cs
@@ -0,0 +1,579 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BizHawk.MultiClient
+{
+ public class WatchList : IEnumerable
+ {
+ private string _currentFilename = "";
+
+ public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange };
+
+ private List _watchList = new List();
+ private MemoryDomain _domain;
+
+ public WatchList(MemoryDomain domain)
+ {
+ _domain = domain;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _watchList.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public int Count
+ {
+ get { return _watchList.Count; }
+ }
+
+ public Watch this[int index]
+ {
+ get
+ {
+ return _watchList[index];
+ }
+ set
+ {
+ _watchList[index] = value;
+ }
+ }
+
+ public int WatchCount
+ {
+ get
+ {
+ return _watchList.Count(w => !w.IsSeparator);
+ }
+ }
+
+ public int ItemCount
+ {
+ get
+ {
+ return _watchList.Count;
+ }
+ }
+
+ public void OrderWatches(string column, bool reverse)
+ {
+ switch (column)
+ {
+ case NewRamWatch.ADDRESS:
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => x.Address ?? 0)
+ .ThenBy(x => x.Domain.Name)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ThenBy(x => x.BigEndian)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Domain.Name)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ThenBy(x => x.BigEndian)
+ .ToList();
+ }
+ break;
+ case NewRamWatch.VALUE:
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => x.Value ?? 0)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ThenBy(x => x.BigEndian)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => x.Value ?? 0)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ThenBy(x => x.BigEndian)
+ .ToList();
+ }
+ break;
+ case NewRamWatch.PREV: //Note: these only work if all entries are detailed objects!
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => (x as IWatchDetails).PreviousStr)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => (x as IWatchDetails).PreviousStr)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ break;
+ case NewRamWatch.DIFF:
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => (x as IWatchDetails).Diff)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => (x as IWatchDetails).Diff)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ break;
+ case NewRamWatch.CHANGES:
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => (x as IWatchDetails).ChangeCount)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => (x as IWatchDetails).ChangeCount)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ break;
+ case NewRamWatch.DOMAIN:
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => x.Domain)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ThenBy(x => x.BigEndian)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => x.Domain)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ThenBy(x => x.BigEndian)
+ .ToList();
+ }
+ break;
+ case NewRamWatch.NOTES:
+ if (reverse)
+ {
+ _watchList = _watchList
+ .OrderByDescending(x => (x as IWatchDetails).Notes)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ else
+ {
+ _watchList = _watchList
+ .OrderBy(x => (x as IWatchDetails).Notes)
+ .ThenBy(x => x.Address ?? 0)
+ .ThenBy(x => x.Size)
+ .ThenBy(x => x.Type)
+ .ToList();
+ }
+ break;
+ }
+ }
+
+ public string AddressFormatStr
+ {
+ get
+ {
+ if (_domain != null)
+ {
+ return "{0:X" + IntHelpers.GetNumDigits(_domain.Size - 1).ToString() + "}";
+ }
+ else
+ {
+ return "";
+ }
+ }
+ }
+
+ public void Clear()
+ {
+ _watchList.Clear();
+ Changes = false;
+ _currentFilename = "";
+ }
+
+ public MemoryDomain Domain { get { return _domain; } set { _domain = value; } }
+
+ public void UpdateValues()
+ {
+ var detailedWatches = _watchList.OfType().ToList();
+ foreach (var watch in detailedWatches)
+ {
+ watch.Update();
+ }
+ }
+
+ public void Add(Watch watch)
+ {
+ _watchList.Add(watch);
+ Changes = true;
+ }
+
+ public void AddRange(IList watches)
+ {
+ _watchList.AddRange(watches);
+ Changes = true;
+ }
+
+ public void Remove(Watch watch)
+ {
+ _watchList.Remove(watch);
+ Changes = true;
+ }
+
+ public void Insert(int index, Watch watch)
+ {
+ _watchList.Insert(index, watch);
+ }
+
+ public void ClearChangeCounts()
+ {
+ var detailedWatches = _watchList.OfType().ToList();
+ foreach (var watch in detailedWatches)
+ {
+ watch.ClearChangeCount();
+ }
+ }
+
+ #region File handling logic - probably needs to be its own class
+
+ public string CurrentFileName { get { return _currentFilename; } set { _currentFilename = value; } }
+ public bool Changes { get; set; }
+
+ public bool Save()
+ {
+ bool result;
+ if (!String.IsNullOrWhiteSpace(CurrentFileName))
+ {
+ result = SaveFile();
+ }
+ else
+ {
+ result = SaveAs();
+ }
+
+ if (result)
+ {
+ Changes = false;
+ }
+
+ return result;
+ }
+
+ public bool Load(string path, bool details, bool append)
+ {
+ bool result = LoadFile(path, details, append);
+
+ if (result)
+ {
+ if (append)
+ {
+ Changes = true;
+ }
+ else
+ {
+ CurrentFileName = path;
+ Changes = false;
+ }
+ }
+
+ return result;
+ }
+
+ public void Reload()
+ {
+ if (!String.IsNullOrWhiteSpace(CurrentFileName))
+ {
+ LoadFile(CurrentFileName, true, false);
+ Changes = false;
+ }
+ }
+
+ private bool SaveFile()
+ {
+ if (String.IsNullOrWhiteSpace(CurrentFileName))
+ {
+ return false;
+ }
+
+ using (StreamWriter sw = new StreamWriter(CurrentFileName))
+ {
+ StringBuilder sb = new StringBuilder();
+ sb
+ .Append("Domain ").AppendLine(_domain.Name)
+ .Append("SystemID ").AppendLine(Global.Emulator.SystemId);
+
+ foreach (Watch w in _watchList)
+ {
+ sb
+ .Append(String.Format(AddressFormatStr, w.Address)).Append('\t')
+ .Append(w.SizeAsChar).Append('\t')
+ .Append(w.TypeAsChar).Append('\t')
+ .Append(w.BigEndian ? '1' : '0').Append('\t')
+ .Append(w.Domain.Name).Append('\t')
+ .Append(w is IWatchDetails ? (w as IWatchDetails).Notes : String.Empty)
+ .AppendLine();
+ }
+
+ sw.WriteLine(sb.ToString());
+ }
+
+ return true;
+ }
+
+ public bool SaveAs()
+ {
+ var file = WatchCommon.GetSaveFileFromUser(CurrentFileName);
+ if (file != null)
+ {
+ CurrentFileName = file.FullName;
+ return SaveFile();
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private bool LoadFile(string path, bool details, bool append)
+ {
+ string domain = "";
+ var file = new FileInfo(path);
+ if (file.Exists == false) return false;
+ bool isBizHawkWatch = true; //Hack to support .wch files from other emulators
+ bool isOldBizHawkWatch = false;
+ using (StreamReader sr = file.OpenText())
+ {
+ string line;
+
+ if (append == false)
+ {
+ Clear();
+ }
+
+ while ((line = sr.ReadLine()) != null)
+ {
+ //.wch files from other emulators start with a number representing the number of watch, that line can be discarded here
+ //Any properly formatted line couldn't possibly be this short anyway, this also takes care of any garbage lines that might be in a file
+ if (line.Length < 5)
+ {
+ isBizHawkWatch = false;
+ continue;
+ }
+
+ if (line.Length >= 6 && line.Substring(0, 6) == "Domain")
+ {
+ domain = line.Substring(7, line.Length - 7);
+ isBizHawkWatch = true;
+ }
+
+ if (line.Length >= 8 && line.Substring(0, 8) == "SystemID")
+ {
+ continue;
+ }
+
+ int numColumns = StringHelpers.HowMany(line, '\t');
+ int startIndex;
+ if (numColumns == 5)
+ {
+ //If 5, then this is a post 1.0.5 .wch file
+ if (isBizHawkWatch)
+ {
+ //Do nothing here
+ }
+ else
+ {
+ startIndex = line.IndexOf('\t') + 1;
+ line = line.Substring(startIndex, line.Length - startIndex); //5 digit value representing the watch position number
+ }
+ }
+ else if (numColumns == 4)
+ {
+ isOldBizHawkWatch = true;
+ }
+ else //4 is 1.0.5 and earlier
+ {
+ continue; //If not 4, something is wrong with this line, ignore it
+ }
+
+
+
+ //Temporary, rename if kept
+ int addr;
+ bool bigEndian;
+ MemoryDomain memDomain = Global.Emulator.MainMemory;
+
+ string temp = line.Substring(0, line.IndexOf('\t'));
+ try
+ {
+ addr = Int32.Parse(temp, NumberStyles.HexNumber);
+ }
+ catch
+ {
+ continue;
+ }
+
+ startIndex = line.IndexOf('\t') + 1;
+ line = line.Substring(startIndex, line.Length - startIndex); //Type
+ Watch.WatchSize size = Watch.SizeFromChar(line[0]);
+
+
+ startIndex = line.IndexOf('\t') + 1;
+ line = line.Substring(startIndex, line.Length - startIndex); //Signed
+ Watch.DisplayType type = Watch.DisplayTypeFromChar(line[0]);
+
+ startIndex = line.IndexOf('\t') + 1;
+ line = line.Substring(startIndex, line.Length - startIndex); //Endian
+ try
+ {
+ startIndex = Int16.Parse(line[0].ToString());
+ }
+ catch
+ {
+ continue;
+ }
+ if (startIndex == 0)
+ {
+ bigEndian = false;
+ }
+ else
+ {
+ bigEndian = true;
+ }
+
+ if (isBizHawkWatch && !isOldBizHawkWatch)
+ {
+ startIndex = line.IndexOf('\t') + 1;
+ line = line.Substring(startIndex, line.Length - startIndex); //Domain
+ temp = line.Substring(0, line.IndexOf('\t'));
+ memDomain = Global.Emulator.MemoryDomains[GetDomainPos(temp)];
+ }
+
+ startIndex = line.IndexOf('\t') + 1;
+ string notes = line.Substring(startIndex, line.Length - startIndex);
+
+ Watch w = Watch.GenerateWatch(memDomain, addr, size, details);
+ w.BigEndian = bigEndian;
+ w.Type = type;
+ if (w is IWatchDetails)
+ {
+ (w as IWatchDetails).Notes = notes;
+ }
+
+ _watchList.Add(w);
+ _domain = Global.Emulator.MemoryDomains[GetDomainPos(domain)];
+ }
+ }
+
+ return true;
+ }
+
+ private static int GetDomainPos(string name)
+ {
+ //Attempts to find the memory domain by name, if it fails, it defaults to index 0
+ for (int x = 0; x < Global.Emulator.MemoryDomains.Count; x++)
+ {
+ if (Global.Emulator.MemoryDomains[x].Name == name)
+ return x;
+ }
+ return 0;
+ }
+
+ public static FileInfo GetFileFromUser(string currentFile)
+ {
+ var ofd = new OpenFileDialog();
+ if (currentFile.Length > 0)
+ ofd.FileName = Path.GetFileNameWithoutExtension(currentFile);
+ ofd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.WatchPath, null);
+ ofd.Filter = "Watch Files (*.wch)|*.wch|All Files|*.*";
+ ofd.RestoreDirectory = true;
+
+ Global.Sound.StopSound();
+ var result = ofd.ShowDialog();
+ Global.Sound.StartSound();
+ if (result != DialogResult.OK)
+ return null;
+ var file = new FileInfo(ofd.FileName);
+ return file;
+ }
+
+ public static FileInfo GetSaveFileFromUser(string currentFile)
+ {
+ var sfd = new SaveFileDialog();
+ if (currentFile.Length > 0)
+ {
+ sfd.FileName = Path.GetFileNameWithoutExtension(currentFile);
+ sfd.InitialDirectory = Path.GetDirectoryName(currentFile);
+ }
+ else if (!(Global.Emulator is NullEmulator))
+ {
+ sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
+ sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.WatchPath, null);
+ }
+ else
+ {
+ sfd.FileName = "NULL";
+ sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.WatchPath, null);
+ }
+ sfd.Filter = "Watch Files (*.wch)|*.wch|All Files|*.*";
+ sfd.RestoreDirectory = true;
+ Global.Sound.StopSound();
+ var result = sfd.ShowDialog();
+ Global.Sound.StartSound();
+ if (result != DialogResult.OK)
+ return null;
+ var file = new FileInfo(sfd.FileName);
+ return file;
+ }
+
+ #endregion
+ }
+}