private string FormatValue(int value, WatchFormatStyle style, int byteLength) { switch(style) { case WatchFormatStyle.Unsigned: return ((UInt32)value).ToString(); case WatchFormatStyle.Hex: return "$" + value.ToString("X" + byteLength * 2); case WatchFormatStyle.Binary: string binary = Convert.ToString(value, 2).PadLeft(byteLength * 8, '0'); for(int i = binary.Length - 4; i > 0; i -= 4) { binary = binary.Insert(i, "."); } return "%" + binary; case WatchFormatStyle.Signed: int bitCount = byteLength * 8; if(bitCount < 32) { if(((value >> (bitCount - 1)) & 0x01) == 0x01) { //Negative value return (value | (-(1 << bitCount))).ToString(); } else { //Position value return value.ToString(); } } else { return value.ToString(); } default: throw new Exception("Unsupported format"); } }
private string ProcessArrayDisplaySyntax(WatchFormatStyle style, ref bool forceHasChanged, Match match) { string newValue; int address; if(match.Groups[2].Value.Length > 0) { address = int.Parse(match.Groups[2].Value.Substring(1), System.Globalization.NumberStyles.HexNumber); } else if(match.Groups[3].Value.Length > 0) { address = int.Parse(match.Groups[3].Value); } else { return "<invalid expression>"; /*CodeLabel label = LabelManager.GetLabel(match.Groups[4].Value); if(label == null) { forceHasChanged = true; return "<invalid label>"; } address = label.GetRelativeAddress();*/ } int elemCount = int.Parse(match.Groups[5].Value); if(address >= 0) { List<string> values = new List<string>(elemCount); for(int j = address, end = address + elemCount; j < end; j++) { int memValue = DebugApi.GetMemoryValue(SnesMemoryType.CpuMemory, (uint)j); values.Add(FormatValue(memValue, style, 1)); } newValue = string.Join(" ", values); } else { newValue = "<label out of scope>"; forceHasChanged = true; } return newValue; }
private bool ProcessFormatSpecifier(ref string expression, ref WatchFormatStyle style, ref int byteLength) { Match match = WatchManager.FormatSuffixRegex.Match(expression); if(!match.Success) { return false; } string format = match.Groups[2].Value.ToUpperInvariant(); switch(format[0]) { case 'S': style = WatchFormatStyle.Signed; break; case 'H': style = WatchFormatStyle.Hex; break; case 'B': style = WatchFormatStyle.Binary; break; case 'U': style = WatchFormatStyle.Unsigned; break; default: throw new Exception("Invalid format"); } if(match.Groups[3].Success) { byteLength = Math.Max(Math.Min(Int32.Parse(match.Groups[3].Value), 4), 1); } else { byteLength = 1; } expression = match.Groups[1].Value; return true; }
public List<WatchValueInfo> GetWatchContent(CpuType cpuType, List<WatchValueInfo> previousValues) { WatchFormatStyle defaultStyle = ConfigManager.Config.Debug.Debugger.WatchFormat; int defaultByteLength = 1; if(defaultStyle == WatchFormatStyle.Signed) { defaultByteLength = 4; } var list = new List<WatchValueInfo>(); for(int i = 0; i < _watchEntries.Count; i++) { string expression = _watchEntries[i].Trim(); string newValue = ""; EvalResultType resultType; string exprToEvaluate = expression; WatchFormatStyle style = defaultStyle; int byteLength = defaultByteLength; if(expression.StartsWith("{") && expression.EndsWith("}")) { //Default to 2-byte values when using {} syntax byteLength = 2; } ProcessFormatSpecifier(ref exprToEvaluate, ref style, ref byteLength); bool forceHasChanged = false; Match match = _arrayWatchRegex.Match(expression); if(match.Success) { //Watch expression matches the array display syntax (e.g: [$300,10] = display 10 bytes starting from $300) newValue = ProcessArrayDisplaySyntax(style, ref forceHasChanged, match); } else { Int32 result = DebugApi.EvaluateExpression(exprToEvaluate, cpuType, out resultType, true); switch(resultType) { case EvalResultType.Numeric: newValue = FormatValue(result, style, byteLength); break; case EvalResultType.Boolean: newValue = result == 0 ? "false" : "true"; break; case EvalResultType.Invalid: newValue = "<invalid expression>"; forceHasChanged = true; break; case EvalResultType.DivideBy0: newValue = "<division by zero>"; forceHasChanged = true; break; case EvalResultType.OutOfScope: newValue = "<label out of scope>"; forceHasChanged = true; break; } } list.Add(new WatchValueInfo() { Expression = expression, Value = newValue, HasChanged = forceHasChanged || (i < previousValues.Count ? (previousValues[i].Value != newValue) : false) }); } return list; }
private string GetFormatString(WatchFormatStyle format, int byteLength) { string formatString = ", "; switch (format) { case WatchFormatStyle.Binary: formatString += "B"; break; case WatchFormatStyle.Hex: formatString += "H"; break; case WatchFormatStyle.Signed: formatString += "S"; break; case WatchFormatStyle.Unsigned: formatString += "U"; break; default: throw new Exception("Unsupported type"); } if (byteLength > 1) { formatString += byteLength.ToString(); } return(formatString); }
private void SetSelectionFormat(WatchFormatStyle format, int byteLength) { SetSelectionFormat(GetFormatString(format, byteLength)); }