Debugger: Added paste/undo support in hex editor

This commit is contained in:
Sour 2018-02-24 14:23:54 -05:00
parent e0611e7a9d
commit d62d701e64
26 changed files with 617 additions and 1105 deletions

View file

@ -1161,6 +1161,25 @@ void BaseMapper::GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* h
}
}
vector<uint8_t> BaseMapper::GetPrgChrCopy()
{
vector<uint8_t> data;
data.resize(_prgSize + (_onlyChrRam ? 0 : _chrRomSize));
memcpy(data.data(), _prgRom, _prgSize);
if(!_onlyChrRam) {
memcpy(data.data() + _prgSize, _chrRom, _chrRomSize);
}
return data;
}
void BaseMapper::RestorePrgChrBackup(vector<uint8_t> &backupData)
{
memcpy(_prgRom, backupData.data(), _prgSize);
if(!_onlyChrRam) {
memcpy(_chrRom, backupData.data() + _prgSize, _chrRomSize);
}
}
void BaseMapper::RevertPrgChrChanges()
{
memcpy(_prgRom, _originalPrgRom.data(), _originalPrgRom.size());

View file

@ -234,6 +234,9 @@ public:
NESHeader GetNesHeader();
void GetRomFileData(vector<uint8_t> &out, bool asIpsFile, uint8_t* header);
vector<uint8_t> GetPrgChrCopy();
void RestorePrgChrBackup(vector<uint8_t>& backupData);
void RevertPrgChrChanges();
bool HasPrgChrChanges();
};

View file

@ -45,6 +45,32 @@ void MemoryDumper::SetMemoryState(DebugMemoryType type, uint8_t *buffer)
}
}
bool MemoryDumper::HasUndoHistory()
{
return _undoHistory.size() > 0;
}
void MemoryDumper::PerformUndo()
{
if(!_undoHistory.empty()) {
_mapper->RestorePrgChrBackup(_undoHistory.back());
_undoHistory.pop_back();
_debugger->UpdateCdlCache();
}
}
void MemoryDumper::AddUndoHistory(vector<uint8_t> &originalRomData)
{
vector<uint8_t> newData = _mapper->GetPrgChrCopy();
if(memcmp(originalRomData.data(), newData.data(), originalRomData.size()) != 0) {
//Add a step in the undo history
_undoHistory.push_back(originalRomData);
if(_undoHistory.size() > 100) {
_undoHistory.pop_front();
}
}
}
uint32_t MemoryDumper::GetMemorySize(DebugMemoryType type)
{
switch(type) {
@ -111,6 +137,7 @@ uint32_t MemoryDumper::GetMemoryState(DebugMemoryType type, uint8_t *buffer)
void MemoryDumper::SetMemoryValues(DebugMemoryType memoryType, uint32_t address, uint8_t* data, int32_t length)
{
vector<uint8_t> originalRomData = _mapper->GetPrgChrCopy();
for(int i = 0; i < length; i++) {
SetMemoryValue(memoryType, address+i, data[i], true);
}
@ -125,10 +152,17 @@ void MemoryDumper::SetMemoryValues(DebugMemoryType memoryType, uint32_t address,
_disassembler->RebuildPrgRomCache(infoStart.Address, length);
}
}
AddUndoHistory(originalRomData);
}
void MemoryDumper::SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value, bool preventRebuildCache, bool disableSideEffects)
{
vector<uint8_t> originalRomData;
if(!preventRebuildCache) {
originalRomData = _mapper->GetPrgChrCopy();
}
switch(memoryType) {
case DebugMemoryType::CpuMemory:
if(disableSideEffects) {
@ -168,6 +202,10 @@ void MemoryDumper::SetMemoryValue(DebugMemoryType memoryType, uint32_t address,
case DebugMemoryType::InternalRam: _memoryManager->DebugWrite(address, value); break;
}
if(!preventRebuildCache) {
AddUndoHistory(originalRomData);
}
}
uint16_t MemoryDumper::GetMemoryValueWord(DebugMemoryType memoryType, uint32_t address, bool disableSideEffects)

View file

@ -77,13 +77,20 @@ private:
shared_ptr<CodeDataLogger> _codeDataLogger;
shared_ptr<Disassembler> _disassembler;
std::deque<vector<uint8_t>> _undoHistory;
std::unordered_map<TileKey, uint32_t> _paletteByTile;
void AddUndoHistory(vector<uint8_t>& originalRomData);
public:
MemoryDumper(shared_ptr<PPU> ppu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper, shared_ptr<CodeDataLogger> codeDataLogger, Debugger *debugger, shared_ptr<Disassembler> disassembler);
void GatherChrPaletteInfo();
bool HasUndoHistory();
void PerformUndo();
uint32_t GetMemorySize(DebugMemoryType type);
uint32_t GetMemoryState(DebugMemoryType type, uint8_t *buffer);
void GetNametable(int nametableIndex, bool useGrayscalePalette, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData);

View file

@ -78,6 +78,7 @@
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.picCloseOccurrenceList = new System.Windows.Forms.PictureBox();
this.lblSearchResult = new System.Windows.Forms.Label();
this.mnuUndoPrgChrEdit = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuCode.SuspendLayout();
this.contextMenuMargin.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
@ -96,6 +97,7 @@
this.toolStripMenuItem4,
this.mnuEditSelectedCode,
this.mnuEditSubroutine,
this.mnuUndoPrgChrEdit,
this.copySelectionToolStripMenuItem,
this.toolStripMenuItem7,
this.mnuShowNextStatement,
@ -117,7 +119,7 @@
this.mnuNavigateBackward,
this.mnuNavigateForward});
this.contextMenuCode.Name = "contextMenuWatch";
this.contextMenuCode.Size = new System.Drawing.Size(259, 420);
this.contextMenuCode.Size = new System.Drawing.Size(259, 464);
this.contextMenuCode.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.contextMenuCode_Closed);
this.contextMenuCode.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuCode_Opening);
//
@ -296,6 +298,7 @@
//
// mnuEditLabel
//
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEditLabel.Name = "mnuEditLabel";
this.mnuEditLabel.ShortcutKeys = System.Windows.Forms.Keys.F2;
this.mnuEditLabel.Size = new System.Drawing.Size(258, 22);
@ -396,6 +399,7 @@
this.ctrlCodeViewer.Name = "ctrlCodeViewer";
this.ctrlCodeViewer.ShowContentNotes = false;
this.ctrlCodeViewer.ShowLineNumberNotes = false;
this.ctrlCodeViewer.ShowMemoryValues = false;
this.ctrlCodeViewer.ShowScrollbars = true;
this.ctrlCodeViewer.ShowSingleContentLineNotes = true;
this.ctrlCodeViewer.ShowSingleLineLineNumberNotes = false;
@ -548,6 +552,15 @@
this.lblSearchResult.TabIndex = 11;
this.lblSearchResult.Text = "Search results for: ";
//
// mnuUndoPrgChrEdit
//
this.mnuUndoPrgChrEdit.Image = global::Mesen.GUI.Properties.Resources.Undo;
this.mnuUndoPrgChrEdit.Name = "mnuUndoPrgChrEdit";
this.mnuUndoPrgChrEdit.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));
this.mnuUndoPrgChrEdit.Size = new System.Drawing.Size(258, 22);
this.mnuUndoPrgChrEdit.Text = "Undo PRG/CHR Edit";
this.mnuUndoPrgChrEdit.Click += new System.EventHandler(this.mnuUndoPrgChrEdit_Click);
//
// ctrlDebuggerCode
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -621,5 +634,6 @@
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsData;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsUnidentifiedData;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
private System.Windows.Forms.ToolStripMenuItem mnuUndoPrgChrEdit;
}
}

View file

@ -597,8 +597,15 @@ namespace Mesen.GUI.Debugger
}
}
protected override bool ProcessKeyMessage(ref Message m)
{
this.UpdateContextMenuItemVisibility(mnuAddToWatch.Visible);
return base.ProcessKeyMessage(ref m);
}
public void UpdateContextMenuItemVisibility(bool visible)
{
mnuUndoPrgChrEdit.Enabled = InteropEmu.DebugHasUndoHistory();
mnuShowNextStatement.Enabled = _currentActiveAddress.HasValue;
mnuSetNextStatement.Enabled = _currentActiveAddress.HasValue;
mnuEditSelectedCode.Enabled = mnuEditSubroutine.Enabled = InteropEmu.DebugIsExecutionStopped() && ctrlCodeViewer.CurrentLine >= 0;
@ -982,6 +989,17 @@ namespace Mesen.GUI.Debugger
this.MarkSelectionAs(CdlPrgFlags.None);
}
private void mnuUndoPrgChrEdit_Click(object sender, EventArgs e)
{
if(InteropEmu.DebugHasUndoHistory()) {
InteropEmu.DebugPerformUndo();
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false);
}
}
}
class LineStyleProvider : ctrlTextbox.ILineStyleProvider
{
private ctrlDebuggerCode _code;

View file

@ -92,7 +92,7 @@
//
// mnuEditLabel
//
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEditLabel.Name = "mnuEditLabel";
this.mnuEditLabel.ShortcutKeys = System.Windows.Forms.Keys.F2;
this.mnuEditLabel.Size = new System.Drawing.Size(166, 22);

View file

@ -46,6 +46,25 @@
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.statusStrip = new System.Windows.Forms.StatusStrip();
this.lblLocation = new System.Windows.Forms.ToolStripStatusLabel();
this.ctxMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuMarkSelectionAs = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsData = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMarkAsUnidentifiedData = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditLabel = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuFreeze = new System.Windows.Forms.ToolStripMenuItem();
this.mnuUnfreeze = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
this.mnuUndo = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
this.mnuCopy = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPaste = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuSelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.tlpMain.SuspendLayout();
this.flowLayoutPanel1.SuspendLayout();
this.panelSearch.SuspendLayout();
@ -55,6 +74,7 @@
((System.ComponentModel.ISupportInitialize)(this.picSearchPrevious)).BeginInit();
this.flowLayoutPanel2.SuspendLayout();
this.statusStrip.SuspendLayout();
this.ctxMenuStrip.SuspendLayout();
this.SuspendLayout();
//
// tlpMain
@ -250,7 +270,9 @@
this.ctrlHexBox.ByteColorProvider = null;
this.ctrlHexBox.ColumnInfoVisible = true;
this.ctrlHexBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlHexBox.EnablePerByteNavigation = false;
this.ctrlHexBox.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.ctrlHexBox.HighDensityMode = false;
this.ctrlHexBox.InfoBackColor = System.Drawing.Color.DarkGray;
this.ctrlHexBox.LineInfoVisible = true;
this.ctrlHexBox.Location = new System.Drawing.Point(0, 27);
@ -285,6 +307,168 @@
this.lblLocation.Name = "lblLocation";
this.lblLocation.Size = new System.Drawing.Size(0, 17);
//
// ctxMenuStrip
//
this.ctxMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMarkSelectionAs,
this.toolStripMenuItem1,
this.mnuAddToWatch,
this.mnuEditBreakpoint,
this.mnuEditLabel,
this.toolStripMenuItem2,
this.mnuFreeze,
this.mnuUnfreeze,
this.toolStripMenuItem3,
this.mnuUndo,
this.toolStripMenuItem4,
this.mnuCopy,
this.mnuPaste,
this.toolStripMenuItem5,
this.mnuSelectAll});
this.ctxMenuStrip.Name = "ctxMenuStrip";
this.ctxMenuStrip.Size = new System.Drawing.Size(175, 276);
this.ctxMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.ctxMenuStrip_Opening);
//
// mnuMarkSelectionAs
//
this.mnuMarkSelectionAs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMarkAsCode,
this.mnuMarkAsData,
this.mnuMarkAsUnidentifiedData});
this.mnuMarkSelectionAs.Name = "mnuMarkSelectionAs";
this.mnuMarkSelectionAs.Size = new System.Drawing.Size(174, 22);
this.mnuMarkSelectionAs.Text = "Mark selection as...";
//
// mnuMarkAsCode
//
this.mnuMarkAsCode.Image = global::Mesen.GUI.Properties.Resources.Accept;
this.mnuMarkAsCode.Name = "mnuMarkAsCode";
this.mnuMarkAsCode.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.D1)));
this.mnuMarkAsCode.Size = new System.Drawing.Size(235, 22);
this.mnuMarkAsCode.Text = "Verified Code";
this.mnuMarkAsCode.Click += new System.EventHandler(this.mnuMarkAsCode_Click);
//
// mnuMarkAsData
//
this.mnuMarkAsData.Image = global::Mesen.GUI.Properties.Resources.VerifiedData;
this.mnuMarkAsData.Name = "mnuMarkAsData";
this.mnuMarkAsData.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.D2)));
this.mnuMarkAsData.Size = new System.Drawing.Size(235, 22);
this.mnuMarkAsData.Text = "Verified Data";
this.mnuMarkAsData.Click += new System.EventHandler(this.mnuMarkAsData_Click);
//
// mnuMarkAsUnidentifiedData
//
this.mnuMarkAsUnidentifiedData.Image = global::Mesen.GUI.Properties.Resources.UnidentifiedData;
this.mnuMarkAsUnidentifiedData.Name = "mnuMarkAsUnidentifiedData";
this.mnuMarkAsUnidentifiedData.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.D3)));
this.mnuMarkAsUnidentifiedData.Size = new System.Drawing.Size(235, 22);
this.mnuMarkAsUnidentifiedData.Text = "Unidentified Code/Data";
this.mnuMarkAsUnidentifiedData.Click += new System.EventHandler(this.mnuMarkAsUnidentifiedData_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(171, 6);
//
// mnuAddToWatch
//
this.mnuAddToWatch.Image = global::Mesen.GUI.Properties.Resources.Add;
this.mnuAddToWatch.Name = "mnuAddToWatch";
this.mnuAddToWatch.Size = new System.Drawing.Size(174, 22);
this.mnuAddToWatch.Text = "Add to Watch";
this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click);
//
// mnuEditBreakpoint
//
this.mnuEditBreakpoint.Image = global::Mesen.GUI.Properties.Resources.BreakpointEnableDisable;
this.mnuEditBreakpoint.Name = "mnuEditBreakpoint";
this.mnuEditBreakpoint.Size = new System.Drawing.Size(174, 22);
this.mnuEditBreakpoint.Text = "Edit Breakpoint";
this.mnuEditBreakpoint.Click += new System.EventHandler(this.mnuEditBreakpoint_Click);
//
// mnuEditLabel
//
this.mnuEditLabel.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEditLabel.Name = "mnuEditLabel";
this.mnuEditLabel.Size = new System.Drawing.Size(174, 22);
this.mnuEditLabel.Text = "Edit Label";
this.mnuEditLabel.Click += new System.EventHandler(this.mnuEditLabel_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(171, 6);
//
// mnuFreeze
//
this.mnuFreeze.Image = global::Mesen.GUI.Properties.Resources.Stop;
this.mnuFreeze.Name = "mnuFreeze";
this.mnuFreeze.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Q)));
this.mnuFreeze.Size = new System.Drawing.Size(174, 22);
this.mnuFreeze.Text = "Freeze";
this.mnuFreeze.Click += new System.EventHandler(this.mnuFreeze_Click);
//
// mnuUnfreeze
//
this.mnuUnfreeze.Image = global::Mesen.GUI.Properties.Resources.Play;
this.mnuUnfreeze.Name = "mnuUnfreeze";
this.mnuUnfreeze.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.W)));
this.mnuUnfreeze.Size = new System.Drawing.Size(174, 22);
this.mnuUnfreeze.Text = "Unfreeze";
this.mnuUnfreeze.Click += new System.EventHandler(this.mnuUnfreeze_Click);
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(171, 6);
//
// mnuUndo
//
this.mnuUndo.Image = global::Mesen.GUI.Properties.Resources.Undo;
this.mnuUndo.Name = "mnuUndo";
this.mnuUndo.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));
this.mnuUndo.Size = new System.Drawing.Size(174, 22);
this.mnuUndo.Text = "Undo";
this.mnuUndo.Click += new System.EventHandler(this.mnuUndo_Click);
//
// toolStripMenuItem4
//
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
this.toolStripMenuItem4.Size = new System.Drawing.Size(171, 6);
//
// mnuCopy
//
this.mnuCopy.Image = global::Mesen.GUI.Properties.Resources.Copy;
this.mnuCopy.Name = "mnuCopy";
this.mnuCopy.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
this.mnuCopy.Size = new System.Drawing.Size(174, 22);
this.mnuCopy.Text = "Copy";
this.mnuCopy.Click += new System.EventHandler(this.mnuCopy_Click);
//
// mnuPaste
//
this.mnuPaste.Image = global::Mesen.GUI.Properties.Resources.Paste;
this.mnuPaste.Name = "mnuPaste";
this.mnuPaste.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
this.mnuPaste.Size = new System.Drawing.Size(174, 22);
this.mnuPaste.Text = "Paste";
this.mnuPaste.Click += new System.EventHandler(this.mnuPaste_Click);
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
this.toolStripMenuItem5.Size = new System.Drawing.Size(171, 6);
//
// mnuSelectAll
//
this.mnuSelectAll.Image = global::Mesen.GUI.Properties.Resources.SelectAll;
this.mnuSelectAll.Name = "mnuSelectAll";
this.mnuSelectAll.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
this.mnuSelectAll.Size = new System.Drawing.Size(174, 22);
this.mnuSelectAll.Text = "Select All";
this.mnuSelectAll.Click += new System.EventHandler(this.mnuSelectAll_Click);
//
// ctrlHexViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -308,6 +492,7 @@
this.flowLayoutPanel2.PerformLayout();
this.statusStrip.ResumeLayout(false);
this.statusStrip.PerformLayout();
this.ctxMenuStrip.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@ -333,5 +518,24 @@
private System.Windows.Forms.CheckBox chkMatchCase;
private System.Windows.Forms.StatusStrip statusStrip;
private System.Windows.Forms.ToolStripStatusLabel lblLocation;
private System.Windows.Forms.ContextMenuStrip ctxMenuStrip;
private System.Windows.Forms.ToolStripMenuItem mnuMarkSelectionAs;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem mnuAddToWatch;
private System.Windows.Forms.ToolStripMenuItem mnuEditBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuEditLabel;
private System.Windows.Forms.ToolStripMenuItem mnuFreeze;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem mnuUnfreeze;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
private System.Windows.Forms.ToolStripMenuItem mnuCopy;
private System.Windows.Forms.ToolStripMenuItem mnuPaste;
private System.Windows.Forms.ToolStripMenuItem mnuSelectAll;
private System.Windows.Forms.ToolStripMenuItem mnuUndo;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsCode;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsData;
private System.Windows.Forms.ToolStripMenuItem mnuMarkAsUnidentifiedData;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
}
}

