A round of code cleanup on Rewind and some other misc things in Client.Common

This commit is contained in:
adelikat 2013-12-30 01:17:11 +00:00
parent 134783ff36
commit 16f7c7fcdc
9 changed files with 383 additions and 315 deletions

View File

@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@ -7,8 +8,8 @@ namespace BizHawk.Client.Common
[Newtonsoft.Json.JsonObject]
public class RecentFiles : IEnumerable
{
public int MAX_RECENT_FILES { get; private set; } //Maximum number of files
public List<string> recentlist { get; private set; } //List of recent files
public int MAX_RECENT_FILES { get; private set; } // Maximum number of files
public List<string> recentlist { get; private set; } // List of recent files
public bool AutoLoad = false;
@ -46,13 +47,14 @@ namespace BizHawk.Client.Common
public void Add(string newFile)
{
for (int x = 0; x < recentlist.Count; x++)
for (int i = 0; i < recentlist.Count; i++)
{
if (string.Compare(newFile, recentlist[x]) == 0)
if (String.Compare(newFile, recentlist[i], StringComparison.CurrentCultureIgnoreCase) == 0)
{
recentlist.Remove(newFile); //intentionally keeps iterating after this to remove duplicate instances, though those should never exist in the first place
recentlist.Remove(newFile); // intentionally keeps iterating after this to remove duplicate instances, though those should never exist in the first place
}
}
recentlist.Insert(0, newFile);
if (recentlist.Count > MAX_RECENT_FILES)
{
@ -62,15 +64,16 @@ namespace BizHawk.Client.Common
public bool Remove(string newFile)
{
bool removed = false;
for (int x = 0; x < recentlist.Count; x++)
var removed = false;
for (int i = 0; i < recentlist.Count; i++)
{
if (string.Compare(newFile, recentlist[x]) == 0)
if (String.Compare(newFile, recentlist[i], StringComparison.CurrentCultureIgnoreCase) == 0)
{
recentlist.Remove(newFile); //intentionally keeps iterating after this to remove duplicate instances, though those should never exist in the first place
recentlist.Remove(newFile); // intentionally keeps iterating after this to remove duplicate instances, though those should never exist in the first place
removed = true;
}
}
return removed;
}
@ -89,7 +92,7 @@ namespace BizHawk.Client.Common
}
else
{
return "";
return String.Empty;
}
}
}

View File

