Debugger: Added option to select refresh speed for hex editor (+ refresh speed optimizations)
This commit is contained in:
parent
b95e374ef5
commit
95c2c30076
7 changed files with 295 additions and 309 deletions
|
@ -137,6 +137,7 @@ namespace Mesen.GUI.Config
|
|||
public XmlColor CodeEffectiveAddressColor = Color.SteelBlue;
|
||||
|
||||
public bool RamAutoRefresh = true;
|
||||
public RefreshSpeed RamAutoRefreshSpeed = RefreshSpeed.Normal;
|
||||
public int RamColumnCount = 2;
|
||||
public float RamFontSize = BaseControl.DefaultFontSize;
|
||||
public bool RamShowCharacters = true;
|
||||
|
@ -252,6 +253,12 @@ namespace Mesen.GUI.Config
|
|||
LoadLastScript = 2
|
||||
}
|
||||
|
||||
public enum RefreshSpeed
|
||||
{
|
||||
Low = 0,
|
||||
Normal = 1,
|
||||
High = 2
|
||||
}
|
||||
|
||||
public class XmlColor
|
||||
{
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
};
|
||||
|
||||
this.ctrlHexBox.ByteProvider = _byteProvider;
|
||||
this.ctrlHexBox.Refresh();
|
||||
|
||||
if(needInit) {
|
||||
InitializeContextMenu?.Invoke(this.ctrlHexBox, EventArgs.Empty);
|
||||
|
|
|
@ -2425,24 +2425,18 @@ namespace Be.Windows.Forms
|
|||
if (_lineInfoVisible)
|
||||
PaintLineInfo(e.Graphics, _startByte, _endByte);
|
||||
|
||||
if (!_stringViewVisible)
|
||||
{
|
||||
PaintHex(e.Graphics, _startByte, _endByte);
|
||||
}
|
||||
else
|
||||
{
|
||||
PaintHexAndStringView(e.Graphics, _startByte, _endByte);
|
||||
if (_shadowSelectionVisible)
|
||||
PaintCurrentBytesSign(e.Graphics);
|
||||
}
|
||||
PaintHexAndStringView(e.Graphics, _startByte, _endByte);
|
||||
if (_shadowSelectionVisible)
|
||||
PaintCurrentBytesSign(e.Graphics);
|
||||
|
||||
if (_columnInfoVisible)
|
||||
PaintHeaderRow(e.Graphics);
|
||||
if (_groupSeparatorVisible)
|
||||
PaintColumnSeparator(e.Graphics);
|
||||
|
||||
if(_caretVisible && this.Focused && _keyInterpreter.GetType() != typeof(StringKeyInterpreter)) {
|
||||
int caretWidth = (this.InsertActive) ? 1 : (int)_charSize.Width;
|
||||
int caretHeight = (int)_charSize.Height;
|
||||
float caretWidth = (this.InsertActive) ? 1 : _charSize.Width;
|
||||
float caretHeight = _charSize.Height;
|
||||
e.Graphics.DrawRectangle(Pens.Gray, _caretPos.X - 1, _caretPos.Y, caretWidth, caretHeight);
|
||||
}
|
||||
}
|
||||
|
@ -2509,63 +2503,10 @@ namespace Be.Windows.Forms
|
|||
}
|
||||
}
|
||||
|
||||
void PaintHex(Graphics g, long startByte, long endByte)
|
||||
{
|
||||
Brush selBrushBack = new SolidBrush(_selectionBackColor);
|
||||
|
||||
int counter = -1;
|
||||
long intern_endByte = Math.Min(_byteProvider.Length - 1, endByte + _iHexMaxHBytes);
|
||||
|
||||
bool isKeyInterpreterActive = _keyInterpreter == null || _keyInterpreter.GetType() == typeof(KeyInterpreter);
|
||||
|
||||
if(this.ByteColorProvider != null) {
|
||||
this.ByteColorProvider.Prepare(_startByte, intern_endByte);
|
||||
}
|
||||
|
||||
bool prevSelected = false;
|
||||
Color prevBgColor = Color.Transparent;
|
||||
|
||||
for (long i = startByte; i < intern_endByte + 1; i++)
|
||||
{
|
||||
counter++;
|
||||
Point gridPoint = GetGridBytePoint(counter);
|
||||
byte b = _byteProvider.ReadByte(i);
|
||||
|
||||
Color byteColor = this.ForeColor;
|
||||
Color bgColor = Color.Transparent;
|
||||
if(this.ByteColorProvider != null) {
|
||||
byteColor = this.ByteColorProvider.GetByteColor(_startByte, i, out bgColor);
|
||||
}
|
||||
|
||||
bool isSelectedByte = i >= _bytePos && i <= (_bytePos + _selectionLength - 1) && _selectionLength != 0;
|
||||
using(Brush byteBrush = new SolidBrush(byteColor)) {
|
||||
if(isSelectedByte && isKeyInterpreterActive) {
|
||||
PaintHexStringSelected(g, b, byteBrush, selBrushBack, gridPoint, prevSelected);
|
||||
prevSelected = true;
|
||||
} else {
|
||||
if(bgColor != Color.Transparent) {
|
||||
using(Brush bgBrush = new SolidBrush(bgColor)) {
|
||||
PaintHexStringSelected(g, b, byteBrush, bgBrush, gridPoint, prevBgColor == bgColor);
|
||||
}
|
||||
} else {
|
||||
PaintHexString(g, b, byteBrush, gridPoint);
|
||||
}
|
||||
prevSelected = false;
|
||||
}
|
||||
prevBgColor = bgColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaintHexString(Graphics g, byte b, Brush brush, Point gridPoint)
|
||||
void PaintHexString(Graphics g, string hexString, Brush brush, Point gridPoint)
|
||||
{
|
||||
PointF bytePointF = GetBytePointF(gridPoint);
|
||||
|
||||
string sB = ConvertByteToHex(b);
|
||||
|
||||
g.DrawString(sB.Substring(0, 1), Font, brush, bytePointF, _stringFormat);
|
||||
bytePointF.X += _charSize.Width;
|
||||
g.DrawString(sB.Substring(1, 1), Font, brush, bytePointF, _stringFormat);
|
||||
g.DrawString(hexString, Font, brush, bytePointF, _stringFormat);
|
||||
}
|
||||
|
||||
void PaintColumnInfo(Graphics g, byte b, Brush brush, int col)
|
||||
|
@ -2579,30 +2520,23 @@ namespace Be.Windows.Forms
|
|||
g.DrawString(sB.Substring(1, 1), Font, brush, headerPointF, _stringFormat);
|
||||
}
|
||||
|
||||
void PaintHexStringSelected(Graphics g, byte b, Brush brush, Brush brushBack, Point gridPoint, bool extendBack = false)
|
||||
void PaintHexStringSelected(Graphics g, string hexString, Brush brush, Brush brushBack, Point gridPoint)
|
||||
{
|
||||
string sB = b.ToString(_hexStringFormat, System.Threading.Thread.CurrentThread.CurrentCulture);
|
||||
if (sB.Length == 1)
|
||||
sB = "0" + sB;
|
||||
|
||||
PointF bytePointF = GetBytePointF(gridPoint);
|
||||
|
||||
bool isFirstLineChar = (gridPoint.X == 0);
|
||||
extendBack &= !isFirstLineChar;
|
||||
float bcWidth = extendBack ? _charSize.Width * 3 : _charSize.Width * 2;
|
||||
float width = hexString.Length * _charSize.Width;
|
||||
float xPos = bytePointF.X - _charSize.Width / 2;
|
||||
|
||||
g.FillRectangle(brushBack, extendBack ? bytePointF.X - _charSize.Width : bytePointF.X, bytePointF.Y, bcWidth, _charSize.Height);
|
||||
if(_selectionLength == 0 && _caretPos.Y == bytePointF.Y && _caretPos.X >= bytePointF.X && _caretPos.X <= bytePointF.X + bcWidth) {
|
||||
g.FillRectangle(brushBack, xPos, bytePointF.Y, width, _charSize.Height);
|
||||
if(_selectionLength == 0 && _caretPos.Y == bytePointF.Y && _caretPos.X >= bytePointF.X && _caretPos.X <= bytePointF.X + width) {
|
||||
if(_caretVisible && this.Focused && _keyInterpreter.GetType() != typeof(StringKeyInterpreter)) {
|
||||
//Redraw caret over background color
|
||||
int caretWidth = (this.InsertActive) ? 1 : (int)_charSize.Width;
|
||||
int caretHeight = (int)_charSize.Height;
|
||||
float caretWidth = (this.InsertActive) ? 1 : _charSize.Width;
|
||||
float caretHeight = (int)_charSize.Height;
|
||||
g.FillRectangle(Brushes.Yellow, _caretPos.X - 1, _caretPos.Y, caretWidth, caretHeight);
|
||||
}
|
||||
}
|
||||
g.DrawString(sB.Substring(0, 1), Font, brush, bytePointF, _stringFormat);
|
||||
bytePointF.X += _charSize.Width;
|
||||
g.DrawString(sB.Substring(1, 1), Font, brush, bytePointF, _stringFormat);
|
||||
g.DrawString(hexString, Font, brush, bytePointF, _stringFormat);
|
||||
}
|
||||
|
||||
Dictionary<int, float> _lineWidthCache = new Dictionary<int, float>();
|
||||
|
@ -2616,9 +2550,12 @@ namespace Be.Windows.Forms
|
|||
|
||||
int yPrevious = -1;
|
||||
float xOffset = 0;
|
||||
_lineWidthCache = new Dictionary<int, float>();
|
||||
_xPosCache = new Dictionary<Point, float>();
|
||||
_xPosList = new Dictionary<int, List<float>>();
|
||||
Color defaultForeColor = this.ForeColor;
|
||||
_lineWidthCache.Clear();
|
||||
for(int i = 0; i < _xPosCache.Length; i++) {
|
||||
_xPosCache[i] = -1;
|
||||
}
|
||||
_xPosList.Clear();
|
||||
float xPrevious = 0;
|
||||
|
||||
Point? caretPoint = null;
|
||||
|
@ -2632,92 +2569,153 @@ namespace Be.Windows.Forms
|
|||
this.ByteColorProvider.Prepare(_startByte, intern_endByte);
|
||||
}
|
||||
|
||||
bool forceDraw = false;
|
||||
float prevXOffset = 0;
|
||||
bool prevSelected = false;
|
||||
Color prevByteColor = Color.Transparent;
|
||||
Color prevBgColor = Color.Transparent;
|
||||
Color prevDrawnColor = Color.Transparent;
|
||||
|
||||
for(long i = startByte; i < intern_endByte + 1; i++) {
|
||||
counter++;
|
||||
Point gridPoint = GetGridBytePoint(counter);
|
||||
PointF byteStringPointF = GetByteStringPointF(gridPoint);
|
||||
|
||||
if(yPrevious != gridPoint.Y) {
|
||||
if(_xPosList.ContainsKey(yPrevious)) {
|
||||
_xPosList[yPrevious].Add(xPrevious);
|
||||
}
|
||||
_xPosList[gridPoint.Y] = new List<float>();
|
||||
_lineWidthCache[yPrevious] = _recStringView.Width + xOffset;
|
||||
xOffset = 0;
|
||||
Point gridPoint = GetGridBytePoint(0);
|
||||
List<byte> bytesToDisplay = new List<byte>();
|
||||
string stringToDisplay = string.Empty;
|
||||
float caretWidth = 0;
|
||||
Action<Color, Color> outputHex = (Color byteColor, Color bgColor) => {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach(byte b in bytesToDisplay) {
|
||||
sb.Append(b.ToString("X2"));
|
||||
sb.Append(" ");
|
||||
}
|
||||
yPrevious = gridPoint.Y;
|
||||
|
||||
byte b = _byteProvider.ReadByte(i);
|
||||
bool isSelectedByte = i >= _bytePos && i <= (_bytePos + _selectionLength - 1) && _selectionLength != 0;
|
||||
PointF bytePointF = GetBytePointF(gridPoint);
|
||||
PointF byteStringPointF = GetByteStringPointF(gridPoint, false);
|
||||
float xPos = byteStringPointF.X + prevXOffset;
|
||||
|
||||
using(Brush selBrushBack = new SolidBrush(_selectionBackColor)) {
|
||||
Color byteColor = this.ForeColor;
|
||||
//String view caret
|
||||
Action drawCaret = () => {
|
||||
if(_selectionLength == 0 && _caretPos.Y == bytePointF.Y && _caretPos.X >= xPos) {
|
||||
if(_caretVisible && this.Focused && _keyInterpreter.GetType() == typeof(StringKeyInterpreter)) {
|
||||
g.FillRectangle(Brushes.Yellow, _caretPos.X, _caretPos.Y, this.InsertActive ? 1 : caretWidth, _charSize.Height);
|
||||
g.DrawRectangle(Pens.Gray, _caretPos.X, _caretPos.Y, this.InsertActive ? 1 : caretWidth, _charSize.Height);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using(Brush fgBrush = new SolidBrush(byteColor)) {
|
||||
if(bgColor != Color.Transparent) {
|
||||
using(Brush bgBrush = new SolidBrush(bgColor)) {
|
||||
PaintHexStringSelected(g, sb.ToString(), fgBrush, bgBrush, gridPoint);
|
||||
|
||||
//Draw string view
|
||||
SizeF stringSize = g.MeasureString(stringToDisplay, Font, 1000, _stringFormat);
|
||||
g.FillRectangle(bgBrush, xPos, bytePointF.Y, stringSize.Width, _charSize.Height);
|
||||
drawCaret();
|
||||
g.DrawString(stringToDisplay, Font, fgBrush, new PointF(xPos, bytePointF.Y), _stringFormat);
|
||||
}
|
||||
} else {
|
||||
PaintHexString(g, sb.ToString(), fgBrush, gridPoint);
|
||||
|
||||
//Draw string view
|
||||
drawCaret();
|
||||
g.DrawString(stringToDisplay, Font, fgBrush, new PointF(xPos, bytePointF.Y), _stringFormat);
|
||||
}
|
||||
}
|
||||
|
||||
prevDrawnColor = bgColor;
|
||||
bytesToDisplay = new List<byte>();
|
||||
stringToDisplay = string.Empty;
|
||||
};
|
||||
|
||||
using(Brush selBrushBack = new SolidBrush(_selectionBackColor)) {
|
||||
for(long i = startByte; i < intern_endByte + 1; i++) {
|
||||
Color byteColor = defaultForeColor;
|
||||
Color bgColor = Color.Transparent;
|
||||
bool isSelectedByte = i >= _bytePos && i <= (_bytePos + _selectionLength - 1) && _selectionLength != 0;
|
||||
if(this.ByteColorProvider != null) {
|
||||
byteColor = this.ByteColorProvider.GetByteColor(_startByte, i, out bgColor);
|
||||
}
|
||||
|
||||
using(Brush byteBrush = new SolidBrush(byteColor)) {
|
||||
if(isSelectedByte && isKeyInterpreterActive) {
|
||||
PaintHexStringSelected(g, b, byteBrush, selBrushBack, gridPoint, prevSelected);
|
||||
prevSelected = true;
|
||||
} else {
|
||||
if(bgColor != Color.Transparent) {
|
||||
using(Brush bgBrush = new SolidBrush(bgColor)) {
|
||||
PaintHexStringSelected(g, b, byteBrush, bgBrush, gridPoint, prevBgColor == bgColor);
|
||||
}
|
||||
} else {
|
||||
PaintHexString(g, b, byteBrush, gridPoint);
|
||||
}
|
||||
prevSelected = false;
|
||||
counter++;
|
||||
|
||||
Point currentPoint = GetGridBytePoint(counter);
|
||||
|
||||
bool lineChanged = false;
|
||||
if(yPrevious != currentPoint.Y) {
|
||||
if(_xPosList.ContainsKey(yPrevious)) {
|
||||
_xPosList[yPrevious].Add(xPrevious);
|
||||
}
|
||||
prevBgColor = bgColor;
|
||||
|
||||
string s;
|
||||
if(skipCount > 0) {
|
||||
skipCount--;
|
||||
s = "";
|
||||
} else {
|
||||
long len = _byteProvider.Length;
|
||||
UInt64 tblValue = (UInt64)b;
|
||||
for(int j = 1; j < 8; j++) {
|
||||
if(len > i + j) {
|
||||
tblValue += (UInt64)_byteProvider.ReadByte(i+j) << (8 * j);
|
||||
}
|
||||
}
|
||||
|
||||
int keyLength;
|
||||
s = ByteCharConverter.ToChar(tblValue, out keyLength);
|
||||
skipCount = keyLength - 1;
|
||||
}
|
||||
|
||||
float width = (float)Math.Ceiling(g.MeasureString(s, Font, 1000, _stringFormat).Width);
|
||||
float xPos = byteStringPointF.X+xOffset;
|
||||
_xPosCache[gridPoint] = xPos;
|
||||
_xPosList[gridPoint.Y].Add(xPos);
|
||||
|
||||
if(gridPoint == caretPoint) {
|
||||
int caretWidth = (this.InsertActive) ? 1 : (int)width;
|
||||
int caretHeight = (int)_charSize.Height;
|
||||
g.FillRectangle(Brushes.Yellow, xPos - 1, _caretPos.Y, caretWidth, caretHeight);
|
||||
g.DrawRectangle(Pens.Gray, xPos - 1, _caretPos.Y, caretWidth, caretHeight);
|
||||
}
|
||||
|
||||
if(isSelectedByte && isStringKeyInterpreterActive) {
|
||||
g.FillRectangle(selBrushBack, xPos, byteStringPointF.Y, width, _charSize.Height);
|
||||
g.DrawString(s, Font, byteBrush, new PointF(xPos, byteStringPointF.Y), _stringFormat);
|
||||
} else {
|
||||
g.DrawString(s, Font, byteBrush, new PointF(xPos, byteStringPointF.Y), _stringFormat);
|
||||
}
|
||||
|
||||
xOffset += width - _charSize.Width;
|
||||
xPrevious = xPos + width;
|
||||
_xPosList[currentPoint.Y] = new List<float>();
|
||||
_lineWidthCache[yPrevious] = _recStringView.Width + xOffset;
|
||||
xOffset = 0;
|
||||
yPrevious = currentPoint.Y;
|
||||
lineChanged = true;
|
||||
}
|
||||
|
||||
if(forceDraw || lineChanged || byteColor != prevByteColor || bgColor != prevBgColor || prevSelected != isSelectedByte) {
|
||||
outputHex(prevByteColor, prevSelected ? _selectionBackColor : prevBgColor);
|
||||
gridPoint = GetGridBytePoint(counter);
|
||||
prevXOffset = xOffset;
|
||||
forceDraw = false;
|
||||
}
|
||||
|
||||
byte b = _byteProvider.ReadByte(i);
|
||||
bytesToDisplay.Add(b);
|
||||
|
||||
prevSelected = isSelectedByte;
|
||||
prevBgColor = bgColor;
|
||||
prevByteColor = byteColor;
|
||||
|
||||
if(!_stringViewVisible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string s;
|
||||
if(skipCount > 0) {
|
||||
skipCount--;
|
||||
s = "";
|
||||
} else {
|
||||
long len = _byteProvider.Length;
|
||||
UInt64 tblValue = (UInt64)b;
|
||||
for(int j = 1; j < 8; j++) {
|
||||
if(len > i + j) {
|
||||
tblValue += (UInt64)_byteProvider.ReadByte(i + j) << (8 * j);
|
||||
}
|
||||
}
|
||||
|
||||
int keyLength;
|
||||
s = ByteCharConverter.ToChar(tblValue, out keyLength);
|
||||
skipCount = keyLength - 1;
|
||||
}
|
||||
|
||||
float width;
|
||||
if(!_measureCache.TryGetValue(s, out width)) {
|
||||
width = g.MeasureString(s, Font, 1000, _stringFormat).Width;
|
||||
_measureCache[s] = width;
|
||||
}
|
||||
|
||||
PointF byteStringPointF = GetByteStringPointF(currentPoint, false);
|
||||
float xPos = byteStringPointF.X + xOffset;
|
||||
if(currentPoint.Y < 150) {
|
||||
_xPosCache[currentPoint.Y * 64 + currentPoint.X] = xPos;
|
||||
}
|
||||
_xPosList[currentPoint.Y].Add(xPos);
|
||||
|
||||
if(currentPoint == caretPoint) {
|
||||
caretWidth = width;
|
||||
}
|
||||
|
||||
stringToDisplay += s;
|
||||
|
||||
if(s.Length > 1 || s.Length > 0 && s[0] > 127 || s[0] < 32) {
|
||||
//Force draw if we hit a non-ascii character (to avoid minor positioning issues)
|
||||
forceDraw = true;
|
||||
}
|
||||
|
||||
xOffset += width - _charSize.Width;
|
||||
xPrevious = xPos + width;
|
||||
}
|
||||
}
|
||||
outputHex(prevByteColor, prevBgColor);
|
||||
}
|
||||
|
||||
float GetLineWidth(int y)
|
||||
|
@ -2732,134 +2730,27 @@ namespace Be.Windows.Forms
|
|||
|
||||
void PaintCurrentBytesSign(Graphics g)
|
||||
{
|
||||
if(_keyInterpreter != null && _bytePos != -1 && Enabled) {
|
||||
if(_selectionLength == 0 && _keyInterpreter != null && _bytePos != -1 && Enabled) {
|
||||
if(_keyInterpreter.GetType() == typeof(KeyInterpreter)) {
|
||||
if(_selectionLength == 0) {
|
||||
Point gp = GetGridBytePoint(_bytePos - _startByte);
|
||||
PointF pf = GetByteStringPointF(gp);
|
||||
Point gp2 = GetGridBytePoint(_bytePos - _startByte + 1);
|
||||
PointF pf2 = GetByteStringPointF(gp2);
|
||||
Point gp = GetGridBytePoint(_bytePos - _startByte);
|
||||
PointF pf = GetByteStringPointF(gp);
|
||||
Point gp2 = GetGridBytePoint(_bytePos - _startByte + 1);
|
||||
PointF pf2 = GetByteStringPointF(gp2);
|
||||
|
||||
Size s;
|
||||
if(gp.X > gp2.X) {
|
||||
s = new Size((int)(GetLineWidth(gp.Y) - (pf.X - _recStringView.X)), (int)_charSize.Height);
|
||||
} else {
|
||||
s = new Size((int)(pf2.X - pf.X), (int)_charSize.Height);
|
||||
}
|
||||
Rectangle r = new Rectangle((int)pf.X, (int)pf.Y, s.Width, s.Height);
|
||||
PaintCurrentByteSign(g, r);
|
||||
Size s;
|
||||
if(gp.X > gp2.X) {
|
||||
s = new Size((int)(GetLineWidth(gp.Y) - (pf.X - _recStringView.X)), (int)_charSize.Height);
|
||||
} else {
|
||||
int lineWidth = (int)(_recStringView.Width - _charSize.Width);
|
||||
|
||||
Point startSelGridPoint = GetGridBytePoint(_bytePos - _startByte);
|
||||
PointF startSelPointF = GetByteStringPointF(startSelGridPoint);
|
||||
|
||||
Point endSelGridPoint = GetGridBytePoint(_bytePos - _startByte + _selectionLength);
|
||||
PointF endSelPointF = GetByteStringPointF(endSelGridPoint);
|
||||
|
||||
int multiLine = endSelGridPoint.Y - startSelGridPoint.Y;
|
||||
if(multiLine == 0) {
|
||||
Rectangle singleLine = new Rectangle(
|
||||
(int)startSelPointF.X,
|
||||
(int)startSelPointF.Y,
|
||||
(int)(endSelPointF.X - startSelPointF.X),
|
||||
(int)_charSize.Height);
|
||||
|
||||
PaintCurrentByteSign(g, singleLine);
|
||||
} else {
|
||||
Rectangle firstLine = new Rectangle(
|
||||
(int)startSelPointF.X,
|
||||
(int)startSelPointF.Y,
|
||||
(int)(_recStringView.X + GetLineWidth(startSelGridPoint.Y) - startSelPointF.X),
|
||||
(int)_charSize.Height);
|
||||
|
||||
PaintCurrentByteSign(g, firstLine);
|
||||
|
||||
for(int i = 0; i < multiLine - 1; i++) {
|
||||
Rectangle betweenLines = new Rectangle(
|
||||
_recStringView.X,
|
||||
(int)(startSelPointF.Y + _charSize.Height * (i + 1)),
|
||||
(int)GetLineWidth(startSelGridPoint.Y + i + 1),
|
||||
(int)(_charSize.Height));
|
||||
|
||||
PaintCurrentByteSign(g, betweenLines);
|
||||
}
|
||||
|
||||
Rectangle lastLine = new Rectangle(
|
||||
_recStringView.X,
|
||||
(int)endSelPointF.Y,
|
||||
(int)(endSelPointF.X - _recStringView.X),
|
||||
(int)_charSize.Height);
|
||||
|
||||
PaintCurrentByteSign(g, lastLine);
|
||||
}
|
||||
s = new Size((int)(pf2.X - pf.X), (int)_charSize.Height);
|
||||
}
|
||||
Rectangle r = new Rectangle((int)pf.X, (int)pf.Y, s.Width, s.Height);
|
||||
PaintCurrentByteSign(g, r);
|
||||
} else {
|
||||
if(_selectionLength == 0) {
|
||||
Point gp = GetGridBytePoint(_bytePos - _startByte);
|
||||
PointF pf = GetBytePointF(gp);
|
||||
Size s = new Size((int)_charSize.Width * 2, (int)_charSize.Height);
|
||||
Rectangle r = new Rectangle((int)pf.X, (int)pf.Y, s.Width, s.Height);
|
||||
PaintCurrentByteSign(g, r);
|
||||
} else {
|
||||
int lineWidth = (int)(_recHex.Width - _charSize.Width * 5);
|
||||
|
||||
Point startSelGridPoint = GetGridBytePoint(_bytePos - _startByte);
|
||||
PointF startSelPointF = GetBytePointF(startSelGridPoint);
|
||||
|
||||
Point endSelGridPoint = GetGridBytePoint(_bytePos - _startByte + _selectionLength - 1);
|
||||
PointF endSelPointF = GetBytePointF(endSelGridPoint);
|
||||
|
||||
int multiLine = endSelGridPoint.Y - startSelGridPoint.Y;
|
||||
if(multiLine == 0) {
|
||||
Rectangle singleLine = new Rectangle(
|
||||
(int)startSelPointF.X,
|
||||
(int)startSelPointF.Y,
|
||||
(int)(endSelPointF.X - startSelPointF.X + _charSize.Width * 2),
|
||||
(int)_charSize.Height);
|
||||
|
||||
if(singleLine.IntersectsWith(_recHex)) {
|
||||
singleLine.Intersect(_recHex);
|
||||
PaintCurrentByteSign(g, singleLine);
|
||||
}
|
||||
} else {
|
||||
Rectangle firstLine = new Rectangle(
|
||||
(int)startSelPointF.X,
|
||||
(int)startSelPointF.Y,
|
||||
(int)(_recHex.X + lineWidth - startSelPointF.X + _charSize.Width * 2),
|
||||
(int)_charSize.Height);
|
||||
|
||||
if(firstLine.IntersectsWith(_recHex)) {
|
||||
firstLine.Intersect(_recHex);
|
||||
PaintCurrentByteSign(g, firstLine);
|
||||
}
|
||||
|
||||
if(multiLine > 1) {
|
||||
Rectangle betweenLines = new Rectangle(
|
||||
_recHex.X,
|
||||
(int)(startSelPointF.Y + _charSize.Height),
|
||||
(int)(lineWidth + _charSize.Width * 2),
|
||||
(int)(_charSize.Height * (multiLine - 1)));
|
||||
|
||||
if(betweenLines.IntersectsWith(_recHex)) {
|
||||
betweenLines.Intersect(_recHex);
|
||||
PaintCurrentByteSign(g, betweenLines);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle lastLine = new Rectangle(
|
||||
_recHex.X,
|
||||
(int)endSelPointF.Y,
|
||||
(int)(endSelPointF.X - _recHex.X + _charSize.Width * 2),
|
||||
(int)_charSize.Height);
|
||||
|
||||
if(lastLine.IntersectsWith(_recHex)) {
|
||||
lastLine.Intersect(_recHex);
|
||||
PaintCurrentByteSign(g, lastLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
Point gp = GetGridBytePoint(_bytePos - _startByte);
|
||||
PointF pf = GetBytePointF(gp);
|
||||
Size s = new Size((int)(_charSize.Width * 2), (int)_charSize.Height);
|
||||
Rectangle r = new Rectangle((int)pf.X, (int)pf.Y, s.Width, s.Height);
|
||||
PaintCurrentByteSign(g, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2933,7 +2824,7 @@ namespace Be.Windows.Forms
|
|||
{
|
||||
charSize = this.CreateGraphics().MeasureString("A", Font, 100, _stringFormat);
|
||||
}
|
||||
CharSize = new SizeF((float)Math.Ceiling(charSize.Width), (float)Math.Ceiling(charSize.Height));
|
||||
CharSize = new SizeF((float)charSize.Width, (float)Math.Ceiling(charSize.Height));
|
||||
|
||||
int requiredWidth = 0;
|
||||
|
||||
|
@ -3063,14 +2954,17 @@ namespace Be.Windows.Forms
|
|||
return new PointF(x, y);
|
||||
}
|
||||
|
||||
Dictionary<Point, float> _xPosCache = new Dictionary<Point, float>();
|
||||
float[] _xPosCache = new float[64 * 150];
|
||||
Dictionary<int, List<float>> _xPosList = new Dictionary<int, List<float>>();
|
||||
PointF GetByteStringPointF(Point gp)
|
||||
PointF GetByteStringPointF(Point gp, bool useCache = true)
|
||||
{
|
||||
float x = (_charSize.Width) * gp.X + _recStringView.X;
|
||||
float y = (gp.Y + 1) * _charSize.Height - _charSize.Height + _recStringView.Y;
|
||||
if(_xPosCache.ContainsKey(gp)) {
|
||||
return new PointF(_xPosCache[gp], y);
|
||||
|
||||
float cachedXPos = gp.Y > 0 && gp.Y < 150 ? _xPosCache[gp.Y * 64 + gp.X] : -1;
|
||||
|
||||
if(useCache && cachedXPos >= 0) {
|
||||
return new PointF(cachedXPos, y);
|
||||
} else {
|
||||
return new PointF(x, y);
|
||||
}
|
||||
|
@ -3121,8 +3015,11 @@ namespace Be.Windows.Forms
|
|||
this.UpdateRectanglePositioning();
|
||||
this.UpdateCaret();
|
||||
this.Invalidate();
|
||||
|
||||
_measureCache = new Dictionary<string, float>();
|
||||
}
|
||||
}
|
||||
Dictionary<string, float> _measureCache = new Dictionary<string, float>();
|
||||
|
||||
/// <summary>
|
||||
/// Not used.
|
||||
|
|
|
@ -15,10 +15,15 @@ namespace Be.Windows.Forms
|
|||
Dictionary<TblKey, string> _tblRules;
|
||||
Dictionary<string, TblKey> _reverseTblRules;
|
||||
List<string> _stringList;
|
||||
bool[] _hasPotentialRule = new bool[256];
|
||||
|
||||
public TblByteCharConverter(Dictionary<TblKey, string> tblRules)
|
||||
{
|
||||
this._tblRules = tblRules;
|
||||
foreach(KeyValuePair<TblKey, string> kvp in tblRules) {
|
||||
_hasPotentialRule[kvp.Key.Key & 0xFF] = true;
|
||||
}
|
||||
|
||||
this._stringList = new List<string>();
|
||||
this._reverseTblRules = new Dictionary<string, TblKey>();
|
||||
foreach(KeyValuePair<TblKey, string> kvp in tblRules) {
|
||||
|
@ -43,6 +48,11 @@ namespace Be.Windows.Forms
|
|||
/// <returns></returns>
|
||||
public virtual string ToChar(UInt64 value, out int keyLength)
|
||||
{
|
||||
if(!_hasPotentialRule[value & 0xFF]) {
|
||||
keyLength = 1;
|
||||
return ".";
|
||||
}
|
||||
|
||||
int byteCount = 8;
|
||||
string result;
|
||||
while(!_tblRules.TryGetValue(new TblKey() { Key = value, Length = byteCount }, out result) && byteCount > 0) {
|
||||
|
|
67
GUI.NET/Debugger/frmMemoryViewer.Designer.cs
generated
67
GUI.NET/Debugger/frmMemoryViewer.Designer.cs
generated
|
@ -31,7 +31,6 @@
|
|||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.ctrlHexViewer = new Mesen.GUI.Debugger.Controls.ctrlHexViewer();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblViewMemoryType = new System.Windows.Forms.Label();
|
||||
|
@ -78,8 +77,13 @@
|
|||
this.mnuIncreaseFontSize = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuDecreaseFontSize = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuResetFontSize = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.autorefreshSpeedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAutoRefreshLow = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAutoRefreshNormal = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAutoRefreshHigh = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuShowCharacters = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuShowLabelInfoOnMouseOver = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -98,7 +102,6 @@
|
|||
this.ctrlMemoryAccessCounters = new Mesen.GUI.Debugger.Controls.ctrlMemoryAccessCounters();
|
||||
this.tpgProfiler = new System.Windows.Forms.TabPage();
|
||||
this.ctrlProfiler = new Mesen.GUI.Debugger.Controls.ctrlProfiler();
|
||||
this.tmrRefresh = new System.Windows.Forms.Timer(this.components);
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.toolStrip1.SuspendLayout();
|
||||
|
@ -252,8 +255,10 @@
|
|||
this.toolStripMenuItem5,
|
||||
this.mnuConfigureColors,
|
||||
this.fontSizeToolStripMenuItem,
|
||||
this.mnuRefresh,
|
||||
this.autorefreshSpeedToolStripMenuItem,
|
||||
this.toolStripMenuItem2,
|
||||
this.mnuRefresh,
|
||||
this.toolStripMenuItem9,
|
||||
this.mnuAutoRefresh,
|
||||
this.mnuShowCharacters,
|
||||
this.mnuShowLabelInfoOnMouseOver});
|
||||
|
@ -518,6 +523,43 @@
|
|||
this.mnuResetFontSize.Text = "Reset to Default";
|
||||
this.mnuResetFontSize.Click += new System.EventHandler(this.mnuResetFontSize_Click);
|
||||
//
|
||||
// autorefreshSpeedToolStripMenuItem
|
||||
//
|
||||
this.autorefreshSpeedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuAutoRefreshLow,
|
||||
this.mnuAutoRefreshNormal,
|
||||
this.mnuAutoRefreshHigh});
|
||||
this.autorefreshSpeedToolStripMenuItem.Image = global::Mesen.GUI.Properties.Resources.Speed;
|
||||
this.autorefreshSpeedToolStripMenuItem.Name = "autorefreshSpeedToolStripMenuItem";
|
||||
this.autorefreshSpeedToolStripMenuItem.Size = new System.Drawing.Size(248, 22);
|
||||
this.autorefreshSpeedToolStripMenuItem.Text = "Auto-refresh Speed";
|
||||
//
|
||||
// mnuAutoRefreshLow
|
||||
//
|
||||
this.mnuAutoRefreshLow.Name = "mnuAutoRefreshLow";
|
||||
this.mnuAutoRefreshLow.Size = new System.Drawing.Size(159, 22);
|
||||
this.mnuAutoRefreshLow.Text = "Low (10 FPS)";
|
||||
this.mnuAutoRefreshLow.Click += new System.EventHandler(this.mnuAutoRefreshSpeed_Click);
|
||||
//
|
||||
// mnuAutoRefreshNormal
|
||||
//
|
||||
this.mnuAutoRefreshNormal.Name = "mnuAutoRefreshNormal";
|
||||
this.mnuAutoRefreshNormal.Size = new System.Drawing.Size(159, 22);
|
||||
this.mnuAutoRefreshNormal.Text = "Normal (30 FPS)";
|
||||
this.mnuAutoRefreshNormal.Click += new System.EventHandler(this.mnuAutoRefreshSpeed_Click);
|
||||
//
|
||||
// mnuAutoRefreshHigh
|
||||
//
|
||||
this.mnuAutoRefreshHigh.Name = "mnuAutoRefreshHigh";
|
||||
this.mnuAutoRefreshHigh.Size = new System.Drawing.Size(159, 22);
|
||||
this.mnuAutoRefreshHigh.Text = "High (60 FPS)";
|
||||
this.mnuAutoRefreshHigh.Click += new System.EventHandler(this.mnuAutoRefreshSpeed_Click);
|
||||
//
|
||||
// toolStripMenuItem2
|
||||
//
|
||||
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
|
||||
this.toolStripMenuItem2.Size = new System.Drawing.Size(245, 6);
|
||||
//
|
||||
// mnuRefresh
|
||||
//
|
||||
this.mnuRefresh.Image = global::Mesen.GUI.Properties.Resources.Reset;
|
||||
|
@ -527,10 +569,10 @@
|
|||
this.mnuRefresh.Text = "Refresh";
|
||||
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
|
||||
//
|
||||
// toolStripMenuItem2
|
||||
// toolStripMenuItem9
|
||||
//
|
||||
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
|
||||
this.toolStripMenuItem2.Size = new System.Drawing.Size(245, 6);
|
||||
this.toolStripMenuItem9.Name = "toolStripMenuItem9";
|
||||
this.toolStripMenuItem9.Size = new System.Drawing.Size(245, 6);
|
||||
//
|
||||
// mnuAutoRefresh
|
||||
//
|
||||
|
@ -712,11 +754,6 @@
|
|||
this.ctrlProfiler.Size = new System.Drawing.Size(606, 343);
|
||||
this.ctrlProfiler.TabIndex = 0;
|
||||
//
|
||||
// tmrRefresh
|
||||
//
|
||||
this.tmrRefresh.Enabled = true;
|
||||
this.tmrRefresh.Tick += new System.EventHandler(this.tmrRefresh_Tick);
|
||||
//
|
||||
// frmMemoryViewer
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
@ -778,7 +815,6 @@
|
|||
private System.Windows.Forms.TabPage tpgMemoryViewer;
|
||||
private System.Windows.Forms.TabPage tpgAccessCounters;
|
||||
private Controls.ctrlMemoryAccessCounters ctrlMemoryAccessCounters;
|
||||
private System.Windows.Forms.Timer tmrRefresh;
|
||||
private System.Windows.Forms.TabPage tpgProfiler;
|
||||
private Controls.ctrlProfiler ctrlProfiler;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLoadTblFile;
|
||||
|
@ -815,5 +851,10 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuHighlightLabelledBytes;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem8;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuHighlightDmcDataBytes;
|
||||
private System.Windows.Forms.ToolStripMenuItem autorefreshSpeedToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshLow;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshNormal;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshHigh;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem9;
|
||||
}
|
||||
}
|
|
@ -22,6 +22,8 @@ namespace Mesen.GUI.Debugger
|
|||
private DebugMemoryType _memoryType = DebugMemoryType.CpuMemory;
|
||||
private int _previousIndex = -1;
|
||||
private DebugWorkspace _previousWorkspace;
|
||||
private bool _updating = false;
|
||||
private DateTime _lastUpdate = DateTime.MinValue;
|
||||
|
||||
public frmMemoryViewer()
|
||||
{
|
||||
|
@ -33,6 +35,8 @@ namespace Mesen.GUI.Debugger
|
|||
base.OnLoad(e);
|
||||
|
||||
this.mnuAutoRefresh.Checked = ConfigManager.Config.DebugInfo.RamAutoRefresh;
|
||||
UpdateRefreshSpeedMenu();
|
||||
|
||||
this.mnuShowCharacters.Checked = ConfigManager.Config.DebugInfo.RamShowCharacters;
|
||||
this.mnuShowLabelInfoOnMouseOver.Checked = ConfigManager.Config.DebugInfo.RamShowLabelInfo;
|
||||
|
||||
|
@ -106,6 +110,23 @@ namespace Mesen.GUI.Debugger
|
|||
{
|
||||
if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) {
|
||||
this.BeginInvoke((MethodInvoker)(() => this.RefreshData()));
|
||||
} else if(e.NotificationType == InteropEmu.ConsoleNotificationType.PpuViewerDisplayFrame) {
|
||||
int refreshDelay = 90;
|
||||
switch(ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed) {
|
||||
case RefreshSpeed.Low: refreshDelay= 90; break;
|
||||
case RefreshSpeed.Normal: refreshDelay = 32; break;
|
||||
case RefreshSpeed.High: refreshDelay = 16; break;
|
||||
}
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
if(!_updating && ConfigManager.Config.DebugInfo.RamAutoRefresh && (now - _lastUpdate).Milliseconds >= refreshDelay) {
|
||||
_lastUpdate = now;
|
||||
_updating = true;
|
||||
this.BeginInvoke((Action)(() => {
|
||||
this.RefreshData();
|
||||
_updating = false;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,17 +318,8 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
}
|
||||
|
||||
private void tmrRefresh_Tick(object sender, EventArgs e)
|
||||
{
|
||||
if(this.mnuAutoRefresh.Checked) {
|
||||
this.RefreshData();
|
||||
}
|
||||
}
|
||||
|
||||
private void tabMain_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
this.tmrRefresh.Interval = this.tabMain.SelectedTab == this.tpgMemoryViewer ? 100 : 500;
|
||||
|
||||
if(this.tabMain.SelectedTab == this.tpgProfiler) {
|
||||
this.ctrlProfiler.RefreshData();
|
||||
}
|
||||
|
@ -654,5 +666,26 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuAutoRefreshSpeed_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(sender == mnuAutoRefreshLow) {
|
||||
ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed = RefreshSpeed.Low;
|
||||
} else if(sender == mnuAutoRefreshNormal) {
|
||||
ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed = RefreshSpeed.Normal;
|
||||
} else if(sender == mnuAutoRefreshHigh) {
|
||||
ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed = RefreshSpeed.High;
|
||||
}
|
||||
ConfigManager.ApplyChanges();
|
||||
|
||||
UpdateRefreshSpeedMenu();
|
||||
}
|
||||
|
||||
private void UpdateRefreshSpeedMenu()
|
||||
{
|
||||
mnuAutoRefreshLow.Checked = ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed == RefreshSpeed.Low;
|
||||
mnuAutoRefreshNormal.Checked = ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed == RefreshSpeed.Normal;
|
||||
mnuAutoRefreshHigh.Checked = ConfigManager.Config.DebugInfo.RamAutoRefreshSpeed == RefreshSpeed.High;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,4 @@
|
|||
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>222, 17</value>
|
||||
</metadata>
|
||||
<metadata name="tmrRefresh.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>327, 17</value>
|
||||
</metadata>
|
||||
</root>
|
Loading…
Add table
Reference in a new issue