View file

@ -18,6 +18,7 @@ namespace Mesen.GUI.Debugger.Controls
{
private FindOptions _findOptions;
private StaticByteProvider _byteProvider;
private DebugMemoryType _memoryType;
public ctrlHexViewer()
{
@ -40,8 +41,11 @@ namespace Mesen.GUI.Debugger.Controls
return this._byteProvider != null ? this._byteProvider.Bytes.ToArray() : new byte[0];
}
public void SetData(byte[] data)
public void RefreshData(DebugMemoryType memoryType)
{
_memoryType = memoryType;
byte[] data = InteropEmu.DebugGetMemoryState(this._memoryType);
if(data != null) {
bool changed = true;
if(this._byteProvider != null && data.Length == this._byteProvider.Bytes.Count) {
@ -55,18 +59,17 @@ namespace Mesen.GUI.Debugger.Controls
}
if(changed) {
bool needInit = _byteProvider == null;
_byteProvider = new StaticByteProvider(data);
_byteProvider.ByteChanged += (int byteIndex, byte newValue, byte oldValue) => {
ByteChanged?.Invoke(byteIndex, newValue, oldValue);
InteropEmu.DebugSetMemoryValue(_memoryType, (UInt32)byteIndex, newValue);
};
_byteProvider.BytesChanged += (int byteIndex, byte[] values) => {
InteropEmu.DebugSetMemoryValues(_memoryType, (UInt32)byteIndex, values);
};
this.ctrlHexBox.ByteProvider = _byteProvider;
this.ctrlHexBox.ContextMenuStrip = this.ctxMenuStrip;
this.ctrlHexBox.Refresh();
if(needInit) {
InitializeContextMenu?.Invoke(this.ctrlHexBox, EventArgs.Empty);
}
}
}
}
@ -304,10 +307,7 @@ namespace Mesen.GUI.Debugger.Controls
add { this.ctrlHexBox.RequiredWidthChanged += value; }
remove { this.ctrlHexBox.RequiredWidthChanged -= value; }
}
public event EventHandler InitializeContextMenu;
public event ByteChangedHandler ByteChanged;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IByteCharConverter ByteCharConverter
{
@ -381,5 +381,207 @@ namespace Mesen.GUI.Debugger.Controls
{
UpdateLocationLabel();
}
private AddressType? GetAddressType()
{
switch(_memoryType) {
case DebugMemoryType.InternalRam: return AddressType.InternalRam;
case DebugMemoryType.WorkRam: return AddressType.WorkRam;
case DebugMemoryType.SaveRam: return AddressType.SaveRam;
case DebugMemoryType.PrgRom: return AddressType.PrgRom;
}
return null;
}
private int SelectionStartAddress { get { return (int)ctrlHexBox.SelectionStart; } }
private int SelectionEndAddress { get { return (int)(ctrlHexBox.SelectionStart + (ctrlHexBox.SelectionLength == 0 ? 0 : (ctrlHexBox.SelectionLength - 1))); } }
private void MarkSelectionAs(int start, int end, CdlPrgFlags type)
{
if(_memoryType == DebugMemoryType.CpuMemory) {
start = InteropEmu.DebugGetAbsoluteAddress((UInt32)start);
end = InteropEmu.DebugGetAbsoluteAddress((UInt32)end);
}
if(start >= 0 && end >= 0 && start <= end) {
InteropEmu.DebugMarkPrgBytesAs((UInt32)start, (UInt32)end, type);
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false, false);
}
}
}
private void mnuAddToWatch_Click(object sender, EventArgs e)
{
string[] toAdd = Enumerable.Range(SelectionStartAddress, SelectionEndAddress - SelectionStartAddress - 1).Select((num) => $"[${num.ToString("X4")}]").ToArray();
WatchManager.AddWatch(toAdd);
}
private void mnuEditBreakpoint_Click(object sender, EventArgs e)
{
UInt32 startAddress = (UInt32)SelectionStartAddress;
UInt32 endAddress = (UInt32)SelectionEndAddress;
BreakpointAddressType addressType = startAddress == endAddress ? BreakpointAddressType.SingleAddress : BreakpointAddressType.AddressRange;
Breakpoint bp = BreakpointManager.GetMatchingBreakpoint(startAddress, endAddress, this._memoryType);
if(bp == null) {
bp = new Breakpoint() { Address = startAddress, MemoryType = this._memoryType, StartAddress = startAddress, EndAddress = endAddress, AddressType = addressType, BreakOnWrite = true, BreakOnRead = true };
if(bp.IsCpuBreakpoint) {
bp.BreakOnExec = true;
}
}
BreakpointManager.EditBreakpoint(bp);
}
private void mnuEditLabel_Click(object sender, EventArgs e)
{
UInt32 address = (UInt32)ctrlHexBox.SelectionStart;
if(this._memoryType == DebugMemoryType.CpuMemory) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info);
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
} else {
ctrlLabelList.EditLabel(address, GetAddressType().Value);
}
}
private void mnuFreeze_Click(object sender, EventArgs e)
{
for(int i = SelectionStartAddress, end = SelectionEndAddress; i <= end; i++) {
InteropEmu.DebugSetFreezeState((UInt16)i, true);
}
}
private void mnuUnfreeze_Click(object sender, EventArgs e)
{
for(int i = SelectionStartAddress, end = SelectionEndAddress; i <= end; i++) {
InteropEmu.DebugSetFreezeState((UInt16)i, false);
}
}
private void mnuMarkAsCode_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(SelectionStartAddress, SelectionEndAddress, CdlPrgFlags.Code);
}
private void mnuMarkAsData_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(SelectionStartAddress, SelectionEndAddress, CdlPrgFlags.Data);
}
private void mnuMarkAsUnidentifiedData_Click(object sender, EventArgs e)
{
this.MarkSelectionAs(SelectionStartAddress, SelectionEndAddress, CdlPrgFlags.None);
}
protected override bool ProcessKeyMessage(ref Message m)
{
this.UpdateActionAvailability();
return base.ProcessKeyMessage(ref m);
}
private void UpdateActionAvailability()
{
UInt32 startAddress = (UInt32)SelectionStartAddress;
UInt32 endAddress = (UInt32)SelectionEndAddress;
string address = "$" + startAddress.ToString("X4");
string addressRange;
if(startAddress != endAddress) {
addressRange = "$" + startAddress.ToString("X4") + "-$" + endAddress.ToString("X4");
} else {
addressRange = address;
}
mnuEditLabel.Text = $"Edit Label ({address})";
mnuEditBreakpoint.Text = $"Edit Breakpoint ({addressRange})";
mnuAddToWatch.Text = $"Add to Watch ({addressRange})";
if(this._memoryType == DebugMemoryType.CpuMemory) {
bool[] freezeState = InteropEmu.DebugGetFreezeState((UInt16)startAddress, (UInt16)(endAddress - startAddress + 1));
mnuFreeze.Enabled = !freezeState.All((frozen) => frozen);
mnuUnfreeze.Enabled = freezeState.Any((frozen) => frozen);
mnuFreeze.Text = $"Freeze ({addressRange})";
mnuUnfreeze.Text = $"Unfreeze ({addressRange})";
} else {
mnuFreeze.Text = $"Freeze";
mnuUnfreeze.Text = $"Unfreeze";
mnuFreeze.Enabled = false;
mnuUnfreeze.Enabled = false;
}
if(this._memoryType == DebugMemoryType.CpuMemory) {
int absStart = InteropEmu.DebugGetAbsoluteAddress(startAddress);
int absEnd = InteropEmu.DebugGetAbsoluteAddress(endAddress);
if(absStart >= 0 && absEnd >= 0 && absStart <= absEnd) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
mnuMarkSelectionAs.Enabled = true;
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
mnuMarkSelectionAs.Enabled = false;
}
} else if(this._memoryType == DebugMemoryType.PrgRom) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
mnuMarkSelectionAs.Enabled = true;
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
mnuMarkSelectionAs.Enabled = false;
}
bool disableEditLabel = false;
if(this._memoryType == DebugMemoryType.CpuMemory) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType(startAddress, ref info);
disableEditLabel = info.Address == -1;
}
mnuEditLabel.Enabled = !disableEditLabel && (this._memoryType == DebugMemoryType.CpuMemory || this.GetAddressType().HasValue);
mnuEditBreakpoint.Enabled = DebugWindowManager.GetDebugger() != null && (
this._memoryType == DebugMemoryType.CpuMemory ||
this._memoryType == DebugMemoryType.PpuMemory ||
this._memoryType == DebugMemoryType.PrgRom ||
this._memoryType == DebugMemoryType.WorkRam ||
this._memoryType == DebugMemoryType.SaveRam ||
this._memoryType == DebugMemoryType.ChrRam ||
this._memoryType == DebugMemoryType.ChrRom ||
this._memoryType == DebugMemoryType.PaletteMemory
);
mnuAddToWatch.Enabled = this._memoryType == DebugMemoryType.CpuMemory;
mnuCopy.Enabled = ctrlHexBox.CanCopy();
mnuPaste.Enabled = ctrlHexBox.CanPaste();
mnuSelectAll.Enabled = ctrlHexBox.CanSelectAll();
mnuUndo.Enabled = InteropEmu.DebugHasUndoHistory();
}
private void ctxMenuStrip_Opening(object sender, CancelEventArgs e)
{
this.UpdateActionAvailability();
}
private void mnuCopy_Click(object sender, EventArgs e)
{
ctrlHexBox.CopyHex();
}
private void mnuPaste_Click(object sender, EventArgs e)
{
ctrlHexBox.Paste();
}
private void mnuSelectAll_Click(object sender, EventArgs e)
{
ctrlHexBox.SelectAll();
}
private void mnuUndo_Click(object sender, EventArgs e)
{
InteropEmu.DebugPerformUndo();
this.RefreshData(_memoryType);
}
}
}

