diff --git a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs index 5bc755fa56..771eb088e3 100644 --- a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs +++ b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs @@ -517,7 +517,7 @@ namespace BizHawk.Client.EmuHawk private string GenerateMemoryViewString(bool forWindow) { var rowStr = new StringBuilder(); - + var test = MakeValues(); for (var i = 0; i < _rowsVisible; i++) { _row = i + HexScrollBar.Value; @@ -531,21 +531,23 @@ namespace BizHawk.Client.EmuHawk { if (_addr + j + DataSize <= _domain.Size) { - int tVal = 0; - for (int k = 0; k < DataSize; k++) - { - int tNext = MakeValue(1, _addr + j + k); - if (BigEndian) - { - tVal += (tNext << (k * 8)); - } - else - { - tVal += (tNext << ((DataSize - k - 1) * 8)); - } - } + var addressVal = test[_addr + j]; + rowStr.AppendFormat(_digitFormatString, addressVal); + //int tVal = 0; + //for (int k = 0; k < DataSize; k++) + //{ + // int tNext = MakeValue(1, _addr + j + k); + // if (BigEndian) + // { + // tVal += (tNext << (k * 8)); + // } + // else + // { + // tVal += (tNext << ((DataSize - k - 1) * 8)); + // } + //} - rowStr.AppendFormat(_digitFormatString, tVal); + //rowStr.AppendFormat(_digitFormatString, tVal); } else { @@ -577,6 +579,70 @@ namespace BizHawk.Client.EmuHawk return rowStr.ToString(); } + private Dictionary MakeValues() + { + var addresses = new List(); + + for (var i = 0; i < _rowsVisible; i++) + { + _row = i + HexScrollBar.Value; + _addr = _row << 4; + if (_addr >= _domain.Size) + { + break; + } + + for (var j = 0; j < 16; j += DataSize) + { + if (_addr + j + DataSize <= _domain.Size) + { + var address = _addr + j; + addresses.Add(address); + } + } + } + + Dictionary dict = new Dictionary(); + var range = new MutableRange(addresses[0], addresses[0] + addresses.Count); + + switch (DataSize) + { + default: + case 1: + { + var vals = new byte[addresses.Count]; + _domain.BulkPeekByte(range, vals); + for (var i = 0; i < addresses.Count; i++) + { + dict.Add(addresses[i], vals[i]); + } + break; + } + case 2: + { + var vals = new ushort[addresses.Count]; + _domain.BulkPeekUshort(range, BigEndian, vals); + for (var i = 0; i < addresses.Count; i++) + { + dict.Add(addresses[i], vals[i]); + } + break; + } + case 4: + { + var vals = new uint[addresses.Count]; + _domain.BulkPeekUint(range, BigEndian, vals); + for (var i = 0; i < addresses.Count; i++) + { + dict.Add(addresses[i], vals[i]); + } + break; + } + } + + return dict; + } + private byte MakeByte(long address) { return Global.CheatList.IsActive(_domain, address) diff --git a/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs b/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs index cb449a9211..a45eeaa8d8 100644 --- a/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs +++ b/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs @@ -1,4 +1,7 @@ -namespace BizHawk.Emulation.Common +using System; +using BizHawk.Common; + +namespace BizHawk.Emulation.Common { /// /// A memory region and the functionality to read/write from it @@ -100,5 +103,59 @@ break; } } + + public virtual void BulkPeekByte(Range addresses, byte[] values) + { + if (addresses == null || values == null) + { + throw new ArgumentException(); + } + + if (addresses.EndInclusive - addresses.Start != values.Length) + { + throw new InvalidOperationException("Invalid length of values array"); + } + + for (var i = addresses.Start; i < addresses.EndInclusive; i++) + { + values[i] = PeekByte(i); + } + } + + public virtual void BulkPeekUshort(Range addresses, bool bigEndian, ushort[] values) + { + if (addresses == null || values == null) + { + throw new ArgumentException(); + } + + if (addresses.EndInclusive - addresses.Start != values.Length) + { + throw new InvalidOperationException("Invalid length of values array"); + } + + for (var i = addresses.Start; i < addresses.EndInclusive; i++) + { + values[i] = PeekUshort(i, bigEndian); + } + } + + public virtual void BulkPeekUint(Range addresses, bool bigEndian, uint[] values) + { + if (addresses == null || values == null) + { + throw new ArgumentException(); + } + + if (addresses.EndInclusive - addresses.Start != values.Length) + { + throw new InvalidOperationException("Invalid length of values array"); + } + + for (var i = addresses.Start; i < addresses.EndInclusive; i++) + { + values[i] = PeekUint(i, bigEndian); + } + } } } diff --git a/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs b/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs index d7f0f22453..c84ed1f408 100644 --- a/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs +++ b/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs @@ -1,5 +1,6 @@ using BizHawk.Common; using System; +using System.Collections.Generic; namespace BizHawk.Emulation.Common { @@ -7,6 +8,11 @@ namespace BizHawk.Emulation.Common { private Action _poke; + // TODO: use an array of Ranges + private Action, byte[]> _bulkPeekByte { get; set; } + private Action, bool, ushort[]> _bulkPeekUshort { get; set; } + private Action, bool, uint[]> _bulkPeekUint { get; set; } + public Func Peek { get; set; } public Action Poke @@ -29,7 +35,52 @@ namespace BizHawk.Emulation.Common _poke?.Invoke(addr, val); } - public MemoryDomainDelegate(string name, long size, Endian endian, Func peek, Action poke, int wordSize) + public override void BulkPeekByte(Range addresses, byte[] values) + { + if (_bulkPeekByte != null) + { + _bulkPeekByte.Invoke(addresses, values); + } + else + { + base.BulkPeekByte(addresses, values); + } + } + + public override void BulkPeekUshort(Range addresses, bool bigEndian, ushort[] values) + { + if (_bulkPeekUshort != null) + { + _bulkPeekUshort.Invoke(addresses, EndianType == Endian.Big, values); + } + else + { + base.BulkPeekUshort(addresses, EndianType == Endian.Big, values); + } + } + + public override void BulkPeekUint(Range addresses, bool bigEndian, uint[] values) + { + if (_bulkPeekUint != null) + { + _bulkPeekUint.Invoke(addresses, EndianType == Endian.Big, values); + } + else + { + base.BulkPeekUint(addresses, EndianType == Endian.Big, values); + } + } + + public MemoryDomainDelegate( + string name, + long size, + Endian endian, + Func peek, + Action poke, + int wordSize, + Action, byte[]> bulkPeekByte = null, + Action, bool, ushort[]> bulkPeekUshort = null, + Action, bool, uint[]> bulkPeekUint = null) { Name = name; EndianType = endian; @@ -38,6 +89,9 @@ namespace BizHawk.Emulation.Common _poke = poke; Writable = poke != null; WordSize = wordSize; + _bulkPeekByte = bulkPeekByte; + _bulkPeekUshort = bulkPeekUshort; + _bulkPeekUint = bulkPeekUint; } }