New Ram Watch - implement Separator object, finish file loading (only 1 byte supported currently)

This commit is contained in:
adelikat 2013-09-05 00:55:12 +00:00
parent ca579745de
commit 1254b8b03e
2 changed files with 341 additions and 262 deletions

View File

@ -109,7 +109,7 @@ namespace BizHawk.MultiClient
if (result) if (result)
{ {
Watches.Load(file.FullName, false); Watches.Load(file.FullName, details: true, append: false);
DisplayWatches(); DisplayWatches();
MessageLabel.Text = Path.GetFileNameWithoutExtension(Watches.CurrentFileName); MessageLabel.Text = Path.GetFileNameWithoutExtension(Watches.CurrentFileName);
UpdateWatchCount(); UpdateWatchCount();

View File

@ -96,7 +96,7 @@ namespace BizHawk.MultiClient
{ {
get { return Value - Prev; } get { return Value - Prev; }
} }
public int DiffOriginal public int DiffOriginal
{ {
get { return Value - Original; } get { return Value - Original; }
@ -256,7 +256,7 @@ namespace BizHawk.MultiClient
} }
Prev = Value; Prev = Value;
switch (Type) switch (Type)
{ {
case TYPE.BYTE: case TYPE.BYTE:
@ -902,52 +902,79 @@ namespace BizHawk.MultiClient
public abstract int? Address { get; } public abstract int? Address { get; }
public abstract int? Value { get; } public abstract int? Value { get; }
public abstract string AddressString { get; } public abstract string AddressString { get; }
public abstract string ValueString { get; } public abstract string ValueString { get; }
public enum WatchSize { Byte = 1, Word = 2, DWord = 4, Separator = 0 }; public enum WatchSize { Byte = 1, Word = 2, DWord = 4, Separator = 0 };
public enum DisplayType { Signed, Unsigned, Hex }; public enum DisplayType { Signed, Unsigned, Hex };
public readonly WatchSize Size; public readonly WatchSize Size;
public readonly DisplayType Type; public readonly DisplayType Type;
public bool BigEndian = false; public bool BigEndian = false;
public bool IsSeparator() public virtual bool IsSeparator
{ {
return Size == WatchSize.Separator; get
} {
return Size == WatchSize.Separator;
}
}
public static WatchSize SizeFromChar(char c) //b = byte, w = word, d = dword public static WatchSize SizeFromChar(char c) //b = byte, w = word, d = dword
{ {
switch (c) switch (c)
{ {
case 'b': case 'b':
return WatchSize.Byte; return WatchSize.Byte;
case 'w': case 'w':
return WatchSize.Word; return WatchSize.Word;
case 'd': case 'd':
return WatchSize.DWord; return WatchSize.DWord;
default: default:
case 'S': case 'S':
return WatchSize.Separator; return WatchSize.Separator;
} }
} }
public static DisplayType DisplayTypeFromChar(char c) //s = signed, u = unsigned, h = hex public static DisplayType DisplayTypeFromChar(char c) //s = signed, u = unsigned, h = hex
{ {
switch (c) switch (c)
{ {
default: default:
case 'u': case 'u':
return DisplayType.Unsigned; return DisplayType.Unsigned;
case 's': case 's':
return DisplayType.Signed; return DisplayType.Signed;
case 'h': case 'h':
return DisplayType.Hex; return DisplayType.Hex;
} }
} }
public static WatchEntryBase GenerateWatch(MemoryDomain domain, int address, WatchSize size, DisplayType type, bool details)
{
switch (size)
{
default:
case WatchSize.Separator:
return new SeparatorWatch();
case WatchSize.Byte:
if (details)
{
return new DetailedByteWatch(domain, address);
}
else
{
return new ByteWatch(domain, address);
}
break;
case WatchSize.Word:
throw new NotImplementedException();
case WatchSize.DWord:
throw new NotImplementedException();
}
}
} }
public interface iWatchEntryDetails public interface iWatchEntryDetails
{ {
int ChangeCount { get; } int ChangeCount { get; }
@ -956,7 +983,49 @@ namespace BizHawk.MultiClient
int? Previous { get; } int? Previous { get; }
void ResetPrevious(); void ResetPrevious();
string Notes { get; set; } string Notes { get; set; }
}
public class SeparatorWatch : WatchEntryBase
{
public SeparatorWatch()
{
}
public override int? Address
{
get { return null; }
}
public override int? Value
{
get { return null; }
}
public override string AddressString
{
get { return ""; }
}
public override string ValueString
{
get { return ""; }
}
public override string ToString()
{
switch (Type)
{
default:
return Value.ToString(); //TODO
}
}
public override bool IsSeparator
{
get { return true; }
}
} }
public class ByteWatch : WatchEntryBase public class ByteWatch : WatchEntryBase
@ -968,8 +1037,8 @@ namespace BizHawk.MultiClient
_address = address; _address = address;
_domain = domain; _domain = domain;
} }
public override int? Address public override int? Address
{ {
get get
{ {
@ -982,35 +1051,35 @@ namespace BizHawk.MultiClient
get get
{ {
if (_address.HasValue) if (_address.HasValue)
{ {
return _domain.PeekByte(_address.Value); return _domain.PeekByte(_address.Value);
} }
else else
{ {
return null; return null;
} }
} }
} }
public override string AddressString public override string AddressString
{ {
get get
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
public override string ValueString public override string ValueString
{ {
get get
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
public override string ToString() public override string ToString()
{ {
switch(Type) switch (Type)
{ {
default: default:
return Value.ToString(); //TODO return Value.ToString(); //TODO
@ -1022,26 +1091,28 @@ namespace BizHawk.MultiClient
{ {
private int? _previous; private int? _previous;
public DetailedByteWatch(MemoryDomain domain, int address) : base(domain, address) { Notes = String.Empty; } public DetailedByteWatch(MemoryDomain domain, int address) : base(domain, address) { Notes = String.Empty; }
public int ChangeCount { get; private set; } public int ChangeCount { get; private set; }
public void ClearChangeCount() { ChangeCount = 0; } public void ClearChangeCount() { ChangeCount = 0; }
public int? Previous { get { return _previous; } } public int? Previous { get { return _previous; } }
public void ResetPrevious() public void ResetPrevious()
{ {
_previous = Value; _previous = Value;
} }
public string Notes { get; set; } public string Notes { get; set; }
} }
public class WatchList : IEnumerable public class WatchList : IEnumerable
{ {
private string _currentFilename = "";
public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange }; public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange };
private List<WatchEntryBase> _watchList = new List<WatchEntryBase>(); private List<WatchEntryBase> _watchList = new List<WatchEntryBase>();
private MemoryDomain _domain = null; private MemoryDomain _domain = null;
public WatchList() { } public WatchList() { }
@ -1063,229 +1134,237 @@ namespace BizHawk.MultiClient
} }
} }
public int WatchCount public int WatchCount
{ {
get get
{ {
return _watchList.Count(w => !w.IsSeparator()); return _watchList.Count(w => !w.IsSeparator);
} }
} }
public int ItemCount public int ItemCount
{ {
get get
{ {
return _watchList.Count; return _watchList.Count;
} }
} }
public string AddressFormatStr public string AddressFormatStr
{ {
get get
{ {
if (_domain != null) if (_domain != null)
{ {
return "X" + IntHelpers.GetNumDigits(_domain.Size - 1).ToString(); return "X" + IntHelpers.GetNumDigits(_domain.Size - 1).ToString();
} }
else else
{ {
return ""; return "";
} }
} }
} }
public void Clear() public void Clear()
{ {
_watchList.Clear(); _watchList.Clear();
} }
public MemoryDomain Domain { get { return _domain; } set { _domain = value; } } public MemoryDomain Domain { get { return _domain; } set { _domain = value; } }
#region File handling logic - probably needs to be its own class #region File handling logic - probably needs to be its own class
public string CurrentFileName { get; set; } public string CurrentFileName { get { return _currentFilename; } set { _currentFilename = value; } }
public bool Changes { get; set; } public bool Changes { get; set; }
public void Save() public void Save()
{ {
if (!String.IsNullOrWhiteSpace(CurrentFileName)) if (!String.IsNullOrWhiteSpace(CurrentFileName))
{ {
SaveFile(); SaveFile();
} }
else else
{ {
SaveFileAs(); SaveFileAs();
} }
} }
public void Load(string path, bool append) public void Load(string path, bool details, bool append)
{ {
bool result = LoadFile(path, append); bool result = LoadFile(path, append, details);
if (result) if (result)
{ {
if (!append) if (!append)
{ {
CurrentFileName = path; CurrentFileName = path;
} }
else else
{ {
Changes = false; Changes = false;
} }
} }
} }
private void SaveFile() private void SaveFile()
{ {
//TODO //TODO
throw new NotImplementedException(); throw new NotImplementedException();
} }
private void SaveFileAs() private void SaveFileAs()
{ {
//TODO //TODO
throw new NotImplementedException(); throw new NotImplementedException();
} }
private bool LoadFile(string path, bool append) private bool LoadFile(string path, bool details, bool append)
{ {
string domain = ""; string domain = "";
var file = new FileInfo(path); var file = new FileInfo(path);
if (file.Exists == false) return false; if (file.Exists == false) return false;
bool isBizHawkWatch = true; //Hack to support .wch files from other emulators bool isBizHawkWatch = true; //Hack to support .wch files from other emulators
bool isOldBizHawkWatch = false; bool isOldBizHawkWatch = false;
using (StreamReader sr = file.OpenText()) using (StreamReader sr = file.OpenText())
{ {
string line; string line;
if (append == false) if (append == false)
{ {
Clear(); Clear();
} }
while ((line = sr.ReadLine()) != null) 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 //.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 //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) if (line.Length < 5)
{ {
isBizHawkWatch = false; isBizHawkWatch = false;
continue; continue;
} }
if (line.Length >= 6 && line.Substring(0, 6) == "Domain") if (line.Length >= 6 && line.Substring(0, 6) == "Domain")
{ {
domain = line.Substring(7, line.Length - 7); domain = line.Substring(7, line.Length - 7);
isBizHawkWatch = true; isBizHawkWatch = true;
} }
if (line.Length >= 8 && line.Substring(0, 8) == "SystemID") if (line.Length >= 8 && line.Substring(0, 8) == "SystemID")
{ {
continue; continue;
} }
int numColumns = StringHelpers.HowMany(line, '\t'); int numColumns = StringHelpers.HowMany(line, '\t');
int startIndex; int startIndex;
if (numColumns == 5) 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) if (isBizHawkWatch)
{ {
//Do nothing here //Do nothing here
} }
else else
{ {
startIndex = line.IndexOf('\t') + 1; 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) else if (numColumns == 4)
{ {
isOldBizHawkWatch = true; 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
Watch w = new Watch(); int THEADDRESS_ = 0;
int THEADDRESS_ = 0; WatchEntryBase.WatchSize THESIZE = WatchEntryBase.WatchSize.Separator;
WatchEntryBase.WatchSize THESIZE = WatchEntryBase.WatchSize.Separator; WatchEntryBase.DisplayType THEDISPLAYTYPE = WatchEntryBase.DisplayType.Unsigned;
WatchEntryBase.DisplayType THEDISPLAYTYPE = WatchEntryBase.DisplayType.Unsigned; bool BIGENDIAN = false;
bool BIGENDIAN = false; MemoryDomain THEDOMAIN = Global.Emulator.MainMemory;
MemoryDomain THEDOMAIN = Global.Emulator.MainMemory; string THENOTES;
string THENOTES;
string temp = line.Substring(0, line.IndexOf('\t')); string temp = line.Substring(0, line.IndexOf('\t'));
try try
{ {
THEADDRESS_ = Int32.Parse(temp, NumberStyles.HexNumber); THEADDRESS_ = Int32.Parse(temp, NumberStyles.HexNumber);
} }
catch catch
{ {
continue; continue;
} }
startIndex = line.IndexOf('\t') + 1; startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //Type line = line.Substring(startIndex, line.Length - startIndex); //Type
THESIZE = WatchEntryBase.SizeFromChar(line[0]); THESIZE = WatchEntryBase.SizeFromChar(line[0]);
startIndex = line.IndexOf('\t') + 1; startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //Signed line = line.Substring(startIndex, line.Length - startIndex); //Signed
THEDISPLAYTYPE = WatchEntryBase.DisplayTypeFromChar(line[0]); THEDISPLAYTYPE = WatchEntryBase.DisplayTypeFromChar(line[0]);
startIndex = line.IndexOf('\t') + 1; startIndex = line.IndexOf('\t') + 1;
line = line.Substring(startIndex, line.Length - startIndex); //Endian line = line.Substring(startIndex, line.Length - startIndex); //Endian
try try
{ {
startIndex = Int16.Parse(line[0].ToString()); startIndex = Int16.Parse(line[0].ToString());
} }
catch catch
{ {
continue; continue;
} }
if (startIndex == 0) if (startIndex == 0)
{ {
BIGENDIAN = false; BIGENDIAN = false;
} }
else else
{ {
BIGENDIAN = true; BIGENDIAN = true;
} }
if (isBizHawkWatch && !isOldBizHawkWatch) if (isBizHawkWatch && !isOldBizHawkWatch)
{ {
startIndex = line.IndexOf('\t') + 1; 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')); temp = line.Substring(0, line.IndexOf('\t'));
THEDOMAIN = Global.Emulator.MemoryDomains[GetDomainPos(temp)]; THEDOMAIN = Global.Emulator.MemoryDomains[GetDomainPos(temp)];
} }
startIndex = line.IndexOf('\t') + 1; startIndex = line.IndexOf('\t') + 1;
THENOTES = line.Substring(startIndex, line.Length - startIndex); //User notes THENOTES = line.Substring(startIndex, line.Length - startIndex); //User notes
//_watchList.Add(w); //TODO: we need a widget factory or something, to manage the logic of what object to use! WatchEntryBase w = WatchEntryBase.GenerateWatch(
} THEDOMAIN,
} THEADDRESS_,
THESIZE,
THEDISPLAYTYPE,
details
);
w.BigEndian = BIGENDIAN;
_watchList.Add(w);
_domain = Global.Emulator.MemoryDomains[GetDomainPos(domain)];
}
}
return true; return true;
} }
private static int GetDomainPos(string name) private static int GetDomainPos(string name)
{ {
//Attempts to find the memory domain by name, if it fails, it defaults to index 0 //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++) for (int x = 0; x < Global.Emulator.MemoryDomains.Count; x++)
{ {
if (Global.Emulator.MemoryDomains[x].Name == name) if (Global.Emulator.MemoryDomains[x].Name == name)
return x; return x;
} }
return 0; return 0;
} }
#endregion #endregion
} }
} }