View file

@ -123,4 +123,7 @@
<metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>
<metadata name="ctxMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>216, 17</value>
</metadata>
</root>

View file

@ -33,14 +33,14 @@
this.mnuEdit = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDelete = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAddBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuFindOccurrences = new System.Windows.Forms.ToolStripMenuItem();
this.lstLabels = new Mesen.GUI.Controls.DoubleBufferedListView();
this.colFunctionLabel = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colFunctionAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colMemoryAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.mnuAddToWatch = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAddBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.contextMenu.SuspendLayout();
this.SuspendLayout();
//
@ -70,7 +70,7 @@
//
// mnuEdit
//
this.mnuEdit.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEdit.Image = global::Mesen.GUI.Properties.Resources.EditLabel;
this.mnuEdit.Name = "mnuEdit";
this.mnuEdit.ShortcutKeys = System.Windows.Forms.Keys.F2;
this.mnuEdit.Size = new System.Drawing.Size(166, 22);
@ -91,6 +91,27 @@
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(163, 6);
//
// mnuAddBreakpoint
//
this.mnuAddBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint;
this.mnuAddBreakpoint.Name = "mnuAddBreakpoint";
this.mnuAddBreakpoint.Size = new System.Drawing.Size(166, 22);
this.mnuAddBreakpoint.Text = "Add breakpoint";
this.mnuAddBreakpoint.Click += new System.EventHandler(this.mnuAddBreakpoint_Click);
//
// mnuAddToWatch
//
this.mnuAddToWatch.Image = global::Mesen.GUI.Properties.Resources.Add;
this.mnuAddToWatch.Name = "mnuAddToWatch";
this.mnuAddToWatch.Size = new System.Drawing.Size(166, 22);
this.mnuAddToWatch.Text = "Add to watch";
this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(163, 6);
//
// mnuFindOccurrences
//
this.mnuFindOccurrences.Image = global::Mesen.GUI.Properties.Resources.Find;
@ -134,27 +155,6 @@
this.colMemoryAddress.Text = "ROM Addr";
this.colMemoryAddress.Width = 84;
//
// mnuAddToWatch
//
this.mnuAddToWatch.Image = global::Mesen.GUI.Properties.Resources.Add;
this.mnuAddToWatch.Name = "mnuAddToWatch";
this.mnuAddToWatch.Size = new System.Drawing.Size(166, 22);
this.mnuAddToWatch.Text = "Add to watch";
this.mnuAddToWatch.Click += new System.EventHandler(this.mnuAddToWatch_Click);
//
// mnuAddBreakpoint
//
this.mnuAddBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint;
this.mnuAddBreakpoint.Name = "mnuAddBreakpoint";
this.mnuAddBreakpoint.Size = new System.Drawing.Size(166, 22);
this.mnuAddBreakpoint.Text = "Add breakpoint";
this.mnuAddBreakpoint.Click += new System.EventHandler(this.mnuAddBreakpoint_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(163, 6);
//
// ctrlLabelList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

View file

@ -92,6 +92,9 @@ namespace Be.Windows.Forms
public delegate void ByteChangedHandler(int byteIndex, byte newValue, byte oldValue);
public event ByteChangedHandler ByteChanged;
public delegate void BytesChangedHandler(int byteIndex, byte[] values);
public event BytesChangedHandler BytesChanged;
/// <summary>
/// Reads a byte from the byte collection.
@ -115,6 +118,14 @@ namespace Be.Windows.Forms
}
}
public void WriteBytes(long index, byte[] values)
{
BytesChanged?.Invoke((int)index, values);
for(int i = 0; i < values.Length && index + i < _bytes.Count; i++) {
_bytes[(int)index+i] = values[i];
}
}
/// <summary>
/// Deletes bytes from the byte collection.
/// </summary>

View file