@ -65,7 +65,7 @@ namespace BizHawk.Client.Common
public bool Deterministic { get; private set; }
public class RomErrorArgs
public class RomErrorArgs : EventArgs
{
// TODO: think about naming here, what to pass, a lot of potential good information about what went wrong could go here!
public RomErrorArgs(string message, string systemId)
@ -78,7 +78,7 @@ namespace BizHawk.Client.Common
public string AttemptedCoreLoad { get; private set; }
}
public class SettingsLoadArgs
public class SettingsLoadArgs : EventArgs
{
public object Settings { get; set; }
public Type Core { get; private set; }

View File

@ -1,6 +1,6 @@
using System;
using System.Threading;
using System.Collections.Concurrent;
using System.Threading;
namespace BizHawk.Client.Common
{
@ -13,10 +13,11 @@ namespace BizHawk.Client.Common
// which will kill N64 for sure...
public static bool IsThreaded = false;
private readonly ConcurrentQueue<Job> Jobs = new ConcurrentQueue<Job>();
private EventWaitHandle _ewh, _ewh2;
private Thread _thread;
private Rewinder _rewinder;
private readonly ConcurrentQueue<Job> _jobs = new ConcurrentQueue<Job>();
private readonly EventWaitHandle _ewh;
private readonly EventWaitHandle _ewh2;
private readonly Thread _thread;
private readonly Rewinder _rewinder;
public RewindThreader(Rewinder rewinder, bool isThreaded)
{
@ -27,8 +28,7 @@ namespace BizHawk.Client.Common
{
_ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
_ewh2 = new EventWaitHandle(false, EventResetMode.AutoReset);
_thread = new Thread(ThreadProc);
_thread.IsBackground = true;
_thread = new Thread(ThreadProc) { IsBackground = true };
_thread.Start();
}
}
@ -40,9 +40,8 @@ namespace BizHawk.Client.Common
return;
}
var job = new Job();
job.Type = JobType.Abort;
Jobs.Enqueue(job);
var job = new Job { Type = JobType.Abort };
_jobs.Enqueue(job);
_ewh.Set();
_thread.Join();
@ -50,15 +49,49 @@ namespace BizHawk.Client.Common
_ewh2.Dispose();
}
void ThreadProc()
public void Rewind(int frames)
{
for (; ; )
if (!IsThreaded)
{
_rewinder._RunRewind(frames);
return;
}
var job = new Job
{
Type = JobType.Rewind,
Frames = frames
};
_jobs.Enqueue(job);
_ewh.Set();
_ewh2.WaitOne();
}
public void Capture(byte[] coreSavestate)
{
if (!IsThreaded)
{
_rewinder.RunCapture(coreSavestate);
return;
}
var job = new Job
{
Type = JobType.Capture,
CoreState = coreSavestate
};
DoSafeEnqueue(job);
}
private void ThreadProc()
{
for (;; )
{
_ewh.WaitOne();
while (Jobs.Count != 0)
while (_jobs.Count != 0)
{
Job job = null;
if (Jobs.TryDequeue(out job))
Job job;
if (_jobs.TryDequeue(out job))
{
if (job.Type == JobType.Abort)
{
@ -80,59 +113,29 @@ namespace BizHawk.Client.Common
}
}
public void Rewind(int frames)
private void DoSafeEnqueue(Job job)
{
if (!IsThreaded)
{
_rewinder._RunRewind(frames);
return;
}
var job = new Job();
job.Type = JobType.Rewind;
job.Frames = frames;
Jobs.Enqueue(job);
_ewh.Set();
_ewh2.WaitOne();
}
void DoSafeEnqueue(Job job)
{
Jobs.Enqueue(job);
_jobs.Enqueue(job);
_ewh.Set();
//just in case... we're getting really behind.. slow it down here
//if this gets backed up too much, then the rewind will seem to malfunction since it requires all the captures in the queue to complete first
while (Jobs.Count > 15)
// just in case... we're getting really behind.. slow it down here
// if this gets backed up too much, then the rewind will seem to malfunction since it requires all the captures in the queue to complete first
while (_jobs.Count > 15)
{
Thread.Sleep(0);
}
}
public void Capture(byte[] coreSavestate)
{
if (!IsThreaded)
{
_rewinder.RunCapture(coreSavestate);
return;
}
var job = new Job();
job.Type = JobType.Capture;
job.CoreState = coreSavestate;
DoSafeEnqueue(job);
}
private enum JobType
{
Capture, Rewind, Abort
}
private class Job
private sealed class Job
{
public JobType Type;
public byte[] CoreState;
public int Frames;
public JobType Type { get; set; }
public byte[] CoreState { get; set; }
public int Frames { get; set; }
}
}
}

View File

@ -5,79 +5,81 @@ namespace BizHawk.Client.Common
{
public class Rewinder
{
public bool RewindActive = true;
public Rewinder()
{
RewindActive = true;
}
private StreamBlobDatabase RewindBuffer;
private RewindThreader RewindThread;
private byte[] LastState;
private bool RewindImpossible;
private int RewindFrequency = 1;
private bool RewindDeltaEnable = false;
private byte[] RewindFellationBuf;
private byte[] TempBuf = new byte[0];
private StreamBlobDatabase _rewindBuffer;
private RewindThreader _rewindThread;
private byte[] _lastState;
private bool _rewindImpossible;
private int _rewindFrequency = 1;
private bool _rewindDeltaEnable;
private byte[] _rewindFellationBuf;
private byte[] _tempBuf = new byte[0];
public Action<string> MessageCallback;
public Action<string> MessageCallback { get; set; }
public bool RewindActive { get; set; }
// TODO: make RewindBuf never be null
public float FullnessRatio
{
get { return RewindBuffer.FullnessRatio; }
get { return _rewindBuffer.FullnessRatio; }
}
public int Count
{
get { return RewindBuffer != null ? RewindBuffer.Count : 0; }
get { return _rewindBuffer != null ? _rewindBuffer.Count : 0; }
}
public long Size
{
get { return RewindBuffer != null ? RewindBuffer.Size : 0; }
get { return _rewindBuffer != null ? _rewindBuffer.Size : 0; }
}
public int BufferCount
{
get { return RewindBuffer != null ? RewindBuffer.Count : 0; }
get { return _rewindBuffer != null ? _rewindBuffer.Count : 0; }
}
public bool HasBuffer
{
get { return RewindBuffer != null; }
get { return _rewindBuffer != null; }
}
// TOOD: this should not be parameterless?! It is only possible due to passing a static context in
public void CaptureRewindState()
{
if (RewindImpossible)
if (_rewindImpossible)
{
return;
}
if (LastState == null)
if (_lastState == null)
{
DoRewindSettings();
}
//log a frame
if (LastState != null && Global.Emulator.Frame % RewindFrequency == 0)
// log a frame
if (_lastState != null && Global.Emulator.Frame % _rewindFrequency == 0)
{
byte[] CurrentState = Global.Emulator.SaveStateBinary();
RewindThread.Capture(CurrentState);
_rewindThread.Capture(Global.Emulator.SaveStateBinary());
}
}
public void DoRewindSettings()
{
// This is the first frame. Capture the state, and put it in LastState for future deltas to be compared against.
LastState = (byte[])Global.Emulator.SaveStateBinary().Clone();
_lastState = (byte[])Global.Emulator.SaveStateBinary().Clone();
int state_size = 0;
if (LastState.Length >= Global.Config.Rewind_LargeStateSize)
int state_size;
if (_lastState.Length >= Global.Config.Rewind_LargeStateSize)
{
SetRewindParams(Global.Config.RewindEnabledLarge, Global.Config.RewindFrequencyLarge);
state_size = 3;
}
else if (LastState.Length >= Global.Config.Rewind_MediumStateSize)
else if (_lastState.Length >= Global.Config.Rewind_MediumStateSize)
{
SetRewindParams(Global.Config.RewindEnabledMedium, Global.Config.RewindFrequencyMedium);
state_size = 2;
@ -88,7 +90,7 @@ namespace BizHawk.Client.Common
state_size = 1;
}
bool rewind_enabled = false;
var rewind_enabled = false;
if (state_size == 1)
{
rewind_enabled = Global.Config.RewindEnabledSmall;
@ -102,31 +104,31 @@ namespace BizHawk.Client.Common
rewind_enabled = Global.Config.RewindEnabledLarge;
}
RewindDeltaEnable = Global.Config.Rewind_UseDelta;
_rewindDeltaEnable = Global.Config.Rewind_UseDelta;
if (rewind_enabled)
{
long cap = Global.Config.Rewind_BufferSize * (long)1024 * (long)1024;
var cap = Global.Config.Rewind_BufferSize * (long)1024 * 1024;
if (RewindBuffer != null)
if (_rewindBuffer != null)
{
RewindBuffer.Dispose();
_rewindBuffer.Dispose();
}
RewindBuffer = new StreamBlobDatabase(Global.Config.Rewind_OnDisk, cap, BufferManage);
_rewindBuffer = new StreamBlobDatabase(Global.Config.Rewind_OnDisk, cap, BufferManage);
if (RewindThread != null)
if (_rewindThread != null)
{
RewindThread.Dispose();
_rewindThread.Dispose();
}
RewindThread = new RewindThreader(this, Global.Config.Rewind_IsThreaded);
_rewindThread = new RewindThreader(this, Global.Config.Rewind_IsThreaded);
}
}
public void Rewind(int frames)
{
RewindThread.Rewind(frames);
_rewindThread.Rewind(frames);
}
// TODO remove me
@ -134,12 +136,12 @@ namespace BizHawk.Client.Common
{
for (int i = 0; i < frames; i++)
{
if (RewindBuffer.Count == 0 || (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.InputLogLength == 0))
if (_rewindBuffer.Count == 0 || (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.InputLogLength == 0))
{
return;
}
if (LastState.Length < 0x10000)
if (_lastState.Length < 0x10000)
{
Rewind64K();
}
@ -153,16 +155,9 @@ namespace BizHawk.Client.Common
// TODO: only run by RewindThreader, refactor
public void RunCapture(byte[] coreSavestate)
{
if (RewindDeltaEnable)
if (_rewindDeltaEnable)
{
if (LastState.Length <= 0x10000)
{
CaptureRewindStateDelta(coreSavestate, true);
}
else
{
CaptureRewindStateDelta(coreSavestate, false);
}
CaptureRewindStateDelta(coreSavestate, _lastState.Length <= 0x10000);
}
else
{
@ -172,13 +167,13 @@ namespace BizHawk.Client.Common
public void ResetRewindBuffer()
{
if (RewindBuffer != null)
if (_rewindBuffer != null)
{
RewindBuffer.Clear();
_rewindBuffer.Clear();
}
RewindImpossible = false;
LastState = null;
_rewindImpossible = false;
_lastState = null;
}
private void DoMessage(string message)
@ -196,17 +191,17 @@ namespace BizHawk.Client.Common
DoMessage("Rewind " + (enabled ? "Enabled" : "Disabled"));
}
if (RewindFrequency != frequency && enabled)
if (_rewindFrequency != frequency && enabled)
{
DoMessage("Rewind frequency set to " + frequency);
}
RewindActive = enabled;
RewindFrequency = frequency;
_rewindFrequency = frequency;
if (!RewindActive)
{
LastState = null;
_lastState = null;
}
}
@ -214,69 +209,69 @@ namespace BizHawk.Client.Common
{
if (allocate)
{
//if we have an appropriate buffer free, return it
if (RewindFellationBuf != null && RewindFellationBuf.LongLength == size)
// if we have an appropriate buffer free, return it
if (_rewindFellationBuf != null && _rewindFellationBuf.LongLength == size)
{
byte[] ret = RewindFellationBuf;
RewindFellationBuf = null;
var ret = _rewindFellationBuf;
_rewindFellationBuf = null;
return ret;
}
//otherwise, allocate it
// otherwise, allocate it
return new byte[size];
}
else
{
RewindFellationBuf = inbuf;
_rewindFellationBuf = inbuf;
return null;
}
}
private void CaptureRewindStateNonDelta(byte[] CurrentState)
private void CaptureRewindStateNonDelta(byte[] currentState)
{
long offset = RewindBuffer.Enqueue(0, CurrentState.Length + 1);
Stream stream = RewindBuffer.Stream;
long offset = _rewindBuffer.Enqueue(0, currentState.Length + 1);
var stream = _rewindBuffer.Stream;
stream.Position = offset;
//write the header for a non-delta frame
stream.WriteByte(1); //i.e. true
stream.Write(CurrentState, 0, CurrentState.Length);
// write the header for a non-delta frame
stream.WriteByte(1); // i.e. true
stream.Write(currentState, 0, currentState.Length);
}
private void CaptureRewindStateDelta(byte[] CurrentState, bool isSmall)
private void CaptureRewindStateDelta(byte[] currentState, bool isSmall)
{
//in case the state sizes mismatch, capture a full state rather than trying to do anything clever
if (CurrentState.Length != LastState.Length)
// in case the state sizes mismatch, capture a full state rather than trying to do anything clever
if (currentState.Length != _lastState.Length)
{
CaptureRewindStateNonDelta(CurrentState);
CaptureRewindStateNonDelta(currentState);
return;
}
int beginChangeSequence = -1;
bool inChangeSequence = false;
MemoryStream ms;
var beginChangeSequence = -1;
var inChangeSequence = false;
// try to set up the buffer in advance so we dont ever have exceptions in here
if (TempBuf.Length < CurrentState.Length)
if (_tempBuf.Length < currentState.Length)
{
TempBuf = new byte[CurrentState.Length * 2];
_tempBuf = new byte[currentState.Length * 2];
}
ms = new MemoryStream(TempBuf, 0, TempBuf.Length, true, true);
var ms = new MemoryStream(_tempBuf, 0, _tempBuf.Length, true, true);
RETRY:
try
{
var writer = new BinaryWriter(ms);
writer.Write(false); // delta state
for (int i = 0; i < CurrentState.Length; i++)
for (int i = 0; i < currentState.Length; i++)
{
if (inChangeSequence == false)
{
if (i >= LastState.Length)
if (i >= _lastState.Length)
{
continue;
}
if (CurrentState[i] == LastState[i])
if (currentState[i] == _lastState[i])
{
continue;
}
@ -286,7 +281,7 @@ namespace BizHawk.Client.Common
continue;
}
if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1)
if (i - beginChangeSequence == 254 || i == currentState.Length - 1)
{
writer.Write((byte)(i - beginChangeSequence + 1));
if (isSmall)
@ -298,12 +293,12 @@ namespace BizHawk.Client.Common
writer.Write(beginChangeSequence);
}
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1);
writer.Write(_lastState, beginChangeSequence, i - beginChangeSequence + 1);
inChangeSequence = false;
continue;
}
if (CurrentState[i] == LastState[i])
if (currentState[i] == _lastState[i])
{
writer.Write((byte)(i - beginChangeSequence));
if (isSmall)
@ -315,30 +310,30 @@ namespace BizHawk.Client.Common
writer.Write(beginChangeSequence);
}
writer.Write(LastState, beginChangeSequence, i - beginChangeSequence);
writer.Write(_lastState, beginChangeSequence, i - beginChangeSequence);
inChangeSequence = false;
}
}
}
catch (NotSupportedException)
{
//ok... we had an exception after all
//if we did actually run out of room in the memorystream, then try it again with a bigger buffer
TempBuf = new byte[TempBuf.Length * 2];
// ok... we had an exception after all
// if we did actually run out of room in the memorystream, then try it again with a bigger buffer
_tempBuf = new byte[_tempBuf.Length * 2];
goto RETRY;
}
if (LastState != null && LastState.Length == CurrentState.Length)
if (_lastState != null && _lastState.Length == currentState.Length)
{
Buffer.BlockCopy(CurrentState, 0, LastState, 0, LastState.Length);
Buffer.BlockCopy(currentState, 0, _lastState, 0, _lastState.Length);
}
else
{
LastState = (byte[])CurrentState.Clone();
_lastState = (byte[])currentState.Clone();
}
var seg = new ArraySegment<byte>(TempBuf, 0, (int)ms.Position);
RewindBuffer.Push(seg);
var seg = new ArraySegment<byte>(_tempBuf, 0, (int)ms.Position);
_rewindBuffer.Push(seg);
}
private void RewindLarge()
@ -353,23 +348,21 @@ namespace BizHawk.Client.Common
private void RewindDelta(bool isSmall)
{
var ms = RewindBuffer.PopMemoryStream();
var ms = _rewindBuffer.PopMemoryStream();
var reader = new BinaryReader(ms);
bool fullstate = reader.ReadBoolean();
var fullstate = reader.ReadBoolean();
if (fullstate)
{
Global.Emulator.LoadStateBinary(reader);
}
else
{
var output = new MemoryStream(LastState);
var output = new MemoryStream(_lastState);
while (ms.Position < ms.Length - 1)
{
byte len = reader.ReadByte();
int offset;
if(isSmall)
offset = reader.ReadUInt16();
else offset = reader.ReadInt32();
var len = reader.ReadByte();
int offset = isSmall ? reader.ReadUInt16() : reader.ReadInt32();
output.Position = offset;
output.Write(ms.GetBuffer(), (int)ms.Position, len);
ms.Position += len;

View File

@ -1,8 +1,6 @@
using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO;
namespace BizHawk.Client.Common
{
@ -25,7 +23,7 @@ namespace BizHawk.Client.Common
_mCapacity = capacity;
if (onDisk)
{
var path = Path.Combine(System.IO.Path.GetTempPath(), "bizhawk.rewindbuf-pid" + System.Diagnostics.Process.GetCurrentProcess().Id + "-" + Guid.NewGuid().ToString());
var path = Path.Combine(Path.GetTempPath(), "bizhawk.rewindbuf-pid" + System.Diagnostics.Process.GetCurrentProcess().Id + "-" + Guid.NewGuid());
// I checked the DeleteOnClose operation to make sure it cleans up when the process is aborted, and it seems to.
// Otherwise we would have a more complex tempfile management problem here.
@ -40,7 +38,7 @@ namespace BizHawk.Client.Common
}
/// <summary>
/// Returns the amount of the buffer that's used
/// Gets the amount of the buffer that's used
/// </summary>
public long Size { get { return _mSize; } }
@ -50,12 +48,12 @@ namespace BizHawk.Client.Common
public float FullnessRatio { get { return (float)((double)Size / (double)_mCapacity); } }
/// <summary>
/// the number of frames stored here
/// Gets the number of frames stored here
/// </summary>
public int Count { get { return _mBookmarks.Count; } }
/// <summary>
/// The underlying stream to
/// Gets the underlying stream to
/// </summary>
public Stream Stream { get { return _mStream; } }
@ -141,7 +139,7 @@ namespace BizHawk.Client.Common
CLEANUP:
// while the head impinges on tail items, discard them
for (; ; )
for (;;)
{
if (_mTail == null)
{
@ -150,12 +148,15 @@ namespace BizHawk.Client.Common
if (_mHead.Value.EndExclusive > _mTail.Value.Index && _mHead.Value.Index <= _mTail.Value.Index)
{
LinkedListNode<ListItem> nextTail = _mTail.Next;
var nextTail = _mTail.Next;
_mSize -= _mTail.Value.Length;
_mBookmarks.Remove(_mTail);
_mTail = nextTail;
}
else break;
else
{
break;
}
}
return _mHead.Value.Index;
@ -177,12 +178,7 @@ namespace BizHawk.Client.Common
_mTail = null;
}
_mHead = nextHead;
if (_mHead == null)
{
_mHead = _mBookmarks.Last;
}
_mHead = nextHead ?? _mBookmarks.Last;
return ret;
}
@ -196,18 +192,14 @@ namespace BizHawk.Client.Common
var ret = _mTail.Value;
_mSize -= ret.Length;
LinkedListNode<ListItem> nextTail = _mTail.Next;
var nextTail = _mTail.Next;
_mBookmarks.Remove(_mTail);
if (_mTail == _mHead)
{
_mHead = null;
}
_mTail = nextTail;
if (_mTail == null)
{
_mTail = _mBookmarks.First;
}
_mTail = nextTail ?? _mBookmarks.First;
return ret;
}
@ -222,7 +214,7 @@ namespace BizHawk.Client.Common
int ts = _mTail.Value.Timestamp;
LinkedListNode<ListItem> curr = _mTail;
for (; ; )
for (;;)
{
if (curr == null)
{

View File

@ -18,12 +18,13 @@ namespace BizHawk.Client.Common
{
return _changes;
}
set
{
_changes = value;
if (value)
{
CheatChanged(Cheat.Separator); //Pass a dummy, no cheat invoked this change
CheatChanged(Cheat.Separator); // Pass a dummy, no cheat invoked this change
}
}
}
@ -49,10 +50,7 @@ namespace BizHawk.Client.Common
public void Pulse()
{
foreach(var cheat in _cheatList)
{
cheat.Pulse();
}
_cheatList.ForEach(cheat => cheat.Pulse());
}
/// <summary>
@ -106,7 +104,6 @@ namespace BizHawk.Client.Common
if (cheat.IsSeparator)
{
_cheatList.Add(cheat);
}
else
{
@ -115,6 +112,7 @@ namespace BizHawk.Client.Common
{
_cheatList.Remove(Global.CheatList.FirstOrDefault(x => x.Domain == cheat.Domain && x.Address == cheat.Address));
}
_cheatList.Add(cheat);
}
@ -138,7 +136,7 @@ namespace BizHawk.Client.Common
public bool Remove(Cheat c)
{
bool result = _cheatList.Remove(c);
var result = _cheatList.Remove(c);
if (result)
{
Changes = true;
@ -152,7 +150,6 @@ namespace BizHawk.Client.Common
public bool Remove(Watch w)
{
var cheat = _cheatList.FirstOrDefault(x => x.Domain == w.Domain && x.Address == w.Address);
if (cheat != null)
{
@ -184,6 +181,7 @@ namespace BizHawk.Client.Common
{
_cheatList.Remove(cheat);
}
Changes = true;
}
@ -254,15 +252,15 @@ namespace BizHawk.Client.Common
{
try
{
FileInfo file = new FileInfo(path);
var file = new FileInfo(path);
if (file.Directory != null && !file.Directory.Exists)
{
file.Directory.Create();
}
using (StreamWriter sw = new StreamWriter(path))
using (var sw = new StreamWriter(path))
{
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
foreach (var cheat in _cheatList)
{
@ -272,7 +270,7 @@ namespace BizHawk.Client.Common
}
else
{
//Set to hex for saving
// Set to hex for saving
cheat.SetType(Watch.DisplayType.Hex);
sb
@ -316,7 +314,7 @@ namespace BizHawk.Client.Common
_currentFileName = path;
}
using (StreamReader sr = file.OpenText())
using (var sr = file.OpenText())
{
if (!append)
{
@ -335,15 +333,18 @@ namespace BizHawk.Client.Common
else
{
int? compare;
Watch.WatchSize size = Watch.WatchSize.Byte;
Watch.DisplayType type = Watch.DisplayType.Hex;
bool BIGENDIAN = false;
var size = Watch.WatchSize.Byte;
var type = Watch.DisplayType.Hex;
var bigendian = false;
if (s.Length < 6)
{
continue;
}
if (s.Length < 6) continue;
string[] vals = s.Split('\t');
int ADDR = Int32.Parse(vals[0], NumberStyles.HexNumber);
int value = Int32.Parse(vals[1], NumberStyles.HexNumber);
var vals = s.Split('\t');
var address = Int32.Parse(vals[0], NumberStyles.HexNumber);
var value = Int32.Parse(vals[1], NumberStyles.HexNumber);
if (vals[2] == "N")
{
@ -353,28 +354,29 @@ namespace BizHawk.Client.Common
{
compare = Int32.Parse(vals[2], NumberStyles.HexNumber);
}
MemoryDomain domain = Global.Emulator.MemoryDomains[vals[3]];
bool ENABLED = vals[4] == "1";
string name = vals[5];
//For backwards compatibility, don't assume these values exist
var domain = Global.Emulator.MemoryDomains[vals[3]];
var enabled = vals[4] == "1";
var name = vals[5];
// For backwards compatibility, don't assume these values exist
if (vals.Length > 6)
{
size = Watch.SizeFromChar(vals[6][0]);
type = Watch.DisplayTypeFromChar(vals[7][0]);
BIGENDIAN = vals[8] == "1";
bigendian = vals[8] == "1";
}
Watch w = Watch.GenerateWatch(
var watch = Watch.GenerateWatch(
domain,
ADDR,
address,
size,
type,
name,
BIGENDIAN
bigendian
);
Add(new Cheat(w, value, compare, !Global.Config.DisableCheatsOnLoad && ENABLED));
Add(new Cheat(watch, value, compare, !Global.Config.DisableCheatsOnLoad && enabled));
}
}
catch
@ -412,6 +414,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case ADDRESS:
if (reverse)
@ -428,6 +431,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Name)
.ToList();
}
break;
case VALUE:
if (reverse)
@ -446,6 +450,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case COMPARE:
if (reverse)
@ -464,6 +469,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case ON:
if (reverse)
@ -482,6 +488,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case DOMAIN:
if (reverse)
@ -500,6 +507,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case SIZE:
if (reverse)
@ -518,6 +526,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case ENDIAN:
if (reverse)
@ -536,6 +545,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
case TYPE:
if (reverse)
@ -554,11 +564,12 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Address ?? 0)
.ToList();
}
break;
}
}
public class CheatListEventArgs
public class CheatListEventArgs : EventArgs
{
public CheatListEventArgs(Cheat c)
{
@ -579,6 +590,7 @@ namespace BizHawk.Client.Common
{
Changed(this, new CheatListEventArgs(sender as Cheat));
}
_changes = true;
}

View File

@ -9,7 +9,7 @@ namespace BizHawk.Client.Common
{
public class RamSearchEngine
{
public enum ComparisonOperator { Equal, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, NotEqual, DifferentBy };
public enum ComparisonOperator { Equal, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, NotEqual, DifferentBy }
public enum Compare { Previous, SpecificValue, SpecificAddress, Changes, Difference }
private int? _differentBy;
@ -72,14 +72,14 @@ namespace BizHawk.Client.Common
case Watch.WatchSize.Word:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
for (int i = 0; i < domain.Size; i += (_settings.CheckMisAligned ? 1 : 2))
for (int i = 0; i < domain.Size; i += _settings.CheckMisAligned ? 1 : 2)
{
_watchList.Add(new MiniWordWatchDetailed(domain, i, _settings.BigEndian));
}
}
else
{
for (int i = 0; i < domain.Size; i += (_settings.CheckMisAligned ? 1 : 2))
for (int i = 0; i < domain.Size; i += _settings.CheckMisAligned ? 1 : 2)
{
_watchList.Add(new MiniWordWatch(domain, i, _settings.BigEndian));
}
@ -89,14 +89,14 @@ namespace BizHawk.Client.Common
case Watch.WatchSize.DWord:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
for (int i = 0; i < domain.Size; i += (_settings.CheckMisAligned ? 1 : 4))
for (int i = 0; i < domain.Size; i += _settings.CheckMisAligned ? 1 : 4)
{
_watchList.Add(new MiniDWordWatchDetailed(domain, i, _settings.BigEndian));
}
}
else
{
for (int i = 0; i < domain.Size; i += (_settings.CheckMisAligned ? 1 : 4))
for (int i = 0; i < domain.Size; i += _settings.CheckMisAligned ? 1 : 4)
{
_watchList.Add(new MiniDWordWatch(domain, i, _settings.BigEndian));
}
@ -219,7 +219,11 @@ namespace BizHawk.Client.Common
public Compare CompareTo
{
get { return _compareTo; }
get
{
return _compareTo;
}
set
{
if (CanDoCompareType(value))
@ -310,7 +314,7 @@ namespace BizHawk.Client.Common
{
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach (IMiniWatchDetails watch in _watchList.Cast<IMiniWatchDetails>())
foreach (var watch in _watchList.Cast<IMiniWatchDetails>())
{
watch.ClearChangeCount();
}
@ -334,45 +338,66 @@ namespace BizHawk.Client.Common
_watchList.Clear();
}
switch(_settings.Size)
switch (_settings.Size)
{
default:
case Watch.WatchSize.Byte:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach(var addr in addresses) { _watchList.Add(new MiniByteWatchDetailed(_settings.Domain, addr)); }
foreach (var addr in addresses)
{
_watchList.Add(new MiniByteWatchDetailed(_settings.Domain, addr));
}
}
else
{
foreach(var addr in addresses) { _watchList.Add(new MiniByteWatch(_settings.Domain, addr)); }
foreach (var addr in addresses)
{
_watchList.Add(new MiniByteWatch(_settings.Domain, addr));
}
}
break;
case Watch.WatchSize.Word:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach (var addr in addresses) { _watchList.Add(new MiniWordWatchDetailed(_settings.Domain, addr, _settings.BigEndian)); }
foreach (var addr in addresses)
{
_watchList.Add(new MiniWordWatchDetailed(_settings.Domain, addr, _settings.BigEndian));
}
}
else
{
foreach (var addr in addresses) { _watchList.Add(new MiniWordWatch(_settings.Domain, addr, _settings.BigEndian)); }
foreach (var addr in addresses)
{
_watchList.Add(new MiniWordWatch(_settings.Domain, addr, _settings.BigEndian));
}
}
break;
case Watch.WatchSize.DWord:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach (var addr in addresses) { _watchList.Add(new MiniDWordWatchDetailed(_settings.Domain, addr, _settings.BigEndian)); }
foreach (var addr in addresses)
{
_watchList.Add(new MiniDWordWatchDetailed(_settings.Domain, addr, _settings.BigEndian));
}
}
else
{
foreach (var addr in addresses) { _watchList.Add(new MiniDWordWatch(_settings.Domain, addr, _settings.BigEndian)); }
foreach (var addr in addresses)
{
_watchList.Add(new MiniDWordWatch(_settings.Domain, addr, _settings.BigEndian));
}
}
break;
}
}
public void Sort(string column, bool reverse)
{
switch(column)
switch (column)
{
case WatchList.ADDRESS:
if (reverse)
@ -383,6 +408,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList.OrderBy(x => x.Address).ToList();
}
break;
case WatchList.VALUE:
if (reverse)
@ -393,6 +419,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList.OrderBy(x => GetValue(x.Address)).ToList();
}
break;
case WatchList.PREV:
if (reverse)
@ -403,6 +430,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList.OrderBy(x => x.Previous).ToList();
}
break;
case WatchList.CHANGES:
if (_settings.Mode == Settings.SearchMode.Detailed)
@ -422,6 +450,7 @@ namespace BizHawk.Client.Common
.Cast<IMiniWatch>().ToList();
}
}
break;
case WatchList.DIFF:
if (reverse)
@ -432,6 +461,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList.OrderBy(x => (GetValue(x.Address) - x.Previous)).ToList();
}
break;
}
}
@ -507,7 +537,6 @@ namespace BizHawk.Client.Common
{
throw new InvalidOperationException();
}
}
}
@ -523,7 +552,7 @@ namespace BizHawk.Client.Common
case ComparisonOperator.NotEqual:
return watchList.Where(x => GetValue(x.Address) != _compareValue.Value);
case ComparisonOperator.GreaterThan:
return watchList.Where(x => GetValue(x.Address) > _compareValue.Value);
return watchList.Where(x => GetValue(x.Address) > _compareValue.Value);
case ComparisonOperator.GreaterThanEqual:
return watchList.Where(x => GetValue(x.Address) >= _compareValue.Value);
case ComparisonOperator.LessThan:
@ -695,6 +724,7 @@ namespace BizHawk.Client.Common
{
return theByte;
}
case Watch.WatchSize.Word:
var theWord = _settings.Domain.PeekWord(addr, _settings.BigEndian);
if (_settings.Type == Watch.DisplayType.Signed)
@ -705,6 +735,7 @@ namespace BizHawk.Client.Common
{
return theWord;
}
case Watch.WatchSize.DWord:
var theDWord = _settings.Domain.PeekDWord(addr, _settings.BigEndian);
if (_settings.Type == Watch.DisplayType.Signed)
@ -749,7 +780,7 @@ namespace BizHawk.Client.Common
void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian);
}
private class MiniByteWatch : IMiniWatch
private sealed class MiniByteWatch : IMiniWatch
{
public int Address { get; private set; }
private byte _previous;
@ -771,7 +802,7 @@ namespace BizHawk.Client.Common
}
}
private class MiniWordWatch : IMiniWatch
private sealed class MiniWordWatch : IMiniWatch
{
public int Address { get; private set; }
private ushort _previous;
@ -793,7 +824,7 @@ namespace BizHawk.Client.Common
}
}
public class MiniDWordWatch : IMiniWatch
public sealed class MiniDWordWatch : IMiniWatch
{
public int Address { get; private set; }
private uint _previous;
@ -818,8 +849,9 @@ namespace BizHawk.Client.Common
private sealed class MiniByteWatchDetailed : IMiniWatch, IMiniWatchDetails
{
public int Address { get; private set; }
private byte _previous;
int _changecount;
private int _changecount;
public MiniByteWatchDetailed(MemoryDomain domain, int addr)
{
@ -844,7 +876,7 @@ namespace BizHawk.Client.Common
public void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian)
{
byte value = domain.PeekByte(Address);
var value = domain.PeekByte(Address);
if (value != Previous)
{
_changecount++;
@ -870,8 +902,9 @@ namespace BizHawk.Client.Common
private sealed class MiniWordWatchDetailed : IMiniWatch, IMiniWatchDetails
{
public int Address { get; private set; }
private ushort _previous;
int _changecount;
private int _changecount;
public MiniWordWatchDetailed(MemoryDomain domain, int addr, bool bigEndian)
{
@ -896,11 +929,12 @@ namespace BizHawk.Client.Common
public void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian)
{
ushort value = domain.PeekWord(Address, bigendian);
var value = domain.PeekWord(Address, bigendian);
if (value != Previous)
{
_changecount++;
}
switch (type)
{
case Watch.PreviousType.Original:
@ -921,8 +955,9 @@ namespace BizHawk.Client.Common
public sealed class MiniDWordWatchDetailed : IMiniWatch, IMiniWatchDetails
{
public int Address { get; private set; }
private uint _previous;
int _changecount;
private int _changecount;
public MiniDWordWatchDetailed(MemoryDomain domain, int addr, bool bigEndian)
{
@ -947,11 +982,12 @@ namespace BizHawk.Client.Common
public void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian)
{
uint value = domain.PeekDWord(Address, bigendian);
var value = domain.PeekDWord(Address, bigendian);
if (value != Previous)
{
_changecount++;
}
switch (type)
{
case Watch.PreviousType.Original:
@ -974,15 +1010,15 @@ namespace BizHawk.Client.Common
/*Require restart*/
public enum SearchMode { Fast, Detailed }
public SearchMode Mode;
public MemoryDomain Domain;
public Watch.WatchSize Size;
public bool CheckMisAligned;
public SearchMode Mode { get; set; }
public MemoryDomain Domain { get; set; }
public Watch.WatchSize Size { get; set; }
public bool CheckMisAligned { get; set; }
/*Can be changed mid-search*/
public Watch.DisplayType Type;
public bool BigEndian;
public Watch.PreviousType PreviousType;
public Watch.DisplayType Type { get; set; }
public bool BigEndian { get; set; }
public Watch.PreviousType PreviousType { get; set; }
public Settings()
{

View File

@ -1,6 +1,6 @@
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Globalization;
using BizHawk.Common;
using BizHawk.Emulation.Common;
@ -9,9 +9,9 @@ namespace BizHawk.Client.Common
{
public abstract class Watch
{
public enum WatchSize { Byte = 1, Word = 2, DWord = 4, Separator = 0 };
public enum DisplayType { Separator, Signed, Unsigned, Hex, Binary, FixedPoint_12_4, FixedPoint_20_12, Float };
public enum PreviousType { Original = 0, LastSearch = 1, LastFrame = 2, LastChange = 3 };
public enum WatchSize { Byte = 1, Word = 2, DWord = 4, Separator = 0 }
public enum DisplayType { Separator, Signed, Unsigned, Hex, Binary, FixedPoint_12_4, FixedPoint_20_12, Float }
public enum PreviousType { Original = 0, LastSearch = 1, LastFrame = 2, LastChange = 3 }
public static string DisplayTypeToString(DisplayType type)
{
@ -161,11 +161,11 @@ namespace BizHawk.Client.Common
{
if (_domain != null)
{
return "X" + IntHelpers.GetNumDigits(_domain.Size - 1).ToString();
return "X" + IntHelpers.GetNumDigits(this._domain.Size - 1);
}
else
{
return "";
return String.Empty;
}
}
}
@ -350,6 +350,7 @@ namespace BizHawk.Client.Common
{
_type = type;
}
_bigEndian = bigEndian;
if (notes != null)
{
@ -452,6 +453,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Signed:
if (InputValidate.IsValidSignedNumber(value))
@ -462,6 +464,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Hex:
if (InputValidate.IsValidHexNumber(value))
@ -472,6 +475,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Binary:
if (InputValidate.IsValidBinaryNumber(value))
@ -482,6 +486,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
}
@ -498,8 +503,8 @@ namespace BizHawk.Client.Common
{
get
{
string diff = String.Empty;
int diffVal = _value - _previous;
var diff = String.Empty;
var diffVal = _value - _previous;
if (diffVal > 0)
{
diff = "+";
@ -508,6 +513,7 @@ namespace BizHawk.Client.Common
{
diff = "-";
}
return diff + FormatValue((byte)(_previous - _value));
}
}
@ -526,6 +532,7 @@ namespace BizHawk.Client.Common
_previous = _value;
_changecount++;
}
break;
case PreviousType.LastFrame:
_previous = _value;
@ -534,6 +541,7 @@ namespace BizHawk.Client.Common
{
_changecount++;
}
break;
}
}
@ -554,6 +562,7 @@ namespace BizHawk.Client.Common
{
_type = type;
}
_bigEndian = bigEndian;
if (notes != null)
@ -627,7 +636,7 @@ namespace BizHawk.Client.Common
case DisplayType.Hex:
return val.ToHexString(4);
case DisplayType.FixedPoint_12_4:
return String.Format("{0:F4}", (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, " ");
}
@ -649,6 +658,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Signed:
if (InputValidate.IsValidSignedNumber(value))
@ -659,6 +669,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Hex:
if (InputValidate.IsValidHexNumber(value))
@ -669,6 +680,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Binary:
if (InputValidate.IsValidBinaryNumber(value))
@ -679,6 +691,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.FixedPoint_12_4:
if (InputValidate.IsValidFixedPointNumber(value))
@ -689,8 +702,10 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
}
PokeWord(val);
return true;
}
@ -720,6 +735,7 @@ namespace BizHawk.Client.Common
_previous = temp;
_changecount++;
}
break;
case PreviousType.LastFrame:
_previous = _value;
@ -728,6 +744,7 @@ namespace BizHawk.Client.Common
{
_changecount++;
}
break;
}
}
@ -748,6 +765,7 @@ namespace BizHawk.Client.Common
{
_type = type;
}
_bigEndian = bigEndian;
if (notes != null)
@ -823,10 +841,10 @@ namespace BizHawk.Client.Common
case DisplayType.Hex:
return val.ToHexString(8);
case DisplayType.FixedPoint_20_12:
return String.Format("{0:0.######}", (val / 4096.0));
return String.Format("{0:0.######}", val / 4096.0);
case DisplayType.Float:
byte[] bytes = BitConverter.GetBytes(val);
float _float = BitConverter.ToSingle(bytes, 0);
var bytes = BitConverter.GetBytes(val);
var _float = BitConverter.ToSingle(bytes, 0);
return String.Format("{0:0.######}", _float);
}
}
@ -847,6 +865,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Signed:
if (InputValidate.IsValidSignedNumber(value))
@ -857,6 +876,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Hex:
if (InputValidate.IsValidHexNumber(value))
@ -867,6 +887,7 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.FixedPoint_20_12:
if (InputValidate.IsValidFixedPointNumber(value))
@ -877,19 +898,22 @@ namespace BizHawk.Client.Common
{
return false;
}
break;
case DisplayType.Float:
if (InputValidate.IsValidDecimalNumber(value))
{
byte[] bytes = BitConverter.GetBytes(float.Parse(value));
var bytes = BitConverter.GetBytes(float.Parse(value));
val = BitConverter.ToUInt32(bytes, 0);
}
else
{
return false;
}
break;
}
PokeDWord(val);
return true;
}
@ -918,6 +942,7 @@ namespace BizHawk.Client.Common
_previous = _value;
_changecount++;
}
break;
case PreviousType.LastFrame:
_previous = _value;
@ -926,6 +951,7 @@ namespace BizHawk.Client.Common
{
_changecount++;
}
break;
}
}

