Debugger: Added paste/undo support in hex editor
This commit is contained in:
parent
e0611e7a9d
commit
d62d701e64
26 changed files with 617 additions and 1105 deletions
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
};
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
204
GUI.NET/Debugger/Controls/ctrlHexViewer.Designer.cs
generated
204
GUI.NET/Debugger/Controls/ctrlHexViewer.Designer.cs
generated
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
50
GUI.NET/Debugger/Controls/ctrlLabelList.Designer.cs
generated
50
GUI.NET/Debugger/Controls/ctrlLabelList.Designer.cs
generated
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
2
GUI.NET/Debugger/frmMemoryViewer.Designer.cs
generated
2
GUI.NET/Debugger/frmMemoryViewer.Designer.cs
generated
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
30
GUI.NET/Properties/Resources.Designer.cs
generated
30
GUI.NET/Properties/Resources.Designer.cs
generated
|
@ -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>
|
||||
|
|
|
@ -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>
|
BIN
GUI.NET/Resources/EditLabel.png
Normal file
BIN
GUI.NET/Resources/EditLabel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 351 B |
BIN
GUI.NET/Resources/Paste.png
Normal file
BIN
GUI.NET/Resources/Paste.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 561 B |
BIN
GUI.NET/Resources/SelectAll.png
Normal file
BIN
GUI.NET/Resources/SelectAll.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 441 B |
|
@ -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); }
|
||||
|
|
Loading…
Add table
Reference in a new issue