@ -1,569 +0,0 @@
using System;
using System.Text;
using System.IO;
namespace Be.Windows.Forms
{
/// <summary>
/// Implements a fully editable byte provider for file data of any size.
/// </summary>
/// <remarks>
/// Only changes to the file are stored in memory with reads from the
/// original data occurring as required.
/// </remarks>
public sealed class DynamicFileByteProvider : IByteProvider, IDisposable
{
const int COPY_BLOCK_SIZE = 4096;
string _fileName;
Stream _stream;
DataMap _dataMap;
long _totalLength;
bool _readOnly;
/// <summary>
/// Constructs a new <see cref="DynamicFileByteProvider" /> instance.
/// </summary>
/// <param name="fileName">The name of the file from which bytes should be provided.</param>
public DynamicFileByteProvider(string fileName) : this(fileName, false) { }
/// <summary>
/// Constructs a new <see cref="DynamicFileByteProvider" /> instance.
/// </summary>
/// <param name="fileName">The name of the file from which bytes should be provided.</param>
/// <param name="readOnly">True, opens the file in read-only mode.</param>
public DynamicFileByteProvider(string fileName, bool readOnly)
{
_fileName = fileName;
if (!readOnly)
{
_stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
}
else
{
_stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
_readOnly = readOnly;
ReInitialize();
}
/// <summary>
/// Constructs a new <see cref="DynamicFileByteProvider" /> instance.
/// </summary>
/// <param name="stream">the stream containing the data.</param>
/// <remarks>
/// The stream must supported seek operations.
/// </remarks>
public DynamicFileByteProvider(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
if (!stream.CanSeek)
throw new ArgumentException("stream must supported seek operations(CanSeek)");
_stream = stream;
_readOnly = !stream.CanWrite;
ReInitialize();
}
#region IByteProvider Members
/// <summary>
/// See <see cref="IByteProvider.LengthChanged" /> for more information.
/// </summary>
public event EventHandler LengthChanged;
/// <summary>
/// See <see cref="IByteProvider.Changed" /> for more information.
/// </summary>
public event EventHandler Changed;
/// <summary>
/// See <see cref="IByteProvider.ReadByte" /> for more information.
/// </summary>
public byte ReadByte(long index)
{
long blockOffset;
DataBlock block = GetDataBlock(index, out blockOffset);
FileDataBlock fileBlock = block as FileDataBlock;
if (fileBlock != null)
{
return ReadByteFromFile(fileBlock.FileOffset + index - blockOffset);
}
else
{
MemoryDataBlock memoryBlock = (MemoryDataBlock)block;
return memoryBlock.Data[index - blockOffset];
}
}
/// <summary>
/// See <see cref="IByteProvider.WriteByte" /> for more information.
/// </summary>
public void WriteByte(long index, byte value)
{
try
{
// Find the block affected.
long blockOffset;
DataBlock block = GetDataBlock(index, out blockOffset);
// If the byte is already in a memory block, modify it.
MemoryDataBlock memoryBlock = block as MemoryDataBlock;
if (memoryBlock != null)
{
memoryBlock.Data[index - blockOffset] = value;
return;
}
FileDataBlock fileBlock = (FileDataBlock)block;
// If the byte changing is the first byte in the block and the previous block is a memory block, extend that.
if (blockOffset == index && block.PreviousBlock != null)
{
MemoryDataBlock previousMemoryBlock = block.PreviousBlock as MemoryDataBlock;
if (previousMemoryBlock != null)
{
previousMemoryBlock.AddByteToEnd(value);
fileBlock.RemoveBytesFromStart(1);
if (fileBlock.Length == 0)
{
_dataMap.Remove(fileBlock);
}
return;
}
}
// If the byte changing is the last byte in the block and the next block is a memory block, extend that.
if (blockOffset + fileBlock.Length - 1 == index && block.NextBlock != null)
{
MemoryDataBlock nextMemoryBlock = block.NextBlock as MemoryDataBlock;
if (nextMemoryBlock != null)
{
nextMemoryBlock.AddByteToStart(value);
fileBlock.RemoveBytesFromEnd(1);
if (fileBlock.Length == 0)
{
_dataMap.Remove(fileBlock);
}
return;
}
}
// Split the block into a prefix and a suffix and place a memory block in-between.
FileDataBlock prefixBlock = null;
if (index > blockOffset)
{
prefixBlock = new FileDataBlock(fileBlock.FileOffset, index - blockOffset);
}
FileDataBlock suffixBlock = null;
if (index < blockOffset + fileBlock.Length - 1)
{
suffixBlock = new FileDataBlock(
fileBlock.FileOffset + index - blockOffset + 1,
fileBlock.Length - (index - blockOffset + 1));
}
block = _dataMap.Replace(block, new MemoryDataBlock(value));
if (prefixBlock != null)
{
_dataMap.AddBefore(block, prefixBlock);
}
if (suffixBlock != null)
{
_dataMap.AddAfter(block, suffixBlock);
}
}
finally
{
OnChanged(EventArgs.Empty);
}
}
/// <summary>
/// See <see cref="IByteProvider.InsertBytes" /> for more information.
/// </summary>
public void InsertBytes(long index, byte[] bs)
{
try
{
// Find the block affected.
long blockOffset;
DataBlock block = GetDataBlock(index, out blockOffset);
// If the insertion point is in a memory block, just insert it.
MemoryDataBlock memoryBlock = block as MemoryDataBlock;
if (memoryBlock != null)
{
memoryBlock.InsertBytes(index - blockOffset, bs);
return;
}
FileDataBlock fileBlock = (FileDataBlock)block;
// If the insertion point is at the start of a file block, and the previous block is a memory block, append it to that block.
if (blockOffset == index && block.PreviousBlock != null)
{
MemoryDataBlock previousMemoryBlock = block.PreviousBlock as MemoryDataBlock;
if (previousMemoryBlock != null)
{
previousMemoryBlock.InsertBytes(previousMemoryBlock.Length, bs);
return;
}
}
// Split the block into a prefix and a suffix and place a memory block in-between.
FileDataBlock prefixBlock = null;
if (index > blockOffset)
{
prefixBlock = new FileDataBlock(fileBlock.FileOffset, index - blockOffset);
}
FileDataBlock suffixBlock = null;
if (index < blockOffset + fileBlock.Length)
{
suffixBlock = new FileDataBlock(
fileBlock.FileOffset + index - blockOffset,
fileBlock.Length - (index - blockOffset));
}
block = _dataMap.Replace(block, new MemoryDataBlock(bs));
if (prefixBlock != null)
{
_dataMap.AddBefore(block, prefixBlock);
}
if (suffixBlock != null)
{
_dataMap.AddAfter(block, suffixBlock);
}
}
finally
{
_totalLength += bs.Length;
OnLengthChanged(EventArgs.Empty);
OnChanged(EventArgs.Empty);
}
}
/// <summary>
/// See <see cref="IByteProvider.DeleteBytes" /> for more information.
/// </summary>
public void DeleteBytes(long index, long length)
{
try
{
long bytesToDelete = length;
// Find the first block affected.
long blockOffset;
DataBlock block = GetDataBlock(index, out blockOffset);
// Truncate or remove each block as necessary.
while ((bytesToDelete > 0) && (block != null))
{
long blockLength = block.Length;
DataBlock nextBlock = block.NextBlock;
// Delete the appropriate section from the block (this may result in two blocks or a zero length block).
long count = Math.Min(bytesToDelete, blockLength - (index - blockOffset));
block.RemoveBytes(index - blockOffset, count);
if (block.Length == 0)
{
_dataMap.Remove(block);
if (_dataMap.FirstBlock == null)
{
_dataMap.AddFirst(new MemoryDataBlock(new byte[0]));
}
}
bytesToDelete -= count;
blockOffset += block.Length;
block = (bytesToDelete > 0) ? nextBlock : null;
}
}
finally
{
_totalLength -= length;
OnLengthChanged(EventArgs.Empty);
OnChanged(EventArgs.Empty);
}
}
/// <summary>
/// See <see cref="IByteProvider.Length" /> for more information.
/// </summary>
public long Length
{
get
{
return _totalLength;
}
}
/// <summary>
/// See <see cref="IByteProvider.HasChanges" /> for more information.
/// </summary>
public bool HasChanges()
{
if (_readOnly)
return false;
if (_totalLength != _stream.Length)
{
return true;
}
long offset = 0;
for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock)
{
FileDataBlock fileBlock = block as FileDataBlock;
if (fileBlock == null)
{
return true;
}
if (fileBlock.FileOffset != offset)
{
return true;
}
offset += fileBlock.Length;
}
return (offset != _stream.Length);
}
/// <summary>
/// See <see cref="IByteProvider.ApplyChanges" /> for more information.
/// </summary>
public void ApplyChanges()
{
if (_readOnly)
throw new OperationCanceledException("File is in read-only mode");
// This method is implemented to efficiently save the changes to the same file stream opened for reading.
// Saving to a separate file would be a much simpler implementation.
// Firstly, extend the file length (if necessary) to ensure that there is enough disk space.
if (_totalLength > _stream.Length)
{
_stream.SetLength(_totalLength);
}
// Secondly, shift around any file sections that have moved.
long dataOffset = 0;
for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock)
{
FileDataBlock fileBlock = block as FileDataBlock;
if (fileBlock != null && fileBlock.FileOffset != dataOffset)
{
MoveFileBlock(fileBlock, dataOffset);
}
dataOffset += block.Length;
}
// Next, write in-memory changes.
dataOffset = 0;
for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock)
{
MemoryDataBlock memoryBlock = block as MemoryDataBlock;
if (memoryBlock != null)
{
_stream.Position = dataOffset;
for (int memoryOffset = 0; memoryOffset < memoryBlock.Length; memoryOffset += COPY_BLOCK_SIZE)
{
_stream.Write(memoryBlock.Data, memoryOffset, (int)Math.Min(COPY_BLOCK_SIZE, memoryBlock.Length - memoryOffset));
}
}
dataOffset += block.Length;
}
// Finally, if the file has shortened, truncate the stream.
_stream.SetLength(_totalLength);
ReInitialize();
}
/// <summary>
/// See <see cref="IByteProvider.SupportsWriteByte" /> for more information.
/// </summary>
public bool SupportsWriteByte()
{
return !_readOnly;
}
/// <summary>
/// See <see cref="IByteProvider.SupportsInsertBytes" /> for more information.
/// </summary>
public bool SupportsInsertBytes()
{
return !_readOnly;
}
/// <summary>
/// See <see cref="IByteProvider.SupportsDeleteBytes" /> for more information.
/// </summary>
public bool SupportsDeleteBytes()
{
return !_readOnly;
}
#endregion
#region IDisposable Members
/// <summary>
/// See <see cref="Object.Finalize" /> for more information.
/// </summary>
~DynamicFileByteProvider()
{
Dispose();
}
/// <summary>
/// See <see cref="IDisposable.Dispose" /> for more information.
/// </summary>
public void Dispose()
{
if (_stream != null)
{
_stream.Close();
_stream = null;
}
_fileName = null;
_dataMap = null;
GC.SuppressFinalize(this);
}
#endregion
/// <summary>
/// Gets a value, if the file is opened in read-only mode.
/// </summary>
public bool ReadOnly
{
get { return _readOnly; }
}
void OnLengthChanged(EventArgs e)
{
if (LengthChanged != null)
LengthChanged(this, e);
}
void OnChanged(EventArgs e)
{
if (Changed != null)
{
Changed(this, e);
}
}
DataBlock GetDataBlock(long findOffset, out long blockOffset)
{
if (findOffset < 0 || findOffset > _totalLength)
{
throw new ArgumentOutOfRangeException("findOffset");
}
// Iterate over the blocks until the block containing the required offset is encountered.
blockOffset = 0;
for (DataBlock block = _dataMap.FirstBlock; block != null; block = block.NextBlock)
{
if ((blockOffset <= findOffset && blockOffset + block.Length > findOffset) || block.NextBlock == null)
{
return block;
}
blockOffset += block.Length;
}
return null;
}
FileDataBlock GetNextFileDataBlock(DataBlock block, long dataOffset, out long nextDataOffset)
{
// Iterate over the remaining blocks until a file block is encountered.
nextDataOffset = dataOffset + block.Length;
block = block.NextBlock;
while (block != null)
{
FileDataBlock fileBlock = block as FileDataBlock;
if (fileBlock != null)
{
return fileBlock;
}
nextDataOffset += block.Length;
block = block.NextBlock;
}
return null;
}
byte ReadByteFromFile(long fileOffset)
{
// Move to the correct position and read the byte.
if (_stream.Position != fileOffset)
{
_stream.Position = fileOffset;
}
return (byte)_stream.ReadByte();
}
void MoveFileBlock(FileDataBlock fileBlock, long dataOffset)
{
// First, determine whether the next file block needs to move before this one.
long nextDataOffset;
FileDataBlock nextFileBlock = GetNextFileDataBlock(fileBlock, dataOffset, out nextDataOffset);
if (nextFileBlock != null && dataOffset + fileBlock.Length > nextFileBlock.FileOffset)
{
// The next block needs to move first, so do that now.
MoveFileBlock(nextFileBlock, nextDataOffset);
}
// Now, move the block.
if (fileBlock.FileOffset > dataOffset)
{
// Move the section to earlier in the file stream (done in chunks starting at the beginning of the section).
byte[] buffer = new byte[COPY_BLOCK_SIZE];
for (long relativeOffset = 0; relativeOffset < fileBlock.Length; relativeOffset += buffer.Length)
{
long readOffset = fileBlock.FileOffset + relativeOffset;
int bytesToRead = (int)Math.Min(buffer.Length, fileBlock.Length - relativeOffset);
_stream.Position = readOffset;
_stream.Read(buffer, 0, bytesToRead);
long writeOffset = dataOffset + relativeOffset;
_stream.Position = writeOffset;
_stream.Write(buffer, 0, bytesToRead);
}
}
else
{
// Move the section to later in the file stream (done in chunks starting at the end of the section).
byte[] buffer = new byte[COPY_BLOCK_SIZE];
for (long relativeOffset = 0; relativeOffset < fileBlock.Length; relativeOffset += buffer.Length)
{
int bytesToRead = (int)Math.Min(buffer.Length, fileBlock.Length - relativeOffset);
long readOffset = fileBlock.FileOffset + fileBlock.Length - relativeOffset - bytesToRead;
_stream.Position = readOffset;
_stream.Read(buffer, 0, bytesToRead);
long writeOffset = dataOffset + fileBlock.Length - relativeOffset - bytesToRead;
_stream.Position = writeOffset;
_stream.Write(buffer, 0, bytesToRead);
}
}
// This block now points to a different position in the file.
fileBlock.SetFileOffset(dataOffset);
}
void ReInitialize()
{
_dataMap = new DataMap();
_dataMap.AddFirst(new FileDataBlock(0, _stream.Length));
_totalLength = _stream.Length;
}
}
}

View file

@ -1,273 +0,0 @@
using System;
using System.IO;
using System.Collections;
namespace Be.Windows.Forms
{
/// <summary>
/// Byte provider for (big) files.
/// </summary>
public class FileByteProvider : IByteProvider, IDisposable
{
#region WriteCollection class
/// <summary>
/// Represents the write buffer class
/// </summary>
class WriteCollection : DictionaryBase
{
/// <summary>
/// Gets or sets a byte in the collection
/// </summary>
public byte this[long index]
{
get { return (byte)this.Dictionary[index]; }
set { Dictionary[index] = value; }
}
/// <summary>
/// Adds a byte into the collection
/// </summary>
/// <param name="index">the index of the byte</param>
/// <param name="value">the value of the byte</param>
public void Add(long index, byte value)
{ Dictionary.Add(index, value); }
/// <summary>
/// Determines if a byte with the given index exists.
/// </summary>
/// <param name="index">the index of the byte</param>
/// <returns>true, if the is in the collection</returns>
public bool Contains(long index)
{ return Dictionary.Contains(index); }
}
#endregion
/// <summary>
/// Occurs, when the write buffer contains new changes.
/// </summary>
public event EventHandler Changed;
/// <summary>
/// Contains all changes
/// </summary>
WriteCollection _writes = new WriteCollection();
/// <summary>
/// Contains the file name.
/// </summary>
string _fileName;
/// <summary>
/// Contains the file stream.
/// </summary>
FileStream _fileStream;
/// <summary>
/// Read-only access.
/// </summary>
bool _readOnly;
/// <summary>
/// Initializes a new instance of the FileByteProvider class.
/// </summary>
/// <param name="fileName"></param>
public FileByteProvider(string fileName)
{
_fileName = fileName;
try
{
// try to open in write mode
_fileStream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
}
catch
{
// write mode failed, try to open in read-only and fileshare friendly mode.
try
{
_fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_readOnly = true;
}
catch
{
throw;
}
}
}
/// <summary>
/// Terminates the instance of the FileByteProvider class.
/// </summary>
~FileByteProvider()
{
Dispose();
}
/// <summary>
/// Raises the Changed event.
/// </summary>
/// <remarks>Never used.</remarks>
void OnChanged(EventArgs e)
{
if(Changed != null)
Changed(this, e);
}
/// <summary>
/// Gets the name of the file the byte provider is using.
/// </summary>
public string FileName
{
get { return _fileName; }
}
/// <summary>
/// Returns a value if there are some changes.
/// </summary>
/// <returns>true, if there are some changes</returns>
public bool HasChanges()
{
return (_writes.Count > 0);
}
/// <summary>
/// Updates the file with all changes the write buffer contains.
/// </summary>
public void ApplyChanges()
{
if (this._readOnly)
{
throw new Exception("File is in read-only mode.");
}
if(!HasChanges())
return;
IDictionaryEnumerator en = _writes.GetEnumerator();
while(en.MoveNext())
{
long index = (long)en.Key;
byte value = (byte)en.Value;
if(_fileStream.Position != index)
_fileStream.Position = index;
_fileStream.Write(new byte[] { value }, 0, 1);
}
_writes.Clear();
}
/// <summary>
/// Clears the write buffer and reject all changes made.
/// </summary>
public void RejectChanges()
{
_writes.Clear();
}
#region IByteProvider Members
/// <summary>
/// Never used.
/// </summary>
#pragma warning disable 0067
public event EventHandler LengthChanged;
#pragma warning restore 0067
/// <summary>
/// Reads a byte from the file.
/// </summary>
/// <param name="index">the index of the byte to read</param>
/// <returns>the byte</returns>
public byte ReadByte(long index)
{
if(_writes.Contains(index))
return _writes[index];
if(_fileStream.Position != index)
_fileStream.Position = index;
byte res = (byte)_fileStream.ReadByte();
return res;
}
/// <summary>
/// Gets the length of the file.
/// </summary>
public long Length
{
get
{
return _fileStream.Length;
}
}
/// <summary>
/// Writes a byte into write buffer
/// </summary>
public void WriteByte(long index, byte value)
{
if(_writes.Contains(index))
_writes[index] = value;
else
_writes.Add(index, value);
OnChanged(EventArgs.Empty);
}
/// <summary>
/// Not supported
/// </summary>
public void DeleteBytes(long index, long length)
{
throw new NotSupportedException("FileByteProvider.DeleteBytes");
}
/// <summary>
/// Not supported
/// </summary>
public void InsertBytes(long index, byte[] bs)
{
throw new NotSupportedException("FileByteProvider.InsertBytes");
}
/// <summary>
/// Returns true
/// </summary>
public bool SupportsWriteByte()
{
return !_readOnly;
}
/// <summary>
/// Returns false
/// </summary>
public bool SupportsInsertBytes()
{
return false;
}
/// <summary>
/// Returns false
/// </summary>
public bool SupportsDeleteBytes()
{
return false;
}
#endregion
#region IDisposable Members
/// <summary>
/// Releases the file handle used by the FileByteProvider.
/// </summary>
public void Dispose()
{
if(_fileStream != null)
{
_fileName = null;
_fileStream.Close();
_fileStream = null;
}
GC.SuppressFinalize(this);
}
#endregion
}
}