View File

@ -19,7 +19,7 @@ namespace BizHawk.Client.Common
public const string DOMAIN = "DomainColumn";
public const string NOTES = "NotesColumn";
public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange };
public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange }
private List<Watch> _watchList = new List<Watch>();
private MemoryDomain _domain;
@ -86,6 +86,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.BigEndian)
.ToList();
}
break;
case VALUE:
if (reverse)
@ -108,8 +109,9 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.BigEndian)
.ToList();
}
break;
case PREV: //Note: these only work if all entries are detailed objects!
case PREV: // Note: these only work if all entries are detailed objects!
if (reverse)
{
_watchList = _watchList
@ -128,6 +130,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Type)
.ToList();
}
break;
case DIFF:
if (reverse)
@ -148,6 +151,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Type)
.ToList();
}
break;
case CHANGES:
if (reverse)
@ -168,6 +172,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Type)
.ToList();
}
break;
case DOMAIN:
if (reverse)
@ -190,6 +195,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.BigEndian)
.ToList();
}
break;
case NOTES:
if (reverse)
@ -210,6 +216,7 @@ namespace BizHawk.Client.Common
.ThenBy(x => x.Type)
.ToList();
}
break;
}
}
@ -220,7 +227,7 @@ namespace BizHawk.Client.Common
{
if (_domain != null)
{
return "{0:X" + IntHelpers.GetNumDigits(_domain.Size - 1).ToString() + "}";
return "{0:X" + IntHelpers.GetNumDigits(this._domain.Size - 1) + "}";
}
else
{
@ -260,11 +267,12 @@ namespace BizHawk.Client.Common
public bool Remove(Watch watch)
{
bool result = _watchList.Remove(watch);
var result = _watchList.Remove(watch);
if (result)
{
Changes = true;
}
return result;
}
@ -317,7 +325,7 @@ namespace BizHawk.Client.Common
public bool Load(string path, bool append)
{
bool result = LoadFile(path, append);
var result = LoadFile(path, append);
if (result)
{
@ -339,7 +347,7 @@ namespace BizHawk.Client.Common
{
if (!String.IsNullOrWhiteSpace(CurrentFileName))
{
LoadFile(CurrentFileName, append:false);
LoadFile(CurrentFileName, append: false);
Changes = false;
}
}
@ -351,22 +359,22 @@ namespace BizHawk.Client.Common
return false;
}
using (StreamWriter sw = new StreamWriter(CurrentFileName))
using (var sw = new StreamWriter(CurrentFileName))
{
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
sb
.Append("Domain ").AppendLine(_domain.Name)
.Append("SystemID ").AppendLine(Global.Emulator.SystemId);
foreach (Watch w in _watchList)
foreach (var watch in _watchList)
{
sb
.Append(String.Format(AddressFormatStr, w.Address ?? 0)).Append('\t')
.Append(w.SizeAsChar).Append('\t')
.Append(w.TypeAsChar).Append('\t')
.Append(w.BigEndian ? '1' : '0').Append('\t')
.Append(w.DomainName).Append('\t')
.Append(w.Notes)
.Append(String.Format(AddressFormatStr, watch.Address ?? 0)).Append('\t')
.Append(watch.SizeAsChar).Append('\t')
.Append(watch.TypeAsChar).Append('\t')
.Append(watch.BigEndian ? '1' : '0').Append('\t')
.Append(watch.DomainName).Append('\t')
.Append(watch.Notes)
.AppendLine();
}
@ -393,12 +401,16 @@ namespace BizHawk.Client.Common
private bool LoadFile(string path, bool append)
{
string domain = String.Empty;
var domain = String.Empty;
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())
if (file.Exists == false)
{
return false;
}
var isBizHawkWatch = true; // Hack to support .wch files from other emulators
var isOldBizHawkWatch = false;
using (var sr = file.OpenText())
{
string line;
@ -409,8 +421,8 @@ namespace BizHawk.Client.Common
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
// .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;
@ -428,38 +440,35 @@ namespace BizHawk.Client.Common
continue;
}
int numColumns = StringHelpers.HowMany(line, '\t');
var numColumns = StringHelpers.HowMany(line, '\t');
int startIndex;
if (numColumns == 5)
{
//If 5, then this is a post 1.0.5 .wch file
// If 5, then this is a post 1.0.5 .wch file
if (isBizHawkWatch)
{
//Do nothing here
// Do nothing here
}
else
{
startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //5 digit value representing the watch position number
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
else // 4 is 1.0.5 and earlier
{
continue; //If not 4, something is wrong with this line, ignore it
continue; // If not 4, something is wrong with this line, ignore it
}
//Temporary, rename if kept
// Temporary, rename if kept
int addr;
bool bigEndian;
MemoryDomain memDomain = Global.Emulator.MemoryDomains.MainMemory;
var memDomain = Global.Emulator.MemoryDomains.MainMemory;
string temp = line.Substring(0, line.IndexOf('\t'));
var temp = line.Substring(0, line.IndexOf('\t'));
try
{
addr = Int32.Parse(temp, NumberStyles.HexNumber);
@ -470,16 +479,15 @@ namespace BizHawk.Client.Common
}
startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //Type
Watch.WatchSize size = Watch.SizeFromChar(line[0]);
line = line.Substring(startIndex, line.Length - startIndex); // Type
var 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]);
line = line.Substring(startIndex, line.Length - startIndex); // Signed
var type = Watch.DisplayTypeFromChar(line[0]);
startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //Endian
line = line.Substring(startIndex, line.Length - startIndex); // Endian
try
{
startIndex = Int16.Parse(line[0].ToString());
@ -488,25 +496,19 @@ namespace BizHawk.Client.Common
{
continue;
}
if (startIndex == 0)
{
bigEndian = false;
}
else
{
bigEndian = true;
}
var bigEndian = startIndex != 0;
if (isBizHawkWatch && !isOldBizHawkWatch)
{
startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //Domain
line = line.Substring(startIndex, line.Length - startIndex); // Domain
temp = line.Substring(0, line.IndexOf('\t'));
memDomain = Global.Emulator.MemoryDomains[temp] ?? Global.Emulator.MemoryDomains.MainMemory;
}
startIndex = line.IndexOf('\t') + 1;
string notes = line.Substring(startIndex, line.Length - startIndex);
var notes = line.Substring(startIndex, line.Length - startIndex);
_watchList.Add(
Watch.GenerateWatch(
@ -531,6 +533,7 @@ namespace BizHawk.Client.Common
{
Changes = true;
}
return true;
}