diff --git a/Core/BaseMapper.cpp b/Core/BaseMapper.cpp index b1a342af..7c6f7bc3 100644 --- a/Core/BaseMapper.cpp +++ b/Core/BaseMapper.cpp @@ -794,9 +794,10 @@ uint8_t* BaseMapper::GetWorkRam() uint32_t BaseMapper::CopyMemory(DebugMemoryType type, uint8_t* buffer) { + uint32_t chrRomSize = _onlyChrRam ? 0 : _chrRomSize; switch(type) { case DebugMemoryType::ChrRam: memcpy(buffer, _chrRam, _chrRamSize); return _chrRamSize; - case DebugMemoryType::ChrRom: memcpy(buffer, _chrRom, _chrRomSize); return _chrRomSize; + case DebugMemoryType::ChrRom: memcpy(buffer, _chrRom, chrRomSize); return chrRomSize; case DebugMemoryType::PrgRom: memcpy(buffer, _prgRom, _prgSize); return _prgSize; case DebugMemoryType::SaveRam: memcpy(buffer, _saveRam, _saveRamSize); return _saveRamSize; case DebugMemoryType::WorkRam: memcpy(buffer, _workRam, _workRamSize); return _workRamSize; @@ -818,12 +819,23 @@ uint32_t BaseMapper::GetMemorySize(DebugMemoryType type) { switch(type) { default: return 0; - case DebugMemoryType::ChrRom: return _chrRomSize; + case DebugMemoryType::ChrRom: return _onlyChrRam ? 0 : _chrRomSize; case DebugMemoryType::ChrRam: return _chrRamSize; case DebugMemoryType::SaveRam: return _saveRamSize; case DebugMemoryType::PrgRom: return _prgSize; case DebugMemoryType::WorkRam: return _workRamSize; - } + } +} + +void BaseMapper::SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value) +{ + switch(memoryType) { + case DebugMemoryType::ChrRom: _chrRom[address] = value; break; + case DebugMemoryType::ChrRam: _chrRam[address] = value; break; + case DebugMemoryType::SaveRam: _saveRam[address] = value; break; + case DebugMemoryType::PrgRom: _prgRom[address] = value; break; + case DebugMemoryType::WorkRam: _workRam[address] = value; break; + } } int32_t BaseMapper::ToAbsoluteAddress(uint16_t addr) diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index fdbf59f5..bf43132a 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -226,6 +226,7 @@ public: uint8_t* GetPrgRom(); uint8_t* GetWorkRam(); + void SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value); uint32_t GetMemorySize(DebugMemoryType type); uint32_t CopyMemory(DebugMemoryType type, uint8_t* buffer); diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 8b62af03..fdeca38e 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -30,7 +30,7 @@ Debugger::Debugger(shared_ptr console, shared_ptr cpu, shared_ptr< _labelManager.reset(new LabelManager(_mapper)); _disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), mapper->GetPrgRom(), mapper->GetMemorySize(DebugMemoryType::PrgRom), mapper->GetWorkRam(), mapper->GetMemorySize(DebugMemoryType::WorkRam), this)); _codeDataLogger.reset(new CodeDataLogger(mapper->GetMemorySize(DebugMemoryType::PrgRom), mapper->GetMemorySize(DebugMemoryType::ChrRom))); - _memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, _mapper, _codeDataLogger)); + _memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, _mapper, _codeDataLogger, this)); _memoryAccessCounter.reset(new MemoryAccessCounter(this)); _profiler.reset(new Profiler(this)); diff --git a/Core/MemoryDumper.cpp b/Core/MemoryDumper.cpp index ee3b538e..b81333fc 100644 --- a/Core/MemoryDumper.cpp +++ b/Core/MemoryDumper.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Debugger.h" #include "MemoryManager.h" #include "PPU.h" #include "CodeDataLogger.h" @@ -6,8 +7,9 @@ #include "MemoryDumper.h" #include "VideoDecoder.h" -MemoryDumper::MemoryDumper(shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper, shared_ptr codeDataLogger) +MemoryDumper::MemoryDumper(shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper, shared_ptr codeDataLogger, Debugger* debugger) { + _debugger = debugger; _ppu = ppu; _memoryManager = memoryManager; _mapper = mapper; @@ -40,6 +42,40 @@ void MemoryDumper::SetMemoryState(DebugMemoryType type, uint8_t *buffer) } } +void MemoryDumper::SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value) +{ + switch(memoryType) { + case DebugMemoryType::CpuMemory: + AddressTypeInfo info; + _debugger->GetAbsoluteAddressAndType(address, &info); + if(info.Address >= 0) { + switch(info.Type) { + case AddressType::InternalRam: SetMemoryValue(DebugMemoryType::InternalRam, info.Address, value); break; + case AddressType::PrgRom: SetMemoryValue(DebugMemoryType::PrgRom, info.Address, value); break; + case AddressType::WorkRam: SetMemoryValue(DebugMemoryType::WorkRam, info.Address, value); break; + case AddressType::SaveRam: SetMemoryValue(DebugMemoryType::SaveRam, info.Address, value); break; + } + } + break; + + case DebugMemoryType::InternalRam: _memoryManager->DebugWrite(address, value); break; + + case DebugMemoryType::PaletteMemory: _ppu->WritePaletteRAM(address, value); break; + case DebugMemoryType::SpriteMemory: _ppu->GetSpriteRam()[address] = value; break; + case DebugMemoryType::SecondarySpriteMemory: _ppu->GetSecondarySpriteRam()[address] = value; break; + + case DebugMemoryType::PpuMemory: _mapper->WriteVRAM(address, value); break; + + case DebugMemoryType::ChrRam: + case DebugMemoryType::WorkRam: + case DebugMemoryType::SaveRam: + case DebugMemoryType::PrgRom: + case DebugMemoryType::ChrRom: + _mapper->SetMemoryValue(memoryType, address, value); + break; + } +} + uint32_t MemoryDumper::GetMemoryState(DebugMemoryType type, uint8_t *buffer) { switch(type) { diff --git a/Core/MemoryDumper.h b/Core/MemoryDumper.h index 78d51753..f0a92ce4 100644 --- a/Core/MemoryDumper.h +++ b/Core/MemoryDumper.h @@ -6,17 +6,19 @@ class PPU; class MemoryManager; class BaseMapper; class CodeDataLogger; +class Debugger; class MemoryDumper { private: + Debugger* _debugger; shared_ptr _ppu; shared_ptr _memoryManager; shared_ptr _mapper; shared_ptr _codeDataLogger; public: - MemoryDumper(shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper, shared_ptr codeDataLogger); + MemoryDumper(shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper, shared_ptr codeDataLogger, Debugger *debugger); uint32_t GetMemoryState(DebugMemoryType type, uint8_t *buffer); void GetNametable(int nametableIndex, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData); @@ -24,5 +26,6 @@ public: void GetSprites(uint32_t* frameBuffer); void GetPalette(uint32_t* frameBuffer); + void SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value); void SetMemoryState(DebugMemoryType type, uint8_t *buffer); }; \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlHexViewer.Designer.cs b/GUI.NET/Debugger/Controls/ctrlHexViewer.Designer.cs index 09a5af7b..8d450805 100644 --- a/GUI.NET/Debugger/Controls/ctrlHexViewer.Designer.cs +++ b/GUI.NET/Debugger/Controls/ctrlHexViewer.Designer.cs @@ -42,8 +42,8 @@ this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); this.chkTextSearch = new System.Windows.Forms.CheckBox(); this.chkMatchCase = new System.Windows.Forms.CheckBox(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.ctrlHexBox = new Be.Windows.Forms.HexBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.tableLayoutPanel1.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); this.panelSearch.SuspendLayout(); @@ -241,7 +241,7 @@ this.chkMatchCase.Text = "Match Case"; this.chkMatchCase.UseVisualStyleBackColor = true; // - // ctrlDataViewer + // ctrlHexBox // this.ctrlHexBox.ColumnInfoVisible = true; this.ctrlHexBox.Dock = System.Windows.Forms.DockStyle.Fill; @@ -250,7 +250,6 @@ this.ctrlHexBox.LineInfoVisible = true; this.ctrlHexBox.Location = new System.Drawing.Point(3, 30); this.ctrlHexBox.Name = "ctrlHexBox"; - this.ctrlHexBox.ReadOnly = true; this.ctrlHexBox.SelectionBackColor = System.Drawing.Color.RoyalBlue; this.ctrlHexBox.ShadowSelectionColor = System.Drawing.Color.Orange; this.ctrlHexBox.Size = new System.Drawing.Size(537, 248); diff --git a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs index b07e970a..03724bf5 100644 --- a/GUI.NET/Debugger/Controls/ctrlHexViewer.cs +++ b/GUI.NET/Debugger/Controls/ctrlHexViewer.cs @@ -10,6 +10,7 @@ using System.Windows.Forms; using Mesen.GUI.Config; using Be.Windows.Forms; using Mesen.GUI.Controls; +using static Be.Windows.Forms.DynamicByteProvider; namespace Mesen.GUI.Debugger.Controls { @@ -57,6 +58,9 @@ namespace Mesen.GUI.Debugger.Controls if(changed) { _byteProvider = new StaticByteProvider(data); + _byteProvider.ByteChanged += (int byteIndex, byte newValue, byte oldValue) => { + ByteChanged?.Invoke(byteIndex, newValue, oldValue); + }; this.ctrlHexBox.ByteProvider = _byteProvider; if(clearHistory) { this.ctrlHexBox.ClearHistory(); @@ -270,16 +274,18 @@ namespace Mesen.GUI.Debugger.Controls } } - public event EventHandler RequiredWidthChanged + private void chkTextSearch_CheckedChanged(object sender, EventArgs e) + { + this.UpdateSearchOptions(); + } + + public event EventHandler RequiredWidthChanged { add { this.ctrlHexBox.RequiredWidthChanged += value; } remove { this.ctrlHexBox.RequiredWidthChanged -= value; } } - private void chkTextSearch_CheckedChanged(object sender, EventArgs e) - { - this.UpdateSearchOptions(); - } + public event ByteChangedHandler ByteChanged; [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public IByteCharConverter ByteCharConverter @@ -294,5 +300,12 @@ namespace Mesen.GUI.Debugger.Controls get { return this.ctrlHexBox.StringViewVisible; } set { this.ctrlHexBox.StringViewVisible = value; } } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool ReadOnly + { + get { return this.ctrlHexBox.ReadOnly; } + set { this.ctrlHexBox.ReadOnly = value; } + } } } diff --git a/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs b/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs index e14f2445..79832691 100644 --- a/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs +++ b/GUI.NET/Debugger/HexBox/DynamicByteProvider.cs @@ -89,7 +89,8 @@ namespace Be.Windows.Forms /// public event EventHandler LengthChanged; - public event EventHandler ByteChanged; + public delegate void ByteChangedHandler(int byteIndex, byte newValue, byte oldValue); + public event ByteChangedHandler ByteChanged; /// @@ -108,8 +109,8 @@ namespace Be.Windows.Forms public void WriteByte(long index, byte value) { if(_bytes[(int)index] != value) { + ByteChanged?.Invoke((int)index, value, _bytes[(int)index]); _bytes[(int)index] = value; - ByteChanged?.Invoke((int)index, EventArgs.Empty); OnChanged(EventArgs.Empty); } } diff --git a/GUI.NET/Debugger/frmMemoryViewer.Designer.cs b/GUI.NET/Debugger/frmMemoryViewer.Designer.cs index 993c1cc5..6c85e66c 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.Designer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.Designer.cs @@ -41,8 +41,8 @@ this.mnuImport = new System.Windows.Forms.ToolStripMenuItem(); this.mnuExport = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); - this.mnuResetTblMappings = new System.Windows.Forms.ToolStripMenuItem(); this.mnuLoadTblFile = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuResetTblMappings = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); this.mnuClose = new System.Windows.Forms.ToolStripMenuItem(); this.mnuView = new System.Windows.Forms.ToolStripMenuItem(); @@ -86,6 +86,7 @@ this.ctrlHexViewer.Size = new System.Drawing.Size(665, 346); this.ctrlHexViewer.TabIndex = 0; this.ctrlHexViewer.RequiredWidthChanged += new System.EventHandler(this.ctrlHexViewer_RequiredWidthChanged); + this.ctrlHexViewer.ByteChanged += new Be.Windows.Forms.DynamicByteProvider.ByteChangedHandler(this.ctrlHexViewer_ByteChanged); // // flowLayoutPanel1 // @@ -175,13 +176,6 @@ this.toolStripMenuItem3.Name = "toolStripMenuItem3"; this.toolStripMenuItem3.Size = new System.Drawing.Size(178, 6); // - // mnuResetTblMappings - // - this.mnuResetTblMappings.Name = "mnuResetTblMappings"; - this.mnuResetTblMappings.Size = new System.Drawing.Size(181, 22); - this.mnuResetTblMappings.Text = "Reset TBL mappings"; - this.mnuResetTblMappings.Click += new System.EventHandler(this.mnuResetTblMappings_Click); - // // mnuLoadTblFile // this.mnuLoadTblFile.Name = "mnuLoadTblFile"; @@ -189,6 +183,13 @@ this.mnuLoadTblFile.Text = "Load TBL file"; this.mnuLoadTblFile.Click += new System.EventHandler(this.mnuLoadTblFile_Click); // + // mnuResetTblMappings + // + this.mnuResetTblMappings.Name = "mnuResetTblMappings"; + this.mnuResetTblMappings.Size = new System.Drawing.Size(181, 22); + this.mnuResetTblMappings.Text = "Reset TBL mappings"; + this.mnuResetTblMappings.Click += new System.EventHandler(this.mnuResetTblMappings_Click); + // // toolStripMenuItem4 // this.toolStripMenuItem4.Name = "toolStripMenuItem4"; diff --git a/GUI.NET/Debugger/frmMemoryViewer.cs b/GUI.NET/Debugger/frmMemoryViewer.cs index 63f87f16..0408160a 100644 --- a/GUI.NET/Debugger/frmMemoryViewer.cs +++ b/GUI.NET/Debugger/frmMemoryViewer.cs @@ -170,6 +170,11 @@ 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(); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index bf5b0112..361c82eb 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -187,6 +187,7 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern Int32 DebugGetRelativeAddress(UInt32 absoluteAddr, AddressType type); [DllImport(DLLPath)] public static extern Int32 DebugGetAbsoluteAddress(UInt32 relativeAddr); [DllImport(DLLPath)] public static extern Int32 DebugGetMemorySize(DebugMemoryType type); + [DllImport(DLLPath)] public static extern void DebugSetMemoryValue(DebugMemoryType type, UInt32 address, byte value); [DllImport(DLLPath)] public static extern void DebugGetAbsoluteAddressAndType(UInt32 relativeAddr, ref AddressTypeInfo addressTypeInfo); [DllImport(DLLPath)] public static extern void DebugSetPpuViewerScanlineCycle(Int32 scanline, Int32 cycle); diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp index 0fab8ec9..1a7df73e 100644 --- a/InteropDLL/DebugWrapper.cpp +++ b/InteropDLL/DebugWrapper.cpp @@ -77,6 +77,7 @@ extern "C" DllExport void __stdcall DebugStartTraceLogger(TraceLoggerOptions options) { GetDebugger()->StartTraceLogger(options); } DllExport void __stdcall DebugStopTraceLogger() { GetDebugger()->StopTraceLogger(); } + DllExport void __stdcall DebugSetMemoryValue(DebugMemoryType type, uint32_t address, uint8_t value) { return GetDebugger()->GetMemoryDumper()->SetMemoryValue(type, address, value); } DllExport int32_t __stdcall DebugGetMemorySize(DebugMemoryType type) { return GetDebugger()->GetMemorySize(type); } DllExport void __stdcall DebugGetMemoryAccessCounts(AddressType memoryType, MemoryOperationType operationType, uint32_t* counts, bool forUninitReads) { GetDebugger()->GetMemoryAccessCounter()->GetAccessCounts(memoryType, operationType, counts, forUninitReads); } DllExport void __stdcall DebugResetMemoryAccessCounts() { GetDebugger()->GetMemoryAccessCounter()->ResetCounts(); }