View file

@ -2199,29 +2199,20 @@ namespace Be.Windows.Forms
{
if (!CanPaste()) return;
if (_selectionLength > 0)
_byteProvider.DeleteBytes(_bytePos, _selectionLength);
byte[] buffer = null;
IDataObject da = Clipboard.GetDataObject();
if (da.GetDataPresent("BinaryData"))
{
if(da.GetDataPresent("BinaryData")) {
System.IO.MemoryStream ms = (System.IO.MemoryStream)da.GetData("BinaryData");
buffer = new byte[ms.Length];
ms.Read(buffer, 0, buffer.Length);
}
else if (da.GetDataPresent(typeof(string)))
{
} else if(da.GetDataPresent(typeof(string))) {
string sBuffer = (string)da.GetData(typeof(string));
buffer = System.Text.Encoding.ASCII.GetBytes(sBuffer);
}
else
{
} else {
return;
}
_byteProvider.InsertBytes(_bytePos, buffer);
_byteProvider.WriteBytes(_bytePos, buffer);
SetPosition(_bytePos + buffer.Length, 0);
ReleaseSelection();
@ -2237,12 +2228,6 @@ namespace Be.Windows.Forms
{
if (ReadOnly || !this.Enabled) return false;
if (_byteProvider == null || !_byteProvider.SupportsInsertBytes())
return false;
if (!_byteProvider.SupportsDeleteBytes() && _selectionLength > 0)
return false;
IDataObject da = Clipboard.GetDataObject();
if (da.GetDataPresent("BinaryData"))
return true;
@ -3749,6 +3734,10 @@ namespace Be.Windows.Forms
void SetPosition(long bytePos, int byteCharacterPos)
{
if(bytePos > this._endByte) {
bytePos = this._endByte;
}
if (_byteCharacterPos != byteCharacterPos)
{
_byteCharacterPos = byteCharacterPos;

View file

@ -19,6 +19,9 @@ namespace Be.Windows.Forms
/// <param name="index">the index of the byte to write</param>
/// <param name="value">the byte to write</param>
void WriteByte(long index, byte value);
void WriteBytes(long index, byte[] values);
/// <summary>
/// Inserts bytes into the provider
/// </summary>

View file

@ -122,8 +122,6 @@
this.ctrlHexViewer.Size = new System.Drawing.Size(606, 343);
this.ctrlHexViewer.TabIndex = 0;
this.ctrlHexViewer.RequiredWidthChanged += new System.EventHandler(this.ctrlHexViewer_RequiredWidthChanged);
this.ctrlHexViewer.InitializeContextMenu += new System.EventHandler(this.ctrlHexViewer_InitializeContextMenu);
this.ctrlHexViewer.ByteChanged += new Be.Windows.Forms.DynamicByteProvider.ByteChangedHandler(this.ctrlHexViewer_ByteChanged);
this.ctrlHexViewer.ByteMouseHover += new Mesen.GUI.Debugger.Controls.ctrlHexViewer.ByteMouseHoverHandler(this.ctrlHexViewer_ByteMouseHover);
//
// flowLayoutPanel1

View file

@ -256,7 +256,7 @@ namespace Mesen.GUI.Debugger
this.ctrlMemoryAccessCounters.RefreshData();
} else if(this.tabMain.SelectedTab == this.tpgMemoryViewer) {
this.UpdateByteColorProvider();
this.ctrlHexViewer.SetData(InteropEmu.DebugGetMemoryState(this._memoryType));
this.ctrlHexViewer.RefreshData(_memoryType);
} else if(this.tabMain.SelectedTab == this.tpgProfiler) {
this.ctrlProfiler.RefreshData();
}
@ -358,11 +358,6 @@ namespace Mesen.GUI.Debugger
}
}
private void ctrlHexViewer_ByteChanged(int byteIndex, byte newValue, byte oldValue)
{
InteropEmu.DebugSetMemoryValue(_memoryType, (UInt32)byteIndex, newValue);
}
private void mnuImport_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
@ -467,202 +462,6 @@ namespace Mesen.GUI.Debugger
}
}
private AddressType? GetAddressType()
{
switch(_memoryType) {
case DebugMemoryType.InternalRam: return AddressType.InternalRam;
case DebugMemoryType.WorkRam: return AddressType.WorkRam;
case DebugMemoryType.SaveRam: return AddressType.SaveRam;
case DebugMemoryType.PrgRom: return AddressType.PrgRom;
}
return null;
}
private void ctrlHexViewer_InitializeContextMenu(object sender, EventArgs evt)
{
HexBox hexBox = (HexBox)sender;
var mnuEditLabel = new ToolStripMenuItem();
mnuEditLabel.Click += (s, e) => {
UInt32 address = (UInt32)hexBox.SelectionStart;
if(this._memoryType == DebugMemoryType.CpuMemory) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType(address, ref info);
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
} else {
ctrlLabelList.EditLabel(address, GetAddressType().Value);
}
};
var mnuEditBreakpoint = new ToolStripMenuItem();
mnuEditBreakpoint.Click += (s, e) => {
UInt32 startAddress = (UInt32)hexBox.SelectionStart;
UInt32 endAddress = (UInt32)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
BreakpointAddressType addressType = startAddress == endAddress ? BreakpointAddressType.SingleAddress : BreakpointAddressType.AddressRange;
Breakpoint bp = BreakpointManager.GetMatchingBreakpoint(startAddress, endAddress, this._memoryType);
if(bp == null) {
bp = new Breakpoint() { Address = startAddress, MemoryType = this._memoryType, StartAddress = startAddress, EndAddress = endAddress, AddressType = addressType, BreakOnWrite = true, BreakOnRead = true };
if(bp.IsCpuBreakpoint) {
bp.BreakOnExec = true;
}
}
BreakpointManager.EditBreakpoint(bp);
};
var mnuAddWatch = new ToolStripMenuItem();
mnuAddWatch.Click += (s, e) => {
UInt32 startAddress = (UInt32)hexBox.SelectionStart;
UInt32 endAddress = (UInt32)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
string[] toAdd = Enumerable.Range((int)startAddress, (int)(endAddress - startAddress + 1)).Select((num) => $"[${num.ToString("X4")}]").ToArray();
WatchManager.AddWatch(toAdd);
};
var mnuMarkSelectionAs = new ToolStripMenuItem();
var mnuMarkAsCode = new ToolStripMenuItem();
mnuMarkAsCode.Text = "Verified Code";
mnuMarkAsCode.Click += (s, e) => {
int startAddress = (int)hexBox.SelectionStart;
int endAddress = (int)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
this.MarkSelectionAs(startAddress, endAddress, CdlPrgFlags.Code);
};
var mnuMarkAsData = new ToolStripMenuItem();
mnuMarkAsData.Text = "Verified Data";
mnuMarkAsData.Click += (s, e) => {
int startAddress = (int)hexBox.SelectionStart;
int endAddress = (int)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
this.MarkSelectionAs(startAddress, endAddress, CdlPrgFlags.Data);
};
var mnuMarkAsUnidentifiedData = new ToolStripMenuItem();
mnuMarkAsUnidentifiedData.Text = "Unidentified Code/Data";
mnuMarkAsUnidentifiedData.Click += (s, e) => {
int startAddress = (int)hexBox.SelectionStart;
int endAddress = (int)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
this.MarkSelectionAs(startAddress, endAddress, CdlPrgFlags.None);
};
mnuMarkSelectionAs.DropDownItems.Add(mnuMarkAsCode);
mnuMarkSelectionAs.DropDownItems.Add(mnuMarkAsData);
mnuMarkSelectionAs.DropDownItems.Add(mnuMarkAsUnidentifiedData);
var mnuFreeze = new ToolStripMenuItem();
mnuFreeze.Click += (s, e) => {
UInt32 startAddress = (UInt32)hexBox.SelectionStart;
UInt32 endAddress = (UInt32)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
for(UInt32 i = startAddress; i <= endAddress; i++) {
InteropEmu.DebugSetFreezeState((UInt16)i, true);
}
};
var mnuUnfreeze = new ToolStripMenuItem();
mnuUnfreeze.Click += (s, e) => {
UInt32 startAddress = (UInt32)hexBox.SelectionStart;
UInt32 endAddress = (UInt32)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
for(UInt32 i = startAddress; i <= endAddress; i++) {
InteropEmu.DebugSetFreezeState((UInt16)i, false);
}
};
hexBox.ContextMenuStrip.Opening += (s, e) => {
UInt32 startAddress = (UInt32)hexBox.SelectionStart;
UInt32 endAddress = (UInt32)(hexBox.SelectionStart + (hexBox.SelectionLength == 0 ? 0 : (hexBox.SelectionLength - 1)));
string address = "$" + startAddress.ToString("X4");
string addressRange;
if(startAddress != endAddress) {
addressRange = "$" + startAddress.ToString("X4") + "-$" + endAddress.ToString("X4");
} else {
addressRange = address;
}
mnuEditLabel.Text = $"Edit Label ({address})";
mnuEditBreakpoint.Text = $"Edit Breakpoint ({addressRange})";
mnuAddWatch.Text = $"Add to Watch ({addressRange})";
if(this._memoryType == DebugMemoryType.CpuMemory) {
bool[] freezeState = InteropEmu.DebugGetFreezeState((UInt16)startAddress, (UInt16)(endAddress - startAddress + 1));
mnuFreeze.Enabled = !freezeState.All((frozen) => frozen);
mnuUnfreeze.Enabled = freezeState.Any((frozen) => frozen);
mnuFreeze.Text = $"Freeze ({addressRange})";
mnuUnfreeze.Text = $"Unfreeze ({addressRange})";
} else {
mnuFreeze.Text = $"Freeze";
mnuUnfreeze.Text = $"Unfreeze";
mnuFreeze.Enabled = false;
mnuUnfreeze.Enabled = false;
}
if(this._memoryType == DebugMemoryType.CpuMemory) {
int absStart = InteropEmu.DebugGetAbsoluteAddress(startAddress);
int absEnd = InteropEmu.DebugGetAbsoluteAddress(endAddress);
if(absStart >= 0 && absEnd >= 0 && absStart <= absEnd) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
mnuMarkSelectionAs.Enabled = true;
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
mnuMarkSelectionAs.Enabled = false;
}
} else if(this._memoryType == DebugMemoryType.PrgRom) {
mnuMarkSelectionAs.Text = "Mark selection as... (" + addressRange + ")";
mnuMarkSelectionAs.Enabled = true;
} else {
mnuMarkSelectionAs.Text = "Mark selection as...";
mnuMarkSelectionAs.Enabled = false;
}
bool disableEditLabel = false;
if(this._memoryType == DebugMemoryType.CpuMemory) {
AddressTypeInfo info = new AddressTypeInfo();
InteropEmu.DebugGetAbsoluteAddressAndType(startAddress, ref info);
disableEditLabel = info.Address == -1;
}
mnuEditLabel.Enabled = !disableEditLabel && (this._memoryType == DebugMemoryType.CpuMemory || this.GetAddressType().HasValue);
mnuEditBreakpoint.Enabled = DebugWindowManager.GetDebugger() != null && (
this._memoryType == DebugMemoryType.CpuMemory ||
this._memoryType == DebugMemoryType.PpuMemory ||
this._memoryType == DebugMemoryType.PrgRom ||
this._memoryType == DebugMemoryType.WorkRam ||
this._memoryType == DebugMemoryType.SaveRam ||
this._memoryType == DebugMemoryType.ChrRam ||
this._memoryType == DebugMemoryType.ChrRom ||
this._memoryType == DebugMemoryType.PaletteMemory
);
mnuAddWatch.Enabled = this._memoryType == DebugMemoryType.CpuMemory;
};
hexBox.ContextMenuStrip.Items.Insert(0, new ToolStripSeparator());
hexBox.ContextMenuStrip.Items.Insert(0, mnuFreeze);
hexBox.ContextMenuStrip.Items.Insert(0, mnuUnfreeze);
hexBox.ContextMenuStrip.Items.Insert(0, new ToolStripSeparator());
hexBox.ContextMenuStrip.Items.Insert(0, mnuEditLabel);
hexBox.ContextMenuStrip.Items.Insert(0, mnuEditBreakpoint);
hexBox.ContextMenuStrip.Items.Insert(0, mnuAddWatch);
hexBox.ContextMenuStrip.Items.Insert(0, new ToolStripSeparator());
hexBox.ContextMenuStrip.Items.Insert(0, mnuMarkSelectionAs);
}
private void MarkSelectionAs(int start, int end, CdlPrgFlags type)
{
if(_memoryType == DebugMemoryType.CpuMemory) {
start = InteropEmu.DebugGetAbsoluteAddress((UInt32)start);
end = InteropEmu.DebugGetAbsoluteAddress((UInt32)end);
}
if(start >= 0 && end >= 0 && start <= end) {
InteropEmu.DebugMarkPrgBytesAs((UInt32)start, (UInt32)end, type);
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false, false);
}
}
}
private void mnuColorProviderOptions_Click(object sender, EventArgs e)
{
this.UpdateConfig();

View file

@ -714,8 +714,6 @@
<Compile Include="Debugger\HexBox\DataBlock.cs" />
<Compile Include="Debugger\HexBox\DataMap.cs" />
<Compile Include="Debugger\HexBox\DynamicByteProvider.cs" />
<Compile Include="Debugger\HexBox\DynamicFileByteProvider.cs" />
<Compile Include="Debugger\HexBox\FileByteProvider.cs" />
<Compile Include="Debugger\HexBox\FileDataBlock.cs" />
<Compile Include="Debugger\HexBox\FindOptions.cs" />
<Compile Include="Debugger\HexBox\HexBox.cs">
@ -1109,6 +1107,9 @@
<Compile Include="ResourceManager.cs" />
<Compile Include="RuntimeChecker.cs" />
<Compile Include="SingleInstance.cs" />
<None Include="Resources\SelectAll.png" />
<None Include="Resources\Paste.png" />
<None Include="Resources\EditLabel.png" />
<None Include="Resources\UnidentifiedData.png" />
<None Include="Resources\VerifiedData.png" />
<None Include="Resources\NesEventViewer.png" />

View file

@ -277,6 +277,9 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void DebugRevertPrgChrChanges();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugHasPrgChrChanges();
[DllImport(DLLPath)] public static extern void DebugPerformUndo();
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugHasUndoHistory();
[DllImport(DLLPath, EntryPoint = "DebugGetNesHeader")] public static extern void DebugGetNesHeaderWrapper(IntPtr headerBuffer);
public static byte[] DebugGetNesHeader()
{

View file

@ -310,6 +310,16 @@ namespace Mesen.GUI.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap EditLabel {
get {
object obj = ResourceManager.GetObject("EditLabel", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -590,6 +600,16 @@ namespace Mesen.GUI.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Paste {
get {
object obj = ResourceManager.GetObject("Paste", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -760,6 +780,16 @@ namespace Mesen.GUI.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SelectAll {
get {
object obj = ResourceManager.GetObject("SelectAll", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View file

@ -388,4 +388,13 @@
<data name="VerifiedData" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\VerifiedData.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="EditLabel" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\EditLabel.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Paste" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Paste.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="SelectAll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\SelectAll.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

BIN
GUI.NET/Resources/Paste.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

View file

@ -113,6 +113,9 @@ extern "C"
DllExport bool __stdcall DebugHasPrgChrChanges() { return GetDebugger()->HasPrgChrChanges(); }
DllExport void __stdcall DebugRevertPrgChrChanges() { GetDebugger()->RevertPrgChrChanges(); }
DllExport bool __stdcall DebugHasUndoHistory() { return GetDebugger()->GetMemoryDumper()->HasUndoHistory(); }
DllExport void __stdcall DebugPerformUndo() { GetDebugger()->GetMemoryDumper()->PerformUndo(); }
DllExport int32_t __stdcall DebugFindSubEntryPoint(uint16_t relativeAddress) { return GetDebugger()->FindSubEntryPoint(relativeAddress); }
DllExport void __stdcall DebugSetInputOverride(uint32_t port, uint32_t state) { GetDebugger()->SetInputOverride(port, state); }