Debugger: Improved memory tools performance
This commit is contained in:
parent
f25a3d1450
commit
41ee29d650
11 changed files with 219 additions and 8 deletions
|
@ -10,6 +10,7 @@ protected:
|
|||
public:
|
||||
virtual uint8_t Read(uint32_t addr) = 0;
|
||||
virtual uint8_t Peek(uint32_t addr) = 0;
|
||||
virtual void PeekBlock(uint8_t *output) = 0;
|
||||
virtual void Write(uint32_t addr, uint8_t value) = 0;
|
||||
|
||||
__forceinline SnesMemoryType GetMemoryType()
|
||||
|
|
|
@ -55,8 +55,8 @@ void MemoryDumper::GetMemoryState(SnesMemoryType type, uint8_t *buffer)
|
|||
{
|
||||
switch(type) {
|
||||
case SnesMemoryType::CpuMemory:
|
||||
for(int i = 0; i <= 0xFFFFFF; i++) {
|
||||
buffer[i] = _memoryManager->Peek(i);
|
||||
for(int i = 0; i <= 0xFFFFFF; i+=0x1000) {
|
||||
_memoryManager->PeekBlock(i, buffer+i);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -224,6 +224,15 @@ uint16_t MemoryManager::PeekWord(uint32_t addr)
|
|||
return (msb << 8) | lsb;
|
||||
}
|
||||
|
||||
void MemoryManager::PeekBlock(uint32_t addr, uint8_t *dest)
|
||||
{
|
||||
if(_handlers[addr >> 12]) {
|
||||
_handlers[addr >> 12]->PeekBlock(dest);
|
||||
} else {
|
||||
memset(dest, 0, 0x1000);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
IncrementMasterClock(addr);
|
||||
|
|
|
@ -53,8 +53,10 @@ public:
|
|||
|
||||
uint8_t Read(uint32_t addr, MemoryOperationType type);
|
||||
uint8_t ReadDma(uint32_t addr, bool forBusA);
|
||||
|
||||
uint8_t Peek(uint32_t addr);
|
||||
uint16_t PeekWord(uint32_t addr);
|
||||
void PeekBlock(uint32_t addr, uint8_t * dest);
|
||||
|
||||
void Write(uint32_t addr, uint8_t value, MemoryOperationType type);
|
||||
void WriteDma(uint32_t addr, uint8_t value, bool forBusA);
|
||||
|
|
|
@ -34,6 +34,17 @@ public:
|
|||
return _ram[addr & _mask];
|
||||
}
|
||||
|
||||
void PeekBlock(uint8_t *output) override
|
||||
{
|
||||
if(_mask != 0xFFF) {
|
||||
for(int i = 0; i < 0x1000; i++) {
|
||||
output[i] = _ram[i & _mask];
|
||||
}
|
||||
} else {
|
||||
memcpy(output, _ram, 0x1000);
|
||||
}
|
||||
}
|
||||
|
||||
void Write(uint32_t addr, uint8_t value) override
|
||||
{
|
||||
_ram[addr & _mask] = value;
|
||||
|
|
|
@ -39,6 +39,12 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
void PeekBlock(uint8_t *output) override
|
||||
{
|
||||
//Avoid side effects for now
|
||||
memset(output, 0, 0x1000);
|
||||
}
|
||||
|
||||
void Write(uint32_t addr, uint8_t value) override
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
|
|
|
@ -36,6 +36,12 @@ uint8_t RegisterHandlerB::Peek(uint32_t addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void RegisterHandlerB::PeekBlock(uint8_t *output)
|
||||
{
|
||||
//Avoid side effects for now
|
||||
memset(output, 0, 0x1000);
|
||||
}
|
||||
|
||||
void RegisterHandlerB::Write(uint32_t addr, uint8_t value)
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
|
||||
uint8_t Read(uint32_t addr) override;
|
||||
uint8_t Peek(uint32_t addr) override;
|
||||
void PeekBlock(uint8_t *output) override;
|
||||
void Write(uint32_t addr, uint8_t value) override;
|
||||
|
||||
AddressInfo GetAbsoluteAddress(uint32_t address) override;
|
||||
|
|
|
@ -60,9 +60,9 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
if(data != null) {
|
||||
bool changed = true;
|
||||
if(this._byteProvider != null && data.Length == this._byteProvider.Bytes.Count) {
|
||||
if(this._byteProvider != null && data.Length == this._byteProvider.Length) {
|
||||
changed = false;
|
||||
for(int i = 0; i < this._byteProvider.Bytes.Count; i++) {
|
||||
for(int i = 0; i < this._byteProvider.Length; i++) {
|
||||
if(this._byteProvider.Bytes[i] != data[i]) {
|
||||
changed = true;
|
||||
break;
|
||||
|
|
|
@ -6,20 +6,193 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Be.Windows.Forms
|
||||
{
|
||||
public class StaticByteProvider : DynamicByteProvider
|
||||
public class StaticByteProvider : IByteProvider
|
||||
{
|
||||
public StaticByteProvider(byte[] data) : base(data)
|
||||
/// <summary>
|
||||
/// Contains information about changes.
|
||||
/// </summary>
|
||||
bool _hasChanges;
|
||||
/// <summary>
|
||||
/// Contains a byte collection.
|
||||
/// </summary>
|
||||
byte[] _bytes;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DynamicByteProvider class.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public StaticByteProvider(byte[] data)
|
||||
{
|
||||
_bytes = data;
|
||||
}
|
||||
|
||||
public void SetData(byte[] data)
|
||||
{
|
||||
_bytes = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the Changed event.
|
||||
/// </summary>
|
||||
void OnChanged(EventArgs e)
|
||||
{
|
||||
_hasChanges = true;
|
||||
|
||||
if(Changed != null)
|
||||
Changed(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the LengthChanged event.
|
||||
/// </summary>
|
||||
void OnLengthChanged(EventArgs e)
|
||||
{
|
||||
if(LengthChanged != null)
|
||||
LengthChanged(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte collection.
|
||||
/// </summary>
|
||||
public byte[] Bytes
|
||||
{
|
||||
get { return _bytes; }
|
||||
}
|
||||
|
||||
#region IByteProvider Members
|
||||
/// <summary>
|
||||
/// True, when changes are done.
|
||||
/// </summary>
|
||||
public bool HasChanges()
|
||||
{
|
||||
return _hasChanges;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies changes.
|
||||
/// </summary>
|
||||
public void ApplyChanges()
|
||||
{
|
||||
_hasChanges = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs, when the write buffer contains new changes.
|
||||
/// </summary>
|
||||
public event EventHandler Changed;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs, when InsertBytes or DeleteBytes method is called.
|
||||
/// </summary>
|
||||
public event EventHandler LengthChanged;
|
||||
|
||||
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.
|
||||
/// </summary>
|
||||
/// <param name="index">the index of the byte to read</param>
|
||||
/// <returns>the byte</returns>
|
||||
public byte ReadByte(long index)
|
||||
{
|
||||
if(_partialPos == index) {
|
||||
return _partialValue;
|
||||
} else {
|
||||
return _bytes[(int)index];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a byte into the byte collection.
|
||||
/// </summary>
|
||||
/// <param name="index">the index of the byte to write.</param>
|
||||
/// <param name="value">the byte</param>
|
||||
public void WriteByte(long index, byte value)
|
||||
{
|
||||
if(index == _partialPos) {
|
||||
_partialPos = -1;
|
||||
}
|
||||
|
||||
if(_bytes[(int)index] != value) {
|
||||
ByteChanged?.Invoke((int)index, value, _bytes[(int)index]);
|
||||
_bytes[(int)index] = value;
|
||||
OnChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(long index, byte[] values)
|
||||
{
|
||||
_partialPos = -1;
|
||||
BytesChanged?.Invoke((int)index, values);
|
||||
for(int i = 0; i < values.Length && index + i < _bytes.Length; i++) {
|
||||
_bytes[(int)index + i] = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
long _partialPos = -1;
|
||||
byte _partialValue = 0;
|
||||
public void PartialWriteByte(long index, byte value)
|
||||
{
|
||||
//Wait for a full byte to be written
|
||||
_partialPos = index;
|
||||
_partialValue = value;
|
||||
}
|
||||
|
||||
public void CommitWriteByte()
|
||||
{
|
||||
if(_partialPos >= 0) {
|
||||
WriteByte(_partialPos, _partialValue);
|
||||
_partialPos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteBytes(long index, long length)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool SupportsInsertBytes()
|
||||
public void InsertBytes(long index, byte[] bs)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the bytes in the byte collection.
|
||||
/// </summary>
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return _bytes.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true
|
||||
/// </summary>
|
||||
public virtual bool SupportsWriteByte()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true
|
||||
/// </summary>
|
||||
public virtual bool SupportsInsertBytes()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool SupportsDeleteBytes()
|
||||
/// <summary>
|
||||
/// Returns true
|
||||
/// </summary>
|
||||
public virtual bool SupportsDeleteBytes()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,8 @@ namespace Mesen.GUI.Forms
|
|||
ConfigManager.ApplyChanges();
|
||||
|
||||
DebugApi.ResumeExecution();
|
||||
DebugWindowManager.CloseAll();
|
||||
|
||||
EmuApi.Stop();
|
||||
EmuApi.Release();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue