2011-03-06 15:03:17 +00:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Drawing ;
2013-11-28 22:06:38 +00:00
using System.Globalization ;
using System.IO ;
2011-03-06 15:03:17 +00:00
using System.Linq ;
using System.Text ;
using System.Windows.Forms ;
2013-11-28 22:06:38 +00:00
using BizHawk.Common ;
2014-07-03 15:35:50 +00:00
using BizHawk.Common.NumberExtensions ;
2014-07-03 16:00:57 +00:00
using BizHawk.Common.StringExtensions ;
2014-07-03 18:29:51 +00:00
using BizHawk.Common.IOExtensions ;
2013-11-04 01:39:19 +00:00
using BizHawk.Emulation.Common ;
2014-09-01 18:43:41 +00:00
using BizHawk.Emulation.Common.IEmulatorExtensions ;
2014-07-03 15:35:50 +00:00
using BizHawk.Client.Common ;
2014-07-27 15:22:30 +00:00
using BizHawk.Client.EmuHawk.WinFormExtensions ;
2014-07-28 01:51:11 +00:00
using BizHawk.Client.EmuHawk.ToolExtensions ;
2013-10-25 00:57:23 +00:00
2013-11-03 03:54:37 +00:00
namespace BizHawk.Client.EmuHawk
2011-03-06 15:03:17 +00:00
{
2015-01-18 16:00:20 +00:00
// int to long TODO: 32 bit domains have more digits than the hex editor can account for and the address covers up the 0 column
2016-01-31 01:24:30 +00:00
public partial class HexEditor : ToolFormBase , IToolFormAutoConfig
2011-06-19 23:39:25 +00:00
{
2016-04-13 23:50:06 +00:00
private class NullMemoryDomain : MemoryDomain
{
public override byte PeekByte ( long addr )
{
return 0 ;
}
public override void PokeByte ( long addr , byte val )
{
}
public NullMemoryDomain ( )
{
EndianType = Endian . Unknown ;
Name = "Null" ;
Size = 1024 ;
Writable = true ;
WordSize = 1 ;
}
}
2014-12-15 03:19:23 +00:00
[RequiredService]
2015-01-14 21:55:48 +00:00
private IMemoryDomains MemoryDomains { get ; set ; }
2014-12-13 21:54:59 +00:00
2014-12-17 03:57:07 +00:00
[RequiredService]
private IEmulator Emulator { get ; set ; }
2019-11-03 16:46:45 +00:00
private readonly int _fontWidth ;
private readonly int _fontHeight ;
2013-11-28 22:06:38 +00:00
2019-11-03 17:48:31 +00:00
private readonly List < char > _nibbles = new List < char > ( ) ;
2019-11-03 17:14:08 +00:00
private long? _highlightedAddress ;
2015-01-18 18:01:27 +00:00
private readonly List < long > _secondaryHighlightedAddresses = new List < long > ( ) ;
2013-11-28 22:06:38 +00:00
2014-03-23 20:27:20 +00:00
private readonly Dictionary < int , char > _textTable = new Dictionary < int , char > ( ) ;
2013-11-28 14:43:27 +00:00
private int _rowsVisible ;
private int _numDigits = 4 ;
private string _numDigitsStr = "{0:X4}" ;
private string _digitFormatString = "{0:X2}" ;
2015-01-18 18:01:27 +00:00
private long _addressOver = - 1 ;
2019-11-03 17:14:08 +00:00
2015-01-18 18:13:38 +00:00
private long _maxRow ;
2013-11-28 22:06:38 +00:00
2016-04-13 23:50:06 +00:00
private MemoryDomain _domain = new NullMemoryDomain ( ) ;
2013-11-28 22:06:38 +00:00
2015-01-18 20:15:03 +00:00
private long _row ;
2015-01-18 18:59:23 +00:00
private long _addr ;
2017-05-10 11:45:23 +00:00
private string _findStr = "" ;
2013-11-28 14:43:27 +00:00
private bool _mouseIsDown ;
private byte [ ] _rom ;
private MemoryDomain _romDomain ;
2013-11-28 20:02:32 +00:00
private HexFind _hexFind = new HexFind ( ) ;
2012-09-02 19:22:51 +00:00
2018-11-18 17:18:42 +00:00
[ConfigPersist]
private string LastDomain { get ; set ; }
2015-01-01 14:54:26 +00:00
[ConfigPersist]
private bool BigEndian { get ; set ; }
[ConfigPersist]
private int DataSize { get ; set ; }
[ConfigPersist]
private RecentFiles RecentTables { get ; set ; }
2012-03-09 16:13:40 +00:00
2011-06-19 23:39:25 +00:00
public HexEditor ( )
{
2015-01-01 14:54:26 +00:00
RecentTables = new RecentFiles ( 8 ) ;
DataSize = 1 ;
2014-09-13 14:50:58 +00:00
var font = new Font ( "Courier New" , 8 ) ;
2015-03-06 02:45:53 +00:00
// Measure the font. There seems to be some extra horizontal padding on the first
// character so we'll see how much the width increases on the second character.
var fontSize1 = TextRenderer . MeasureText ( "0" , font ) ;
var fontSize2 = TextRenderer . MeasureText ( "00" , font ) ;
2019-11-03 16:46:45 +00:00
_fontWidth = fontSize2 . Width - fontSize1 . Width ;
_fontHeight = fontSize1 . Height ;
2014-09-13 14:50:58 +00:00
2011-06-19 23:39:25 +00:00
InitializeComponent ( ) ;
2011-08-23 01:43:19 +00:00
AddressesLabel . BackColor = Color . Transparent ;
2012-03-09 16:13:40 +00:00
LoadConfigSettings ( ) ;
2011-08-22 02:48:12 +00:00
SetHeader ( ) ;
2019-11-03 18:46:39 +00:00
Closing + = ( o , e ) = > CloseHexFind ( ) ;
2014-09-13 14:50:58 +00:00
Header . Font = font ;
AddressesLabel . Font = font ;
AddressLabel . Font = font ;
2011-06-19 23:39:25 +00:00
}
2019-11-03 16:46:45 +00:00
private WatchSize WatchSize = > ( WatchSize ) DataSize ;
2013-11-28 22:06:38 +00:00
#region API
2019-11-03 16:46:45 +00:00
public bool UpdateBefore = > false ;
2013-11-28 22:06:38 +00:00
2014-08-19 19:24:17 +00:00
public bool AskSaveChanges ( )
2013-11-28 22:06:38 +00:00
{
return true ;
}
2016-08-13 20:31:04 +00:00
public void NewUpdate ( ToolFormUpdateType type ) { }
2013-11-28 20:02:32 +00:00
public void UpdateValues ( )
2019-12-07 18:59:01 +00:00
{
AddressesLabel . Text = GenerateMemoryViewString ( true ) ;
}
public void FullUpdate ( )
2012-03-09 16:13:40 +00:00
{
2015-08-31 16:37:46 +00:00
AddressesLabel . Text = GenerateMemoryViewString ( true ) ;
2013-11-28 20:02:32 +00:00
AddressLabel . Text = GenerateAddressString ( ) ;
2012-03-09 16:13:40 +00:00
}
2014-07-25 01:55:21 +00:00
public void FastUpdate ( )
{
// Do nothing
}
2017-05-10 11:45:23 +00:00
private string _lastRom = "" ;
2015-08-23 16:59:27 +00:00
2013-11-28 20:02:32 +00:00
public void Restart ( )
2011-06-19 23:39:25 +00:00
{
2015-01-14 00:08:20 +00:00
_rom = GetRomBytes ( ) ;
2017-04-24 18:55:20 +00:00
_romDomain = new MemoryDomainByteArray ( "File on Disk" , MemoryDomain . Endian . Little , _rom , true , 1 ) ;
2013-11-28 20:02:32 +00:00
2015-01-14 00:08:20 +00:00
if ( _domain . Name = = _romDomain . Name )
{
_domain = _romDomain ;
}
else if ( MemoryDomains . Any ( x = > x . Name = = _domain . Name ) )
{
_domain = MemoryDomains [ _domain . Name ] ;
}
else
2012-06-23 18:45:01 +00:00
{
2015-01-14 00:08:20 +00:00
_domain = MemoryDomains . MainMemory ;
2012-06-23 18:45:01 +00:00
}
2015-01-14 00:08:20 +00:00
BigEndian = _domain . EndianType = = MemoryDomain . Endian . Big ;
2017-11-09 13:41:35 +00:00
2015-01-18 18:59:23 +00:00
_maxRow = _domain . Size / 2 ;
2015-01-14 00:08:20 +00:00
2015-08-23 16:59:27 +00:00
// Don't reset scroll bar if restarting the same rom
if ( _lastRom ! = GlobalWin . MainForm . CurrentlyOpenRom )
{
_lastRom = GlobalWin . MainForm . CurrentlyOpenRom ;
ResetScrollBar ( ) ;
}
2015-01-01 14:54:26 +00:00
SetDataSize ( DataSize ) ;
2015-08-23 18:04:00 +00:00
SetHeader ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2013-11-28 20:02:32 +00:00
}
2015-11-28 21:47:16 +00:00
public void SetToAddresses ( IEnumerable < long > addresses , MemoryDomain domain , WatchSize size )
2013-11-28 20:02:32 +00:00
{
2015-01-01 14:54:26 +00:00
DataSize = ( int ) size ;
SetDataSize ( DataSize ) ;
2013-11-28 20:02:32 +00:00
var addrList = addresses . ToList ( ) ;
if ( addrList . Any ( ) )
2011-06-19 23:39:25 +00:00
{
2013-11-28 20:02:32 +00:00
SetDomain ( domain ) ;
SetHighlighted ( addrList [ 0 ] ) ;
_secondaryHighlightedAddresses . Clear ( ) ;
2019-10-13 15:50:57 +00:00
_secondaryHighlightedAddresses . AddRange ( addrList . Where ( addr = > addr ! = addrList [ 0 ] ) ) ;
2013-11-28 20:02:32 +00:00
ClearNibbles ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2013-11-28 20:02:32 +00:00
MemoryViewerBox . Refresh ( ) ;
}
}
2014-03-23 23:47:20 +00:00
public byte [ ] ConvertTextToBytes ( string str )
{
if ( _textTable . Any ( ) )
{
var byteArr = new List < byte > ( ) ;
foreach ( var chr in str )
{
byteArr . Add ( ( byte ) _textTable . FirstOrDefault ( kvp = > kvp . Value = = chr ) . Key ) ;
}
return byteArr . ToArray ( ) ;
}
return str . Select ( Convert . ToByte ) . ToArray ( ) ;
}
2018-03-18 14:26:36 +00:00
public byte [ ] ConvertHexStringToByteArray ( string str )
{
if ( string . IsNullOrWhiteSpace ( str ) ) {
return new byte [ 0 ] ;
}
// TODO: Better method of handling this?
if ( str . Length % 2 = = 1 )
{
str + = "0" ;
}
byte [ ] bytes = new byte [ str . Length / 2 ] ;
for ( int i = 0 ; i < str . Length ; i + = 2 )
{
bytes [ i / 2 ] = Convert . ToByte ( str . Substring ( i , 2 ) , 16 ) ;
}
return bytes ;
}
2013-11-28 20:02:32 +00:00
public void FindNext ( string value , bool wrap )
{
2015-01-18 18:01:27 +00:00
long found = - 1 ;
2013-11-28 20:02:32 +00:00
2017-05-10 11:45:23 +00:00
var search = value . Replace ( " " , "" ) . ToUpper ( ) ;
2014-01-30 03:10:17 +00:00
if ( string . IsNullOrEmpty ( search ) )
2013-11-28 20:02:32 +00:00
{
return ;
}
var numByte = search . Length / 2 ;
2015-01-18 18:01:27 +00:00
long startByte ;
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress = = null )
2013-11-28 20:02:32 +00:00
{
startByte = 0 ;
}
2019-11-03 17:14:08 +00:00
else if ( _highlightedAddress > = ( _domain . Size - 1 - numByte ) )
2013-11-28 20:02:32 +00:00
{
startByte = 0 ;
}
else
{
2019-11-03 17:14:08 +00:00
startByte = _highlightedAddress . Value + DataSize ;
2013-11-28 20:02:32 +00:00
}
2018-03-18 14:26:36 +00:00
byte [ ] searchBytes = ConvertHexStringToByteArray ( search ) ;
2015-01-18 16:00:20 +00:00
for ( var i = startByte ; i < ( _domain . Size - numByte ) ; i + + )
2013-11-28 20:02:32 +00:00
{
2018-03-18 14:26:36 +00:00
bool differenceFound = false ;
2013-11-28 20:02:32 +00:00
for ( var j = 0 ; j < numByte ; j + + )
{
2018-03-18 14:26:36 +00:00
if ( _domain . PeekByte ( i + j ) ! = searchBytes [ j ] )
{
differenceFound = true ;
break ;
}
2013-11-28 20:02:32 +00:00
}
2013-11-28 22:06:38 +00:00
2018-03-18 14:26:36 +00:00
if ( ! differenceFound )
2013-11-28 20:02:32 +00:00
{
found = i ;
break ;
}
}
if ( found > - 1 )
{
HighlightSecondaries ( search , found ) ;
GoToAddress ( found ) ;
_findStr = search ;
}
2013-11-28 22:06:38 +00:00
else if ( wrap = = false )
2013-11-28 20:02:32 +00:00
{
2013-11-28 22:06:38 +00:00
FindPrev ( value , true ) ; // Search the opposite direction if not found
2013-11-28 20:02:32 +00:00
}
2014-03-23 19:55:56 +00:00
_hexFind . Close ( ) ;
2013-11-28 20:02:32 +00:00
}
public void FindPrev ( string value , bool wrap )
{
2015-01-18 18:01:27 +00:00
long found = - 1 ;
2013-11-28 20:02:32 +00:00
2017-05-10 11:45:23 +00:00
var search = value . Replace ( " " , "" ) . ToUpper ( ) ;
2014-03-23 19:55:56 +00:00
if ( string . IsNullOrEmpty ( search ) )
2013-11-28 20:02:32 +00:00
{
return ;
}
var numByte = search . Length / 2 ;
2019-11-03 17:14:08 +00:00
long startByte = _highlightedAddress - 1 ? ? _domain . Size - DataSize - numByte ;
2013-11-28 20:02:32 +00:00
2018-03-18 14:26:36 +00:00
byte [ ] searchBytes = ConvertHexStringToByteArray ( search ) ;
2013-11-28 20:02:32 +00:00
for ( var i = startByte ; i > = 0 ; i - - )
{
2018-03-18 14:26:36 +00:00
bool differenceFound = false ;
2013-11-28 20:02:32 +00:00
for ( var j = 0 ; j < numByte ; j + + )
{
2018-03-18 14:26:36 +00:00
if ( _domain . PeekByte ( i + j ) ! = searchBytes [ j ] ) {
differenceFound = true ;
break ;
}
2013-11-28 20:02:32 +00:00
}
2013-11-28 22:06:38 +00:00
2018-03-18 14:26:36 +00:00
if ( ! differenceFound )
2013-11-28 20:02:32 +00:00
{
found = i ;
break ;
}
}
if ( found > - 1 )
{
HighlightSecondaries ( search , found ) ;
GoToAddress ( found ) ;
_findStr = search ;
}
2013-11-28 22:06:38 +00:00
else if ( wrap = = false )
2013-11-28 20:02:32 +00:00
{
2013-11-28 22:06:38 +00:00
FindPrev ( value , true ) ; // Search the opposite direction if not found
2011-06-19 23:39:25 +00:00
}
2014-03-23 19:55:56 +00:00
_hexFind . Close ( ) ;
2011-06-19 23:39:25 +00:00
}
2013-11-28 20:02:32 +00:00
#endregion
2014-03-23 20:27:20 +00:00
private char Remap ( byte val )
2013-11-28 22:06:38 +00:00
{
2014-03-23 20:27:20 +00:00
if ( _textTable . Any ( ) )
2013-11-28 22:06:38 +00:00
{
2014-03-23 20:27:20 +00:00
if ( _textTable . ContainsKey ( val ) )
{
return _textTable [ val ] ;
}
return '?' ;
2013-11-28 22:06:38 +00:00
}
2014-03-23 20:27:20 +00:00
2019-11-03 18:46:39 +00:00
if ( val < ' ' | | val > = 0x7F )
{
return '.' ;
2013-11-28 22:06:38 +00:00
}
2019-11-03 18:46:39 +00:00
return ( char ) val ;
2013-11-28 22:06:38 +00:00
}
private static bool CurrentRomIsArchive ( )
{
var path = GlobalWin . MainForm . CurrentlyOpenRom ;
if ( path = = null )
{
return false ;
}
2019-11-03 16:46:45 +00:00
using var file = new HawkFile ( ) ;
file . Open ( path ) ;
2013-11-28 22:06:38 +00:00
2019-11-03 16:46:45 +00:00
if ( ! file . Exists )
{
return false ;
2013-11-28 22:06:38 +00:00
}
2019-11-03 16:46:45 +00:00
return file . IsArchive ;
2013-11-28 22:06:38 +00:00
}
private static byte [ ] GetRomBytes ( )
{
2015-11-19 03:17:34 +00:00
var path = GlobalWin . MainForm . CurrentlyOpenRomArgs . OpenAdvanced . SimplePath ;
if ( string . IsNullOrEmpty ( path ) )
2013-11-28 22:06:38 +00:00
{
return new byte [ ] { 0xFF } ;
}
2019-11-03 16:46:45 +00:00
using var file = new HawkFile ( ) ;
file . Open ( path ) ;
2013-11-28 22:06:38 +00:00
2019-11-03 16:46:45 +00:00
if ( ! file . Exists )
{
return null ;
}
2013-11-28 22:06:38 +00:00
2019-11-03 16:46:45 +00:00
if ( file . IsArchive )
{
var stream = file . GetStream ( ) ;
return stream . ReadAllBytes ( ) ;
2013-11-28 22:06:38 +00:00
}
2019-11-03 16:46:45 +00:00
return File . ReadAllBytes ( path ) ;
2013-11-28 22:06:38 +00:00
}
2014-09-11 21:55:38 +00:00
private static int GetNumDigits ( long i )
2013-11-28 22:06:38 +00:00
{
if ( i < = 0x10000 )
{
return 4 ;
}
return i < = 0x1000000 ? 6 : 8 ;
}
private static bool IsHexKeyCode ( char key )
{
2014-02-08 21:47:39 +00:00
if ( key > = '0' & & key < = '9' ) // 0-9
2013-11-28 22:06:38 +00:00
{
return true ;
}
2014-03-01 15:21:17 +00:00
if ( key > = 'a' & & key < = 'f' ) // A-F
2013-11-28 22:06:38 +00:00
{
return true ;
}
2014-03-01 15:21:17 +00:00
if ( key > = 'A' & & key < = 'F' ) // A-F
2013-11-28 22:06:38 +00:00
{
return true ;
}
2014-03-01 15:21:17 +00:00
return false ;
2013-11-28 22:06:38 +00:00
}
2011-06-19 23:39:25 +00:00
private void HexEditor_Load ( object sender , EventArgs e )
{
2016-04-13 23:50:06 +00:00
DataSize = _domain . WordSize ;
2015-01-01 14:54:26 +00:00
SetDataSize ( DataSize ) ;
2014-03-23 20:27:20 +00:00
2018-11-18 17:18:42 +00:00
if ( ! string . IsNullOrWhiteSpace ( LastDomain )
& & MemoryDomains . Any ( m = > m . Name = = LastDomain ) )
{
SetMemoryDomain ( LastDomain ) ;
}
2015-01-01 14:54:26 +00:00
if ( RecentTables . AutoLoad )
2014-03-23 20:27:20 +00:00
{
2015-01-01 14:54:26 +00:00
LoadFileFromRecent ( RecentTables [ 0 ] ) ;
2014-03-23 20:27:20 +00:00
}
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2011-06-19 23:39:25 +00:00
}
2013-11-28 20:02:32 +00:00
private void LoadConfigSettings ( )
2011-06-19 23:39:25 +00:00
{
2013-11-28 22:06:38 +00:00
HexMenuStrip . BackColor = Global . Config . HexMenubarColor ;
2013-11-28 20:02:32 +00:00
MemoryViewerBox . BackColor = Global . Config . HexBackgrndColor ;
MemoryViewerBox . ForeColor = Global . Config . HexForegrndColor ;
Header . BackColor = Global . Config . HexBackgrndColor ;
Header . ForeColor = Global . Config . HexForegrndColor ;
2011-06-19 23:39:25 +00:00
}
2019-11-03 18:46:39 +00:00
private void CloseHexFind ( )
2011-06-19 23:39:25 +00:00
{
2013-11-28 20:02:32 +00:00
if ( _hexFind . IsHandleCreated | | ! _hexFind . IsDisposed )
{
_hexFind . Close ( ) ;
}
2011-08-22 02:48:12 +00:00
}
2013-11-28 20:02:32 +00:00
private string GenerateAddressString ( )
2012-06-18 03:34:14 +00:00
{
2013-11-28 14:43:27 +00:00
var addrStr = new StringBuilder ( ) ;
2012-06-18 03:34:14 +00:00
2013-11-28 14:43:27 +00:00
for ( var i = 0 ; i < _rowsVisible ; i + + )
2012-06-18 03:34:14 +00:00
{
2013-11-28 20:02:32 +00:00
_row = i + HexScrollBar . Value ;
2013-11-28 22:06:38 +00:00
_addr = _row < < 4 ;
2015-01-18 16:00:20 +00:00
if ( _addr > = _domain . Size )
2013-11-28 14:43:27 +00:00
{
2012-06-18 03:34:14 +00:00
break ;
2013-11-28 14:43:27 +00:00
}
2012-09-11 00:17:54 +00:00
2013-11-28 14:43:27 +00:00
if ( _numDigits = = 4 )
2012-09-11 00:17:54 +00:00
{
2013-11-28 22:06:38 +00:00
addrStr . Append ( " " ) ; // Hack to line things up better between 4 and 6
2012-12-03 16:51:39 +00:00
}
2013-11-28 14:43:27 +00:00
else if ( _numDigits = = 6 )
2012-12-03 16:51:39 +00:00
{
addrStr . Append ( " " ) ;
2012-09-11 00:17:54 +00:00
}
2013-11-28 22:06:38 +00:00
2019-03-18 14:06:37 +00:00
addrStr . AppendLine ( $"{_addr.ToHexString(_numDigits)} |" ) ;
2012-06-18 03:34:14 +00:00
}
return addrStr . ToString ( ) ;
}
2015-08-31 16:37:46 +00:00
private string GenerateMemoryViewString ( bool forWindow )
2011-08-22 02:48:12 +00:00
{
2013-11-28 14:43:27 +00:00
var rowStr = new StringBuilder ( ) ;
2011-08-24 02:48:52 +00:00
2013-11-28 14:43:27 +00:00
for ( var i = 0 ; i < _rowsVisible ; i + + )
2011-08-27 04:32:54 +00:00
{
2013-11-28 20:02:32 +00:00
_row = i + HexScrollBar . Value ;
2013-11-28 22:06:38 +00:00
_addr = _row < < 4 ;
2015-01-18 16:00:20 +00:00
if ( _addr > = _domain . Size )
2013-11-28 22:06:38 +00:00
{
2011-08-27 04:32:54 +00:00
break ;
2013-11-28 22:06:38 +00:00
}
2012-06-18 03:39:21 +00:00
2015-01-01 14:54:26 +00:00
for ( var j = 0 ; j < 16 ; j + = DataSize )
2011-08-27 04:32:54 +00:00
{
2015-01-18 16:00:20 +00:00
if ( _addr + j + DataSize < = _domain . Size )
2012-09-02 22:45:06 +00:00
{
2019-11-03 16:46:45 +00:00
int tVal = 0 ;
2017-10-21 13:52:07 +00:00
for ( int k = 0 ; k < DataSize ; k + + )
{
2019-11-03 16:46:45 +00:00
int tNext = MakeValue ( 1 , _addr + j + k ) ;
2019-11-03 16:58:41 +00:00
if ( BigEndian )
2017-11-09 13:41:35 +00:00
{
2019-11-03 16:46:45 +00:00
tVal + = ( tNext < < ( k * 8 ) ) ;
2017-11-09 13:41:35 +00:00
}
else
{
2019-11-03 16:46:45 +00:00
tVal + = ( tNext < < ( ( DataSize - k - 1 ) * 8 ) ) ;
2018-11-18 17:18:42 +00:00
}
2017-10-21 13:52:07 +00:00
}
2019-11-03 16:46:45 +00:00
rowStr . AppendFormat ( _digitFormatString , tVal ) ;
2012-09-02 22:45:06 +00:00
}
2012-12-03 16:51:39 +00:00
else
{
2015-01-01 14:54:26 +00:00
for ( var t = 0 ; t < DataSize ; t + + )
2013-11-28 14:43:27 +00:00
{
2012-12-03 16:51:39 +00:00
rowStr . Append ( " " ) ;
2013-11-28 14:43:27 +00:00
}
2013-11-28 22:06:38 +00:00
2012-12-03 16:51:39 +00:00
rowStr . Append ( ' ' ) ;
}
2011-08-27 04:32:54 +00:00
}
2013-11-28 22:06:38 +00:00
2015-12-20 19:51:07 +00:00
rowStr . Append ( "| " ) ;
2013-11-28 14:43:27 +00:00
for ( var k = 0 ; k < 16 ; k + + )
2011-08-27 04:32:54 +00:00
{
2015-01-18 16:00:20 +00:00
if ( _addr + k < _domain . Size )
2012-09-02 22:45:06 +00:00
{
2015-08-31 16:37:46 +00:00
byte b = MakeByte ( _addr + k ) ;
char c = Remap ( b ) ;
rowStr . Append ( c ) ;
//winforms will be using these as escape codes for hotkeys
if ( forWindow ) if ( c = = '&' ) rowStr . Append ( '&' ) ;
2012-09-02 22:45:06 +00:00
}
2011-08-22 02:48:12 +00:00
}
2011-08-27 04:32:54 +00:00
2013-11-28 22:06:38 +00:00
rowStr . AppendLine ( ) ;
2011-08-22 02:48:12 +00:00
}
2013-11-28 22:06:38 +00:00
return rowStr . ToString ( ) ;
2011-08-22 02:48:12 +00:00
}
2015-01-18 18:13:38 +00:00
private byte MakeByte ( long address )
2014-01-01 03:19:08 +00:00
{
2015-01-18 18:59:23 +00:00
return Global . CheatList . IsActive ( _domain , address )
? Global . CheatList . GetByteValue ( _domain , address ) . Value
2014-01-01 03:19:08 +00:00
: _domain . PeekByte ( address ) ;
}
2019-11-03 16:46:45 +00:00
private int MakeValue ( int dataSize , long address )
2011-08-22 02:48:12 +00:00
{
2015-09-29 07:29:19 +00:00
switch ( dataSize )
2011-08-22 02:48:12 +00:00
{
2011-08-27 04:32:54 +00:00
default :
case 1 :
2013-11-28 14:43:27 +00:00
return _domain . PeekByte ( address ) ;
2011-08-27 04:32:54 +00:00
case 2 :
2019-11-03 16:58:41 +00:00
return _domain . PeekUshort ( address , BigEndian ) ;
2011-08-27 04:32:54 +00:00
case 4 :
2019-11-03 16:58:41 +00:00
return ( int ) _domain . PeekUint ( address , BigEndian ) ;
2011-08-22 02:48:12 +00:00
}
}
2015-09-29 07:29:19 +00:00
private int MakeValue ( long address )
{
2019-11-03 16:46:45 +00:00
return MakeValue ( DataSize , address ) ;
2015-09-29 07:29:19 +00:00
}
2015-01-14 00:08:20 +00:00
private void SetMemoryDomain ( string name )
2011-08-22 02:48:12 +00:00
{
2019-11-03 16:46:45 +00:00
_domain = name = = _romDomain . Name
? _romDomain
: MemoryDomains [ name ] ;
2014-09-11 21:55:38 +00:00
2015-01-14 00:08:20 +00:00
BigEndian = _domain . EndianType = = MemoryDomain . Endian . Big ;
2015-01-18 18:13:38 +00:00
_maxRow = _domain . Size / 2 ;
2011-08-22 02:48:12 +00:00
SetUpScrollBar ( ) ;
2013-11-28 20:02:32 +00:00
if ( 0 > = HexScrollBar . Minimum & & 0 < = HexScrollBar . Maximum )
2012-12-23 02:49:08 +00:00
{
2013-11-28 20:02:32 +00:00
HexScrollBar . Value = 0 ;
2012-12-23 02:49:08 +00:00
}
2013-11-28 22:06:38 +00:00
2019-11-03 16:46:45 +00:00
AddressesLabel . ForeColor = _domain . CanPoke ( )
? SystemColors . ControlText
: SystemColors . ControlDarkDark ;
2015-01-25 15:42:07 +00:00
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress > = _domain . Size
2016-10-06 14:35:17 +00:00
| | ( _secondaryHighlightedAddresses . Any ( ) & & _secondaryHighlightedAddresses . Max ( ) > = _domain . Size ) )
{
2019-11-03 17:14:08 +00:00
_highlightedAddress = null ;
2016-10-06 14:35:17 +00:00
_secondaryHighlightedAddresses . Clear ( ) ;
}
2015-01-14 00:08:20 +00:00
UpdateGroupBoxTitle ( ) ;
2015-08-23 18:04:00 +00:00
SetHeader ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2018-11-18 17:18:42 +00:00
LastDomain = _domain . Name ;
2011-08-22 02:48:12 +00:00
}
2013-11-28 20:02:32 +00:00
private void SetDomain ( MemoryDomain domain )
{
2015-01-25 15:42:07 +00:00
SetMemoryDomain ( domain . Name ) ;
2011-06-19 23:39:25 +00:00
}
2011-08-23 23:48:22 +00:00
private void UpdateGroupBoxTitle ( )
2011-06-19 23:39:25 +00:00
{
2019-03-18 14:06:37 +00:00
var addressesString = "0x" + $"{_domain.Size / DataSize:X8}" . TrimStart ( '0' ) ;
2019-11-03 17:31:53 +00:00
var viewerText = $"{Emulator.SystemId} {_domain}{(_domain.CanPoke() ? string.Empty : " ( READ - ONLY ) ")} - {addressesString} addresses" ;
2019-11-03 17:48:31 +00:00
if ( _nibbles . Any ( ) )
2019-11-03 17:31:53 +00:00
{
viewerText + = $" Typing: ({MakeNibbles()})" ;
}
MemoryViewerBox . Text = viewerText ;
2011-06-19 23:39:25 +00:00
}
2013-11-28 20:02:32 +00:00
private void ClearNibbles ( )
2011-08-22 02:48:12 +00:00
{
2019-11-03 17:48:31 +00:00
_nibbles . Clear ( ) ;
UpdateGroupBoxTitle ( ) ;
2011-06-19 23:39:25 +00:00
}
2015-01-18 18:01:27 +00:00
private void GoToAddress ( long address )
2011-08-07 19:53:52 +00:00
{
2011-08-22 02:48:12 +00:00
if ( address < 0 )
2013-04-14 23:56:45 +00:00
{
2011-08-22 02:48:12 +00:00
address = 0 ;
2013-04-14 23:56:45 +00:00
}
2011-08-22 02:48:12 +00:00
2015-01-18 16:00:20 +00:00
if ( address > = _domain . Size )
2013-04-14 23:56:45 +00:00
{
2015-01-19 02:42:58 +00:00
address = _domain . Size - DataSize ;
2013-04-14 23:56:45 +00:00
}
2011-08-22 02:48:12 +00:00
SetHighlighted ( address ) ;
ClearNibbles ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2011-08-23 22:22:24 +00:00
MemoryViewerBox . Refresh ( ) ;
2011-08-07 19:53:52 +00:00
}
2011-06-19 23:39:25 +00:00
2015-01-18 18:01:27 +00:00
private void SetHighlighted ( long address )
2011-08-22 02:48:12 +00:00
{
2013-04-14 23:56:45 +00:00
if ( address < 0 )
{
address = 0 ;
}
2015-01-18 16:00:20 +00:00
if ( address > = _domain . Size )
2013-04-14 23:56:45 +00:00
{
2015-01-19 02:42:58 +00:00
address = _domain . Size - DataSize ;
2013-04-14 23:56:45 +00:00
}
2011-08-22 02:48:12 +00:00
2013-04-14 23:56:45 +00:00
if ( ! IsVisible ( address ) )
2011-08-22 02:48:12 +00:00
{
2013-11-28 14:43:27 +00:00
var value = ( address / 16 ) - _rowsVisible + 1 ;
if ( value < 0 )
2013-04-14 23:56:45 +00:00
{
2013-11-28 14:43:27 +00:00
value = 0 ;
2013-04-14 23:56:45 +00:00
}
2013-11-28 22:06:38 +00:00
2015-01-18 18:01:27 +00:00
HexScrollBar . Value = ( int ) value ; // This will fail on a sufficiently large domain
2011-08-22 02:48:12 +00:00
}
2013-11-28 22:06:38 +00:00
2019-11-03 17:14:08 +00:00
_highlightedAddress = address ;
2013-11-28 14:43:27 +00:00
_addressOver = address ;
2011-08-25 23:58:16 +00:00
ClearNibbles ( ) ;
2011-08-25 23:49:13 +00:00
UpdateFormText ( ) ;
2011-08-22 02:48:12 +00:00
}
2011-08-25 23:49:13 +00:00
private void UpdateFormText ( )
{
2015-12-20 19:51:07 +00:00
Text = "Hex Editor" ;
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2013-11-28 22:06:38 +00:00
{
2019-11-03 17:14:08 +00:00
Text + = " - Editing Address 0x" + string . Format ( _numDigitsStr , _highlightedAddress ) ;
2015-12-20 19:51:07 +00:00
if ( _secondaryHighlightedAddresses . Any ( ) )
{
2019-11-03 17:14:08 +00:00
Text + = $" (Selected 0x{_secondaryHighlightedAddresses.Count + (_secondaryHighlightedAddresses.Contains(_highlightedAddress.Value) ? 0 : 1):X})" ;
2015-12-20 19:51:07 +00:00
}
2013-11-28 22:06:38 +00:00
}
2011-08-25 23:49:13 +00:00
}
2015-01-18 18:01:27 +00:00
private bool IsVisible ( long address )
2011-08-22 02:48:12 +00:00
{
2013-11-28 14:43:27 +00:00
var i = address > > 4 ;
2019-11-03 18:46:39 +00:00
return i > = HexScrollBar . Value & & i < _rowsVisible + HexScrollBar . Value ;
2011-08-22 02:48:12 +00:00
}
private void SetHeader ( )
{
2015-01-01 14:54:26 +00:00
switch ( DataSize )
2011-08-22 02:48:12 +00:00
{
case 1 :
2015-12-20 19:51:07 +00:00
Header . Text = " 0 1 2 3 4 5 6 7 8 9 A B C D E F" ;
2011-08-22 02:48:12 +00:00
break ;
case 2 :
2015-12-20 19:51:07 +00:00
Header . Text = " 0 2 4 6 8 A C E" ;
2011-08-22 02:48:12 +00:00
break ;
case 4 :
2015-12-20 19:51:07 +00:00
Header . Text = " 0 4 8 C" ;
2011-08-22 02:48:12 +00:00
break ;
}
2013-11-28 22:06:38 +00:00
2015-01-18 16:00:20 +00:00
_numDigits = GetNumDigits ( _domain . Size ) ;
2019-03-18 14:06:37 +00:00
_numDigitsStr = $"{{0:X{_numDigits}}} " ;
2011-08-22 02:48:12 +00:00
}
2013-11-28 22:06:38 +00:00
private void SetDataSize ( int size )
2011-08-22 02:48:12 +00:00
{
if ( size = = 1 | | size = = 2 | | size = = 4 )
2013-11-28 20:02:32 +00:00
{
2015-01-01 14:54:26 +00:00
DataSize = size ;
2019-03-18 14:06:37 +00:00
_digitFormatString = $"{{0:X{DataSize * 2}}} " ;
2013-11-28 20:02:32 +00:00
SetHeader ( ) ;
UpdateGroupBoxTitle ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2015-09-29 04:54:26 +00:00
_secondaryHighlightedAddresses . Clear ( ) ;
2013-11-28 20:02:32 +00:00
}
2011-06-19 23:39:25 +00:00
}
2015-01-18 18:01:27 +00:00
private Watch MakeWatch ( long address )
2012-06-19 02:42:07 +00:00
{
2015-01-01 14:54:26 +00:00
switch ( DataSize )
2012-06-19 02:42:07 +00:00
{
default :
2018-11-18 17:18:42 +00:00
case 1 :
2019-11-03 16:46:45 +00:00
return Watch . GenerateWatch ( _domain , address , WatchSize . Byte , Common . DisplayType . Hex , BigEndian ) ;
2017-04-15 20:37:30 +00:00
case 2 :
2019-11-03 16:46:45 +00:00
return Watch . GenerateWatch ( _domain , address , WatchSize . Word , Common . DisplayType . Hex , BigEndian ) ;
2012-06-19 02:42:07 +00:00
case 4 :
2019-11-03 16:46:45 +00:00
return Watch . GenerateWatch ( _domain , address , WatchSize . DWord , Common . DisplayType . Hex , BigEndian ) ;
2012-06-19 02:42:07 +00:00
}
}
2015-01-18 18:01:27 +00:00
private bool IsFrozen ( long address )
2012-03-09 01:24:46 +00:00
{
2015-01-18 18:59:23 +00:00
return Global . CheatList . IsActive ( _domain , address ) ;
2012-03-09 01:24:46 +00:00
}
2015-01-18 18:01:27 +00:00
private void UnFreezeAddress ( long address )
2012-03-09 01:24:46 +00:00
{
2013-11-28 22:06:38 +00:00
if ( address > = 0 )
2012-03-09 01:24:46 +00:00
{
2019-10-13 15:50:57 +00:00
Global . CheatList . RemoveRange ( Global . CheatList . Where ( x = > x . Contains ( address ) ) ) ;
2013-10-06 16:40:51 +00:00
}
2012-03-09 01:24:46 +00:00
2013-11-28 22:06:38 +00:00
MemoryViewerBox . Refresh ( ) ;
2012-03-09 01:24:46 +00:00
}
2015-01-18 18:01:27 +00:00
private void FreezeAddress ( long address )
2011-06-19 23:39:25 +00:00
{
if ( address > = 0 )
{
2013-11-28 14:43:27 +00:00
var watch = Watch . GenerateWatch (
_domain ,
2015-01-18 18:59:23 +00:00
address ,
2013-10-06 16:40:51 +00:00
WatchSize ,
2019-11-03 16:46:45 +00:00
Common . DisplayType . Hex ,
2015-01-01 14:54:26 +00:00
BigEndian ) ;
2011-08-25 01:22:03 +00:00
2013-10-20 18:02:43 +00:00
Global . CheatList . Add ( new Cheat (
2013-10-06 18:44:51 +00:00
watch ,
2015-11-29 16:13:32 +00:00
watch . Value ) ) ;
2011-06-19 23:39:25 +00:00
}
}
2014-03-01 18:04:21 +00:00
private void FreezeSecondaries ( )
{
var cheats = new List < Cheat > ( ) ;
foreach ( var address in _secondaryHighlightedAddresses )
{
var watch = Watch . GenerateWatch (
_domain ,
2015-01-18 18:59:23 +00:00
address ,
2014-03-01 18:04:21 +00:00
WatchSize ,
2019-11-03 16:46:45 +00:00
Common . DisplayType . Hex ,
2015-01-01 14:54:26 +00:00
BigEndian ) ;
2014-03-01 18:04:21 +00:00
cheats . Add ( new Cheat (
watch ,
2015-11-29 16:13:32 +00:00
watch . Value ) ) ;
2014-03-01 18:04:21 +00:00
}
Global . CheatList . AddRange ( cheats ) ;
}
private void UnfreezeSecondaries ( )
{
Global . CheatList . RemoveRange (
Global . CheatList . Where (
cheat = > ! cheat . IsSeparator & & cheat . Domain = = _domain & & _secondaryHighlightedAddresses . Contains ( cheat . Address . Value ) ) ) ;
}
2013-11-28 14:43:27 +00:00
private void SaveFileBinary ( string path )
2012-09-02 23:12:00 +00:00
{
2013-11-28 14:43:27 +00:00
var file = new FileInfo ( path ) ;
2019-11-03 16:46:45 +00:00
using var binWriter = new BinaryWriter ( File . Open ( file . FullName , FileMode . Create ) ) ;
for ( var i = 0 ; i < _domain . Size ; i + + )
2012-06-10 17:28:38 +00:00
{
2019-11-03 16:46:45 +00:00
binWriter . Write ( _domain . PeekByte ( i ) ) ;
2012-06-10 17:28:38 +00:00
}
}
2012-09-02 23:12:00 +00:00
private string GetSaveFileFilter ( )
{
2014-02-10 01:15:11 +00:00
if ( _domain . Name = = "File on Disk" )
2012-09-02 23:12:00 +00:00
{
2015-08-23 16:34:13 +00:00
var extension = Path . GetExtension ( RomName ) ;
2019-03-18 14:06:37 +00:00
return $"Binary (*{extension})|*{extension}|All Files|*.*" ;
2012-09-02 23:12:00 +00:00
}
2014-03-01 15:21:17 +00:00
return "Binary (*.bin)|*.bin|All Files|*.*" ;
2012-09-02 23:12:00 +00:00
}
2015-08-23 16:34:13 +00:00
private string RomDirectory
{
get
{
string path = Global . Config . RecentRoms . MostRecent ;
if ( string . IsNullOrWhiteSpace ( path ) )
{
2019-11-03 18:46:39 +00:00
return "" ;
2015-08-23 16:34:13 +00:00
}
if ( path . Contains ( "|" ) )
{
path = path . Split ( '|' ) . First ( ) ;
}
return Path . GetDirectoryName ( path ) ;
}
}
private string RomName
{
get
{
string path = Global . Config . RecentRoms . MostRecent ;
if ( string . IsNullOrWhiteSpace ( path ) )
{
2019-11-03 18:46:39 +00:00
return "" ;
2015-08-23 16:34:13 +00:00
}
if ( path . Contains ( "|" ) )
{
path = path . Split ( '|' ) . Last ( ) ;
}
return Path . GetFileName ( path ) ;
}
}
2013-11-28 14:43:27 +00:00
private string GetBinarySaveFileFromUser ( )
2012-06-10 17:28:38 +00:00
{
2019-11-02 04:29:09 +00:00
using var sfd = new SaveFileDialog
2014-03-26 00:34:43 +00:00
{
2019-11-03 16:46:45 +00:00
Filter = GetSaveFileFilter ( )
, RestoreDirectory = true
, InitialDirectory = RomDirectory
, FileName =
_domain . Name = = "File on Disk"
? RomName
: PathManager . FilesystemSafeName ( Global . Game )
2015-08-23 16:34:13 +00:00
} ;
var result = sfd . ShowHawkDialog ( ) ;
2017-05-10 11:45:23 +00:00
return result = = DialogResult . OK ? sfd . FileName : "" ;
2015-08-23 16:34:13 +00:00
}
private string GetSaveFileFromUser ( )
{
2019-11-02 04:29:09 +00:00
using var sfd = new SaveFileDialog
2015-08-23 16:34:13 +00:00
{
2019-11-03 16:46:45 +00:00
Filter = "Text (*.txt)|*.txt|All Files|*.*"
, RestoreDirectory = true
, InitialDirectory = RomDirectory
, FileName = _domain . Name = = "File on Disk"
? $"{Path.GetFileNameWithoutExtension(RomName)}.txt"
: PathManager . FilesystemSafeName ( Global . Game )
2014-03-26 00:34:43 +00:00
} ;
2012-06-10 17:28:38 +00:00
2013-11-28 22:39:00 +00:00
var result = sfd . ShowHawkDialog ( ) ;
2017-05-10 11:45:23 +00:00
return result = = DialogResult . OK ? sfd . FileName : "" ;
2012-06-10 17:28:38 +00:00
}
2013-11-28 20:02:32 +00:00
private void ResetScrollBar ( )
2011-08-22 02:48:12 +00:00
{
2013-11-28 20:02:32 +00:00
HexScrollBar . Value = 0 ;
2011-08-22 02:48:12 +00:00
SetUpScrollBar ( ) ;
Refresh ( ) ;
}
2013-11-28 20:02:32 +00:00
private void SetUpScrollBar ( )
2011-08-22 02:48:12 +00:00
{
2019-11-03 16:46:45 +00:00
_rowsVisible = ( MemoryViewerBox . Height - ( _fontHeight * 2 ) - ( _fontHeight / 2 ) ) / _fontHeight ;
2015-01-18 16:00:20 +00:00
var totalRows = ( int ) ( ( _domain . Size + 15 ) / 16 ) ;
2013-10-09 15:28:45 +00:00
2013-12-21 20:06:52 +00:00
if ( totalRows < _rowsVisible )
{
_rowsVisible = totalRows ;
}
2013-11-28 20:02:32 +00:00
HexScrollBar . Maximum = totalRows - 1 ;
HexScrollBar . LargeChange = _rowsVisible ;
HexScrollBar . Visible = totalRows > _rowsVisible ;
2011-08-22 02:48:12 +00:00
2012-06-18 03:34:14 +00:00
AddressLabel . Text = GenerateAddressString ( ) ;
2011-08-22 02:48:12 +00:00
}
2015-01-18 18:13:38 +00:00
private long GetPointedAddress ( int x , int y )
2011-08-22 02:48:12 +00:00
{
2015-01-18 18:13:38 +00:00
long address ;
2013-11-28 22:06:38 +00:00
// Scroll value determines the first row
2015-01-18 20:15:03 +00:00
long i = HexScrollBar . Value ;
2019-11-03 16:46:45 +00:00
var rowOffset = y / _fontHeight ;
i + = rowOffset ;
2015-01-01 14:54:26 +00:00
int colWidth = DataSize * 2 + 1 ;
2013-11-28 22:06:38 +00:00
2019-11-03 16:46:45 +00:00
var column = x / ( _fontWidth * colWidth ) ;
2011-08-22 02:48:12 +00:00
2015-12-24 05:29:48 +00:00
var innerOffset = AddressesLabel . Location . X - AddressLabel . Location . X + AddressesLabel . Margin . Left ;
var start = GetTextOffset ( ) - innerOffset ;
2012-09-10 23:52:42 +00:00
if ( x > start )
{
2019-11-03 16:46:45 +00:00
column = ( x - start ) / ( _fontWidth * DataSize ) ;
2012-09-10 23:52:42 +00:00
}
2012-09-03 00:49:59 +00:00
2015-01-01 14:54:26 +00:00
if ( i > = 0 & & i < = _maxRow & & column > = 0 & & column < ( 16 / DataSize ) )
2011-08-22 02:48:12 +00:00
{
2015-01-01 14:54:26 +00:00
address = ( i * 16 ) + ( column * DataSize ) ;
2011-08-22 02:48:12 +00:00
}
else
{
2012-06-19 02:42:07 +00:00
address = - 1 ;
2011-08-22 02:48:12 +00:00
}
2013-11-28 22:06:38 +00:00
2012-06-19 02:42:07 +00:00
return address ;
2011-08-22 02:48:12 +00:00
}
2012-09-29 21:13:11 +00:00
private void DoShiftClick ( )
{
2015-01-18 16:00:20 +00:00
if ( _addressOver > = 0 & & _addressOver < _domain . Size )
2011-08-23 01:43:19 +00:00
{
2013-11-28 14:43:27 +00:00
_secondaryHighlightedAddresses . Clear ( ) ;
2019-11-03 17:14:08 +00:00
if ( _addressOver < _highlightedAddress )
2012-06-19 02:42:07 +00:00
{
2019-11-03 17:14:08 +00:00
for ( var x = _addressOver ; x < _highlightedAddress ; x + = DataSize )
2012-06-19 02:42:07 +00:00
{
2013-11-28 14:43:27 +00:00
_secondaryHighlightedAddresses . Add ( x ) ;
2012-06-19 02:42:07 +00:00
}
}
2019-11-03 17:14:08 +00:00
else if ( _addressOver > _highlightedAddress )
2012-06-19 02:42:07 +00:00
{
2019-11-03 17:14:08 +00:00
for ( var x = _highlightedAddress . Value + DataSize ; x < = _addressOver ; x + = DataSize )
2012-06-19 02:42:07 +00:00
{
2013-11-28 14:43:27 +00:00
_secondaryHighlightedAddresses . Add ( x ) ;
2012-06-19 02:42:07 +00:00
}
}
2015-12-20 19:51:07 +00:00
if ( ! IsVisible ( _addressOver ) )
{
var value = ( _addressOver / 16 ) + 1 - ( ( _addressOver / 16 ) < HexScrollBar . Value ? 1 : _rowsVisible ) ;
if ( value < 0 )
{
value = 0 ;
}
HexScrollBar . Value = ( int ) value ; // This will fail on a sufficiently large domain
}
2011-08-23 01:43:19 +00:00
}
2011-08-25 23:58:16 +00:00
}
private void ClearHighlighted ( )
{
2019-11-03 17:14:08 +00:00
_highlightedAddress = null ;
2011-08-25 23:58:16 +00:00
UpdateFormText ( ) ;
MemoryViewerBox . Refresh ( ) ;
2011-08-23 01:43:19 +00:00
}
2015-01-18 18:01:27 +00:00
private Point GetAddressCoordinates ( long address )
2011-08-23 22:22:24 +00:00
{
2019-11-03 16:46:45 +00:00
var extra = ( address % DataSize ) * _fontWidth * 2 ;
var xOffset = AddressesLabel . Location . X + _fontWidth / 2 - 2 ;
2014-09-13 14:50:58 +00:00
var yOffset = AddressesLabel . Location . Y ;
return new Point (
2019-11-03 16:46:45 +00:00
( int ) ( ( ( ( address % 16 ) / DataSize ) * ( _fontWidth * ( DataSize * 2 + 1 ) ) ) + xOffset + extra ) ,
2019-11-03 17:14:08 +00:00
( int ) ( ( ( ( address / 16 ) - HexScrollBar . Value ) * _fontHeight ) + yOffset ) ) ;
2011-08-23 22:22:24 +00:00
}
2014-03-23 15:39:47 +00:00
// TODO: rename this, but it is a hack work around for highlighting misaligned addresses that result from highlighting on in a smaller data size and switching size
2015-01-18 18:01:27 +00:00
private bool NeedsExtra ( long val )
2014-03-23 15:39:47 +00:00
{
2015-01-01 14:54:26 +00:00
return val % DataSize > 0 ;
2014-03-23 15:39:47 +00:00
}
2012-09-03 00:49:59 +00:00
private int GetTextOffset ( )
{
2019-11-03 16:46:45 +00:00
int start = ( 16 / DataSize ) * _fontWidth * ( DataSize * 2 + 1 ) ;
start + = AddressesLabel . Location . X + _fontWidth / 2 ;
start + = _fontWidth * 2 ;
2012-09-03 00:49:59 +00:00
return start ;
}
2015-01-18 18:01:27 +00:00
private long GetTextX ( long address )
2012-09-03 00:49:59 +00:00
{
2019-11-03 16:46:45 +00:00
return GetTextOffset ( ) + ( ( address % 16 ) * _fontWidth ) ;
2012-09-03 00:49:59 +00:00
}
2013-11-28 20:02:32 +00:00
private string MakeNibbles ( )
{
2017-05-10 11:45:23 +00:00
var str = "" ;
2019-11-03 17:48:31 +00:00
foreach ( var c in _nibbles )
2011-08-23 01:43:19 +00:00
{
2019-11-03 17:48:31 +00:00
str + = c ;
2011-08-23 01:43:19 +00:00
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
return str ;
}
2012-06-23 20:48:17 +00:00
2015-01-18 18:01:27 +00:00
private void AddToSecondaryHighlights ( long address )
2013-11-28 20:02:32 +00:00
{
2015-12-20 19:51:07 +00:00
if ( address > = 0 & & address < _domain . Size & & ! _secondaryHighlightedAddresses . Contains ( address ) )
2013-11-28 20:02:32 +00:00
{
_secondaryHighlightedAddresses . Add ( address ) ;
}
}
2012-09-28 17:24:44 +00:00
2015-01-18 18:01:27 +00:00
private void IncrementAddress ( long address )
2013-11-28 20:02:32 +00:00
{
2015-01-19 02:42:58 +00:00
if ( Global . CheatList . IsActive ( _domain , address ) )
2013-10-09 15:28:45 +00:00
{
2013-11-28 22:06:38 +00:00
// TODO: Increment should be intelligent since IsActive is. If this address is part of a multi-byte cheat it should intelligently increment just that byte
2019-11-03 18:46:39 +00:00
Global . CheatList . First ( x = > x . Domain = = _domain & & x . Address = = address ) . Increment ( ) ;
2013-10-09 15:28:45 +00:00
}
else
2012-03-08 18:33:57 +00:00
{
2015-01-01 14:54:26 +00:00
switch ( DataSize )
2012-03-08 18:33:57 +00:00
{
default :
2013-10-09 15:28:45 +00:00
case 1 :
2013-11-28 14:43:27 +00:00
_domain . PokeByte (
2013-10-09 15:28:45 +00:00
address ,
2014-03-01 15:21:17 +00:00
( byte ) ( _domain . PeekByte ( address ) + 1 ) ) ;
2012-03-08 18:33:57 +00:00
break ;
case 2 :
2016-04-13 23:50:06 +00:00
_domain . PokeUshort (
2013-10-09 15:28:45 +00:00
address ,
2016-04-13 23:50:06 +00:00
( ushort ) ( _domain . PeekUshort ( address , BigEndian ) + 1 ) ,
2015-01-01 14:54:26 +00:00
BigEndian ) ;
2012-03-08 18:33:57 +00:00
break ;
case 4 :
2016-04-13 23:50:06 +00:00
_domain . PokeUint (
2013-10-09 15:28:45 +00:00
address ,
2016-04-13 23:50:06 +00:00
_domain . PeekUint ( address , BigEndian ) + 1 ,
2015-01-01 14:54:26 +00:00
BigEndian ) ;
2012-03-08 18:33:57 +00:00
break ;
}
}
}
2015-01-18 18:01:27 +00:00
private void DecrementAddress ( long address )
2012-06-25 03:10:04 +00:00
{
2015-01-19 02:42:58 +00:00
if ( Global . CheatList . IsActive ( _domain , address ) )
2012-06-25 03:10:04 +00:00
{
2013-11-28 22:06:38 +00:00
// TODO: Increment should be intelligent since IsActive is. If this address is part of a multi-byte cheat it should intelligently increment just that byte
2019-11-03 18:46:39 +00:00
Global . CheatList . First ( x = > x . Domain = = _domain & & x . Address = = address ) . Decrement ( ) ;
2012-06-25 03:10:04 +00:00
}
else
{
2015-01-01 14:54:26 +00:00
switch ( DataSize )
2012-03-08 18:33:57 +00:00
{
default :
case 1 :
2013-11-28 14:43:27 +00:00
_domain . PokeByte (
2013-10-09 15:28:45 +00:00
address ,
2014-03-01 15:21:17 +00:00
( byte ) ( _domain . PeekByte ( address ) - 1 ) ) ;
2012-03-08 18:33:57 +00:00
break ;
2012-06-25 03:10:04 +00:00
case 2 :
2016-04-13 23:50:06 +00:00
_domain . PokeUshort (
2013-10-09 15:28:45 +00:00
address ,
2016-04-13 23:50:06 +00:00
( ushort ) ( _domain . PeekUshort ( address , BigEndian ) - 1 ) ,
2015-01-01 14:54:26 +00:00
BigEndian ) ;
2012-03-08 18:33:57 +00:00
break ;
case 4 :
2016-04-13 23:50:06 +00:00
_domain . PokeUint (
2013-10-09 15:28:45 +00:00
address ,
2016-04-13 23:50:06 +00:00
_domain . PeekUint ( address , BigEndian ) - 1 ,
2015-01-01 14:54:26 +00:00
BigEndian ) ;
2012-03-08 18:33:57 +00:00
break ;
}
}
}
2015-01-18 18:01:27 +00:00
private string ValueString ( long address )
2012-06-10 16:34:35 +00:00
{
2012-06-19 02:42:07 +00:00
if ( address ! = - 1 )
2012-06-10 16:34:35 +00:00
{
2014-01-30 03:10:17 +00:00
return string . Format ( _digitFormatString , MakeValue ( address ) ) . Trim ( ) ;
2012-06-10 16:34:35 +00:00
}
2014-03-01 15:21:17 +00:00
2017-05-10 11:45:23 +00:00
return "" ;
2012-06-10 16:34:35 +00:00
}
2012-06-23 18:45:01 +00:00
private string GetFindValues ( )
{
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2012-06-23 18:45:01 +00:00
{
2019-11-03 17:14:08 +00:00
var values = ValueString ( _highlightedAddress . Value ) ;
2013-11-28 14:43:27 +00:00
return _secondaryHighlightedAddresses . Aggregate ( values , ( current , x ) = > current + ValueString ( x ) ) ;
2013-04-14 23:56:45 +00:00
}
2014-03-01 15:21:17 +00:00
2017-05-10 11:45:23 +00:00
return "" ;
2012-06-23 18:45:01 +00:00
}
2015-01-18 18:01:27 +00:00
private void HighlightSecondaries ( string value , long found )
2012-06-23 18:45:01 +00:00
{
2013-11-28 22:06:38 +00:00
// This function assumes that the primary highlighted value has been set and sets the remaining characters in this string
2013-11-28 20:02:32 +00:00
_secondaryHighlightedAddresses . Clear ( ) ;
2012-06-23 18:45:01 +00:00
2015-01-01 14:54:26 +00:00
var addrLength = DataSize * 2 ;
2013-11-28 20:02:32 +00:00
if ( value . Length < = addrLength )
{
2012-06-23 18:45:01 +00:00
return ;
2013-11-28 20:02:32 +00:00
}
2013-11-28 22:06:38 +00:00
var numToHighlight = ( value . Length / addrLength ) - 1 ;
2012-06-23 18:45:01 +00:00
2015-01-01 14:54:26 +00:00
for ( var i = 0 ; i < numToHighlight ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
2015-01-01 14:54:26 +00:00
_secondaryHighlightedAddresses . Add ( found + DataSize + i ) ;
2013-11-28 20:02:32 +00:00
}
}
2012-06-23 18:45:01 +00:00
2014-03-23 20:27:20 +00:00
private bool LoadTable ( string path )
{
2018-06-23 16:29:06 +00:00
if ( string . IsNullOrWhiteSpace ( path ) )
{
return false ;
}
2014-03-23 20:27:20 +00:00
var file = new FileInfo ( path ) ;
if ( ! file . Exists )
{
return false ;
}
using ( var sr = file . OpenText ( ) )
{
string line ;
while ( ( line = sr . ReadLine ( ) ) ! = null )
{
var parts = line . Split ( '=' ) ;
_textTable . Add (
int . Parse ( parts [ 0 ] ,
NumberStyles . HexNumber ) , parts [ 1 ] . First ( ) ) ;
}
}
return true ;
}
2013-11-28 20:02:32 +00:00
#region Events
#region File Menu
private void FileSubMenu_DropDownOpened ( object sender , EventArgs e )
{
2014-02-10 01:15:11 +00:00
if ( _domain . Name = = "File on Disk" )
2012-06-23 18:45:01 +00:00
{
2013-11-28 20:02:32 +00:00
SaveMenuItem . Visible = ! CurrentRomIsArchive ( ) ;
SaveAsBinaryMenuItem . Text = "Save as ROM..." ;
2012-06-23 18:45:01 +00:00
}
2013-11-28 20:02:32 +00:00
else
2012-06-23 18:45:01 +00:00
{
2013-11-28 20:02:32 +00:00
SaveAsBinaryMenuItem . Text = "Save as binary..." ;
2012-06-23 18:45:01 +00:00
}
2014-03-23 22:47:28 +00:00
CloseTableFileMenuItem . Enabled = _textTable . Any ( ) ;
2013-11-28 20:02:32 +00:00
}
private void SaveMenuItem_Click ( object sender , EventArgs e )
{
if ( ! CurrentRomIsArchive ( ) )
2012-09-26 04:25:45 +00:00
{
2013-11-28 20:02:32 +00:00
SaveFileBinary ( GlobalWin . MainForm . CurrentlyOpenRom ) ;
2012-09-26 04:25:45 +00:00
}
2012-06-23 18:45:01 +00:00
}
2013-11-28 20:02:32 +00:00
private void SaveAsBinaryMenuItem_Click ( object sender , EventArgs e )
2012-06-23 18:45:01 +00:00
{
2014-02-10 01:01:36 +00:00
var path = GetBinarySaveFileFromUser ( ) ;
if ( ! string . IsNullOrEmpty ( path ) )
{
SaveFileBinary ( path ) ;
}
2013-11-28 20:02:32 +00:00
}
2017-03-01 21:06:58 +00:00
private void importAsBinaryToolStripMenuItem_Click ( object sender , EventArgs e )
{
if ( ! _domain . CanPoke ( ) )
{
MessageBox . Show ( "This Memory Domain can't be Poked; so importing can't work" ) ;
return ;
}
2019-11-02 04:29:09 +00:00
using var sfd = new OpenFileDialog
2017-03-01 21:06:58 +00:00
{
Filter = "Binary (*.bin)|*.bin|Save Files (*.sav)|*.sav|All Files|*.*" ,
RestoreDirectory = true ,
} ;
var result = sfd . ShowHawkDialog ( ) ;
2019-11-03 16:46:45 +00:00
if ( result ! = DialogResult . OK )
{
return ;
}
2017-03-01 21:06:58 +00:00
var path = sfd . FileName ;
2019-11-03 16:46:45 +00:00
using var inf = File . Open ( path , FileMode . Open , FileAccess . Read , FileShare . Read ) ;
long todo = Math . Min ( inf . Length , _domain . Size ) ;
for ( long i = 0 ; i < todo ; i + + )
2017-03-01 21:06:58 +00:00
{
2019-11-03 16:46:45 +00:00
_domain . PokeByte ( i , ( byte ) inf . ReadByte ( ) ) ;
2017-03-01 21:06:58 +00:00
}
}
2013-11-28 20:02:32 +00:00
private void SaveAsTextMenuItem_Click ( object sender , EventArgs e )
{
var path = GetSaveFileFromUser ( ) ;
2014-01-30 03:10:17 +00:00
if ( ! string . IsNullOrWhiteSpace ( path ) )
2013-11-28 20:02:32 +00:00
{
var file = new FileInfo ( path ) ;
2019-11-03 16:46:45 +00:00
using var sw = new StreamWriter ( file . FullName ) ;
var sb = new StringBuilder ( ) ;
2013-11-28 20:02:32 +00:00
2019-11-03 16:46:45 +00:00
for ( var i = 0 ; i < _domain . Size / 16 ; i + + )
{
for ( var j = 0 ; j < 16 ; j + + )
2013-11-28 20:02:32 +00:00
{
2019-11-03 16:46:45 +00:00
sb . Append ( $"{_domain.PeekByte((i * 16) + j):X2} " ) ;
2013-11-28 20:02:32 +00:00
}
2019-11-03 16:46:45 +00:00
sb . AppendLine ( ) ;
2013-11-28 20:02:32 +00:00
}
2019-11-03 16:46:45 +00:00
sw . WriteLine ( sb ) ;
2013-11-28 20:02:32 +00:00
}
}
2014-03-23 20:27:20 +00:00
private void LoadTableFileMenuItem_Click ( object sender , EventArgs e )
{
2019-11-03 16:46:45 +00:00
string initialDirectory = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . ToolsPathFragment , null ) ;
var romName = Global . Config . RecentRoms . MostRecent . Contains ( '|' )
? Global . Config . RecentRoms . MostRecent . Split ( '|' ) . Last ( )
: Global . Config . RecentRoms . MostRecent ;
2015-02-22 03:36:54 +00:00
2019-11-02 04:29:09 +00:00
using var ofd = new OpenFileDialog
2014-03-23 20:27:20 +00:00
{
2019-03-18 14:06:37 +00:00
FileName = $"{Path.GetFileNameWithoutExtension(romName)}.tbl" ,
2019-11-03 16:46:45 +00:00
InitialDirectory = initialDirectory ,
2014-03-23 20:27:20 +00:00
Filter = "Text Table files (*.tbl)|*.tbl|All Files|*.*" ,
RestoreDirectory = false
} ;
2015-02-22 03:36:54 +00:00
var result = ofd . ShowHawkDialog ( ) ;
2014-03-23 20:27:20 +00:00
if ( result = = DialogResult . OK )
{
LoadTable ( ofd . FileName ) ;
2015-01-01 14:54:26 +00:00
RecentTables . Add ( ofd . FileName ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2014-03-23 20:27:20 +00:00
}
}
2014-03-23 22:47:28 +00:00
private void CloseTableFileMenuItem_Click ( object sender , EventArgs e )
{
_textTable . Clear ( ) ;
}
2014-03-23 20:27:20 +00:00
public void LoadFileFromRecent ( string path )
{
var result = LoadTable ( path ) ;
if ( ! result )
{
2015-01-01 14:54:26 +00:00
RecentTables . HandleLoadError ( path ) ;
2014-03-23 20:27:20 +00:00
}
else
{
2015-01-01 14:54:26 +00:00
RecentTables . Add ( path ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2014-03-23 20:27:20 +00:00
}
}
private void RecentTablesSubMenu_DropDownOpened ( object sender , EventArgs e )
{
RecentTablesSubMenu . DropDownItems . Clear ( ) ;
RecentTablesSubMenu . DropDownItems . AddRange (
2015-01-01 14:54:26 +00:00
RecentTables . RecentMenu ( LoadFileFromRecent , true ) ) ;
2014-03-23 20:27:20 +00:00
}
2013-11-28 20:02:32 +00:00
private void ExitMenuItem_Click ( object sender , EventArgs e )
{
Close ( ) ;
}
#endregion
#region Edit
private void EditMenuItem_DropDownOpened ( object sender , EventArgs e )
{
2015-01-25 15:42:07 +00:00
var data = Clipboard . GetDataObject ( ) ;
PasteMenuItem . Enabled =
_domain . CanPoke ( ) & &
2019-11-03 17:14:08 +00:00
( _highlightedAddress . HasValue | | _secondaryHighlightedAddresses . Any ( ) ) & &
2015-01-25 15:42:07 +00:00
data ! = null & &
data . GetDataPresent ( DataFormats . Text ) ;
2014-01-30 03:10:17 +00:00
FindNextMenuItem . Enabled = ! string . IsNullOrWhiteSpace ( _findStr ) ;
2013-11-28 20:02:32 +00:00
}
2015-09-29 07:29:19 +00:00
string MakeCopyExportString ( bool export )
2013-11-28 20:02:32 +00:00
{
2019-11-03 16:46:45 +00:00
// make room for an array with _secondaryHighlightedAddresses and optionally HighlightedAddress
2019-11-03 17:14:08 +00:00
long [ ] addresses = new long [ _secondaryHighlightedAddresses . Count + ( _highlightedAddress . HasValue ? 1 : 0 ) ] ;
2015-09-29 07:29:19 +00:00
2019-11-03 16:46:45 +00:00
// if there was actually nothing to do, return
2015-09-29 07:29:19 +00:00
if ( addresses . Length = = 0 )
2019-11-03 16:46:45 +00:00
{
2015-09-29 07:29:19 +00:00
return null ;
2019-11-03 16:46:45 +00:00
}
2015-09-29 07:29:19 +00:00
2019-11-03 16:46:45 +00:00
// fill the array with _secondaryHighlightedAddresses
2015-09-29 07:29:19 +00:00
for ( int i = 0 ; i < _secondaryHighlightedAddresses . Count ; i + + )
2019-11-03 16:46:45 +00:00
{
2015-09-29 07:29:19 +00:00
addresses [ i ] = _secondaryHighlightedAddresses [ i ] ;
2019-11-03 16:46:45 +00:00
}
// and add HighlightedAddress if present
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2019-11-03 16:46:45 +00:00
{
2019-11-03 17:14:08 +00:00
addresses [ addresses . Length - 1 ] = _highlightedAddress . Value ;
2019-11-03 16:46:45 +00:00
}
2015-09-29 07:29:19 +00:00
2019-11-03 16:46:45 +00:00
// these need to be sorted. it's not just for HighlightedAddress, _secondaryHighlightedAddresses can even be jumbled
2015-09-29 07:29:19 +00:00
Array . Sort ( addresses ) ;
2019-11-03 16:46:45 +00:00
// find the maximum length of the exported string
2015-09-29 07:29:19 +00:00
int maximumLength = addresses . Length * ( export ? 3 : 2 ) + 8 ;
2019-11-03 16:46:45 +00:00
var sb = new StringBuilder ( maximumLength ) ;
2015-09-29 07:29:19 +00:00
2019-11-03 16:46:45 +00:00
// generate it differently for export (as you see it) or copy (raw bytes)
2015-09-29 07:29:19 +00:00
if ( export )
for ( int i = 0 ; i < addresses . Length ; i + + )
{
sb . Append ( ValueString ( addresses [ i ] ) ) ;
2019-11-03 18:46:39 +00:00
if ( i ! = addresses . Length - 1 )
{
2015-09-29 07:29:19 +00:00
sb . Append ( ' ' ) ;
2019-11-03 18:46:39 +00:00
}
2015-09-29 07:29:19 +00:00
}
else
2013-12-21 17:51:07 +00:00
{
2019-11-03 16:46:45 +00:00
foreach ( var addr in addresses )
2015-09-29 07:29:19 +00:00
{
2019-11-03 16:46:45 +00:00
long start = addr ;
long end = addr + DataSize - 1 ;
for ( long a = start ; a < = end ; a + + )
{
sb . AppendFormat ( "{0:X2}" , MakeValue ( 1 , a ) ) ;
}
2015-09-29 07:29:19 +00:00
}
2013-12-21 17:51:07 +00:00
}
2015-09-29 07:29:19 +00:00
return sb . ToString ( ) ;
}
private void ExportMenuItem_Click ( object sender , EventArgs e )
{
var value = MakeCopyExportString ( true ) ;
if ( ! string . IsNullOrEmpty ( value ) )
2019-11-03 16:46:45 +00:00
{
2015-09-29 07:29:19 +00:00
Clipboard . SetDataObject ( value ) ;
2019-11-03 16:46:45 +00:00
}
2015-09-29 07:29:19 +00:00
}
private void CopyMenuItem_Click ( object sender , EventArgs e )
{
var value = MakeCopyExportString ( false ) ;
if ( ! string . IsNullOrEmpty ( value ) )
2019-11-03 16:46:45 +00:00
{
2015-09-29 07:29:19 +00:00
Clipboard . SetDataObject ( value ) ;
2019-11-03 16:46:45 +00:00
}
2013-11-28 20:02:32 +00:00
}
private void PasteMenuItem_Click ( object sender , EventArgs e )
{
2013-12-21 17:51:07 +00:00
var data = Clipboard . GetDataObject ( ) ;
2019-11-03 16:46:45 +00:00
if ( data = = null | | ! data . GetDataPresent ( DataFormats . Text ) )
{
2015-09-29 07:29:19 +00:00
return ;
2019-11-03 16:46:45 +00:00
}
2015-09-29 07:29:19 +00:00
var clipboardRaw = ( string ) data . GetData ( DataFormats . Text ) ;
var hex = clipboardRaw . OnlyHex ( ) ;
2013-12-21 17:51:07 +00:00
2015-09-29 07:29:19 +00:00
var numBytes = hex . Length / 2 ;
for ( var i = 0 ; i < numBytes ; i + + )
{
var value = int . Parse ( hex . Substring ( i * 2 , 2 ) , NumberStyles . HexNumber ) ;
2019-11-03 17:14:08 +00:00
var address = ( _highlightedAddress ? ? 0 ) + i ;
2016-10-06 00:59:46 +00:00
if ( address < _domain . Size )
{
_domain . PokeByte ( address , ( byte ) value ) ;
}
2013-12-21 17:51:07 +00:00
}
2015-09-29 07:29:19 +00:00
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2017-05-28 15:13:34 +00:00
}
2019-11-03 16:46:45 +00:00
private bool _lastSearchWasText ;
2017-05-28 15:13:34 +00:00
private void SearchTypeChanged ( bool isText )
{
_lastSearchWasText = isText ;
}
2013-11-28 20:02:32 +00:00
private void FindMenuItem_Click ( object sender , EventArgs e )
{
_findStr = GetFindValues ( ) ;
if ( ! _hexFind . IsHandleCreated | | _hexFind . IsDisposed )
{
2015-01-31 01:16:41 +00:00
_hexFind = new HexFind
{
InitialLocation = PointToScreen ( AddressesLabel . Location ) ,
2017-05-28 15:13:34 +00:00
InitialValue = _findStr ,
SearchTypeChangedCallback = SearchTypeChanged ,
InitialText = _lastSearchWasText
2015-01-31 01:16:41 +00:00
} ;
2013-11-28 20:02:32 +00:00
_hexFind . Show ( ) ;
}
else
{
2015-01-31 01:16:41 +00:00
_hexFind . InitialValue = _findStr ;
2013-11-28 20:02:32 +00:00
_hexFind . Focus ( ) ;
}
}
private void FindNextMenuItem_Click ( object sender , EventArgs e )
{
FindNext ( _findStr , false ) ;
}
private void FindPrevMenuItem_Click ( object sender , EventArgs e )
{
FindPrev ( _findStr , false ) ;
}
#endregion
#region Options
private void OptionsSubMenu_DropDownOpened ( object sender , EventArgs e )
{
2015-01-01 14:54:26 +00:00
BigEndianMenuItem . Checked = BigEndian ;
DataSizeByteMenuItem . Checked = DataSize = = 1 ;
DataSizeWordMenuItem . Checked = DataSize = = 2 ;
DataSizeDWordMenuItem . Checked = DataSize = = 4 ;
2013-11-28 20:02:32 +00:00
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue & & IsFrozen ( _highlightedAddress . Value ) )
2013-11-28 20:02:32 +00:00
{
FreezeAddressMenuItem . Image = Properties . Resources . Unfreeze ;
FreezeAddressMenuItem . Text = "Un&freeze Address" ;
}
else
{
FreezeAddressMenuItem . Image = Properties . Resources . Freeze ;
FreezeAddressMenuItem . Text = "&Freeze Address" ;
}
AddToRamWatchMenuItem . Enabled =
2019-11-03 17:14:08 +00:00
_highlightedAddress . HasValue ;
2015-01-25 15:42:07 +00:00
PokeAddressMenuItem . Enabled =
FreezeAddressMenuItem . Enabled =
2019-11-03 17:14:08 +00:00
_highlightedAddress . HasValue & &
2015-01-25 15:42:07 +00:00
_domain . CanPoke ( ) ;
2013-11-28 20:02:32 +00:00
}
private void MemoryDomainsMenuItem_DropDownOpened ( object sender , EventArgs e )
{
2015-01-14 00:08:20 +00:00
MemoryDomainsMenuItem . DropDownItems . Clear ( ) ;
MemoryDomainsMenuItem . DropDownItems . AddRange (
MemoryDomains . MenuItems ( SetMemoryDomain , _domain . Name )
. ToArray ( ) ) ;
var romMenuItem = new ToolStripMenuItem
2013-11-28 20:02:32 +00:00
{
2015-01-14 00:08:20 +00:00
Text = _romDomain . Name ,
Checked = _domain . Name = = _romDomain . Name
} ;
MemoryDomainsMenuItem . DropDownItems . Add ( new ToolStripSeparator ( ) ) ;
MemoryDomainsMenuItem . DropDownItems . Add ( romMenuItem ) ;
romMenuItem . Click + = ( o , ev ) = > SetMemoryDomain ( _romDomain . Name ) ;
2013-11-28 20:02:32 +00:00
}
private void DataSizeByteMenuItem_Click ( object sender , EventArgs e )
{
SetDataSize ( 1 ) ;
}
private void DataSizeWordMenuItem_Click ( object sender , EventArgs e )
{
SetDataSize ( 2 ) ;
}
private void DataSizeDWordMenuItem_Click ( object sender , EventArgs e )
{
SetDataSize ( 4 ) ;
}
private void BigEndianMenuItem_Click ( object sender , EventArgs e )
{
2019-11-03 16:58:41 +00:00
BigEndian ^ = true ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2013-11-28 20:02:32 +00:00
}
private void GoToAddressMenuItem_Click ( object sender , EventArgs e )
{
2019-11-02 04:29:09 +00:00
using var inputPrompt = new InputPrompt
2014-07-28 02:31:51 +00:00
{
Text = "Go to Address" ,
2014-07-28 02:40:30 +00:00
StartLocation = this . ChildPointToScreen ( MemoryViewerBox ) ,
Message = "Enter a hexadecimal value"
2014-07-28 02:31:51 +00:00
} ;
2014-07-28 02:40:30 +00:00
2014-07-15 23:43:17 +00:00
var result = inputPrompt . ShowHawkDialog ( ) ;
2013-11-28 20:02:32 +00:00
2014-07-28 02:40:30 +00:00
if ( result = = DialogResult . OK & & inputPrompt . PromptText . IsHex ( ) )
2013-11-28 20:02:32 +00:00
{
2015-01-18 18:01:27 +00:00
GoToAddress ( long . Parse ( inputPrompt . PromptText , NumberStyles . HexNumber ) ) ;
2013-11-28 20:02:32 +00:00
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
AddressLabel . Text = GenerateAddressString ( ) ;
}
private void AddToRamWatchMenuItem_Click ( object sender , EventArgs e )
{
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue | | _secondaryHighlightedAddresses . Any ( ) )
2013-11-28 20:02:32 +00:00
{
GlobalWin . Tools . LoadRamWatch ( true ) ;
}
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2013-11-28 20:02:32 +00:00
{
2019-11-03 17:14:08 +00:00
GlobalWin . Tools . RamWatch . AddWatch ( MakeWatch ( _highlightedAddress . Value ) ) ;
2013-11-28 20:02:32 +00:00
}
_secondaryHighlightedAddresses . ForEach ( addr = >
2014-03-01 15:21:17 +00:00
GlobalWin . Tools . RamWatch . AddWatch ( MakeWatch ( addr ) ) ) ;
2013-11-28 20:02:32 +00:00
}
private void FreezeAddressMenuItem_Click ( object sender , EventArgs e )
{
2015-01-25 15:42:07 +00:00
if ( ! _domain . CanPoke ( ) )
{
return ;
}
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2013-11-28 20:02:32 +00:00
{
2019-11-03 17:53:52 +00:00
var highlighted = _highlightedAddress . Value ;
if ( IsFrozen ( highlighted ) )
2013-11-28 20:02:32 +00:00
{
2019-11-03 17:53:52 +00:00
UnFreezeAddress ( highlighted ) ;
2014-03-01 18:04:21 +00:00
UnfreezeSecondaries ( ) ;
2013-11-28 20:02:32 +00:00
}
else
{
2019-11-03 17:53:52 +00:00
FreezeAddress ( highlighted ) ;
2014-03-01 18:04:21 +00:00
FreezeSecondaries ( ) ;
2013-11-28 20:02:32 +00:00
}
}
2016-01-31 01:24:30 +00:00
UpdateCheatRelatedTools ( null , null ) ;
2014-03-01 18:09:09 +00:00
MemoryViewerBox . Refresh ( ) ;
2013-11-28 20:02:32 +00:00
}
private void UnfreezeAllMenuItem_Click ( object sender , EventArgs e )
{
2014-03-23 13:21:48 +00:00
Global . CheatList . RemoveAll ( ) ;
2013-11-28 20:02:32 +00:00
}
private void PokeAddressMenuItem_Click ( object sender , EventArgs e )
{
2015-01-25 15:42:07 +00:00
if ( ! _domain . CanPoke ( ) )
{
return ;
}
2015-01-18 18:01:27 +00:00
var addresses = new List < long > ( ) ;
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2013-11-28 20:02:32 +00:00
{
2019-11-03 17:14:08 +00:00
addresses . Add ( _highlightedAddress . Value ) ;
2013-11-28 20:02:32 +00:00
}
if ( _secondaryHighlightedAddresses . Any ( ) )
{
addresses . AddRange ( _secondaryHighlightedAddresses ) ;
}
if ( addresses . Any ( ) )
{
2019-11-02 04:29:09 +00:00
using var poke = new RamPoke
2013-11-28 20:02:32 +00:00
{
2015-01-19 01:49:56 +00:00
InitialLocation = this . ChildPointToScreen ( AddressLabel ) ,
2015-01-19 01:39:47 +00:00
ParentTool = this
2013-11-28 20:02:32 +00:00
} ;
2013-11-28 22:06:38 +00:00
var watches = addresses . Select (
address = > Watch . GenerateWatch (
_domain ,
2015-01-19 02:42:58 +00:00
address ,
2015-11-28 21:47:16 +00:00
( WatchSize ) DataSize ,
2019-11-03 16:46:45 +00:00
Common . DisplayType . Hex ,
2015-01-01 14:54:26 +00:00
BigEndian ) ) ;
2013-11-28 20:02:32 +00:00
2013-11-28 22:06:38 +00:00
poke . SetWatch ( watches ) ;
2013-11-28 22:39:00 +00:00
poke . ShowHawkDialog ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2013-11-28 20:02:32 +00:00
}
}
#endregion
#region Settings Menu
private void SetColorsMenuItem_Click ( object sender , EventArgs e )
{
2019-11-02 04:29:09 +00:00
using var form = new HexColorsForm ( ) ;
form . ShowHawkDialog ( ) ;
2013-11-28 20:02:32 +00:00
}
private void ResetColorsToDefaultMenuItem_Click ( object sender , EventArgs e )
{
MemoryViewerBox . BackColor = Color . FromName ( "Control" ) ;
MemoryViewerBox . ForeColor = Color . FromName ( "ControlText" ) ;
2013-11-28 22:06:38 +00:00
this . HexMenuStrip . BackColor = Color . FromName ( "Control" ) ;
2013-11-28 20:02:32 +00:00
Header . BackColor = Color . FromName ( "Control" ) ;
Header . ForeColor = Color . FromName ( "ControlText" ) ;
Global . Config . HexMenubarColor = Color . FromName ( "Control" ) ;
Global . Config . HexForegrndColor = Color . FromName ( "ControlText" ) ;
Global . Config . HexBackgrndColor = Color . FromName ( "Control" ) ;
Global . Config . HexFreezeColor = Color . LightBlue ;
Global . Config . HexHighlightColor = Color . Pink ;
Global . Config . HexHighlightFreezeColor = Color . Violet ;
}
#endregion
#region Context Menu and Dialog Events
private void HexEditor_Resize ( object sender , EventArgs e )
{
SetUpScrollBar ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2013-11-28 20:02:32 +00:00
}
private void HexEditor_ResizeEnd ( object sender , EventArgs e )
{
SetUpScrollBar ( ) ;
}
private void HexEditor_KeyDown ( object sender , KeyEventArgs e )
{
if ( e . Control & & e . KeyCode = = Keys . G )
{
GoToAddressMenuItem_Click ( sender , e ) ;
return ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
if ( e . Control & & e . KeyCode = = Keys . P )
{
PokeAddressMenuItem_Click ( sender , e ) ;
return ;
}
2019-11-03 17:18:23 +00:00
long currentAddress = _highlightedAddress ? ? - 1 ;
2015-01-18 18:01:27 +00:00
long newHighlighted ;
2013-11-28 20:02:32 +00:00
switch ( e . KeyCode )
{
case Keys . Up :
2019-11-03 17:18:23 +00:00
newHighlighted = currentAddress - 16 ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
for ( var i = newHighlighted + DataSize ; i < = currentAddress ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
AddToSecondaryHighlights ( i ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . Down :
2019-11-03 17:18:23 +00:00
newHighlighted = currentAddress + 16 ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
for ( var i = currentAddress ; i < newHighlighted ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
AddToSecondaryHighlights ( i ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . Left :
2019-11-03 17:18:23 +00:00
newHighlighted = currentAddress - ( 1 * DataSize ) ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
AddToSecondaryHighlights ( currentAddress ) ;
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . Right :
2019-11-03 17:18:23 +00:00
newHighlighted = currentAddress + ( 1 * DataSize ) ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
AddToSecondaryHighlights ( currentAddress ) ;
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . PageUp :
2019-11-03 17:18:23 +00:00
newHighlighted = currentAddress - ( _rowsVisible * 16 ) ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
for ( var i = newHighlighted + 1 ; i < = currentAddress ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
AddToSecondaryHighlights ( i ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . PageDown :
2019-11-03 17:18:23 +00:00
newHighlighted = currentAddress + ( _rowsVisible * 16 ) ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
for ( var i = currentAddress + 1 ; i < newHighlighted ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
AddToSecondaryHighlights ( i ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . Tab :
_secondaryHighlightedAddresses . Clear ( ) ;
if ( e . Modifiers = = Keys . Shift )
2013-11-28 22:06:38 +00:00
{
2019-11-03 17:18:23 +00:00
GoToAddress ( currentAddress - 8 ) ;
2013-11-28 22:06:38 +00:00
}
2013-11-28 20:02:32 +00:00
else
2013-11-28 22:06:38 +00:00
{
2019-11-03 17:18:23 +00:00
GoToAddress ( currentAddress + 8 ) ;
2013-11-28 22:06:38 +00:00
}
2013-11-28 20:02:32 +00:00
break ;
case Keys . Home :
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
for ( var i = 1 ; i < = currentAddress ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
AddToSecondaryHighlights ( i ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
GoToAddress ( 0 ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( 0 ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . End :
2015-01-18 18:59:23 +00:00
newHighlighted = _domain . Size - DataSize ;
2013-11-28 20:02:32 +00:00
if ( e . Modifiers = = Keys . Shift )
{
2019-11-03 17:18:23 +00:00
for ( var i = currentAddress ; i < newHighlighted ; i + = DataSize )
2013-11-28 20:02:32 +00:00
{
AddToSecondaryHighlights ( i ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
GoToAddress ( newHighlighted ) ;
}
else
{
_secondaryHighlightedAddresses . Clear ( ) ;
GoToAddress ( newHighlighted ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . Add :
IncrementContextItem_Click ( sender , e ) ;
break ;
case Keys . Subtract :
DecrementContextItem_Click ( sender , e ) ;
break ;
case Keys . Space :
FreezeAddressMenuItem_Click ( sender , e ) ;
break ;
case Keys . Delete :
if ( e . Modifiers = = Keys . Shift )
{
2014-03-23 13:21:48 +00:00
Global . CheatList . RemoveAll ( ) ;
2013-11-28 20:02:32 +00:00
}
else
{
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2013-11-28 20:02:32 +00:00
{
2019-11-03 17:14:08 +00:00
UnFreezeAddress ( _highlightedAddress . Value ) ;
2013-11-28 20:02:32 +00:00
}
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . W :
if ( e . Modifiers = = Keys . Control )
{
AddToRamWatchMenuItem_Click ( sender , e ) ;
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
break ;
case Keys . Escape :
_secondaryHighlightedAddresses . Clear ( ) ;
ClearHighlighted ( ) ;
break ;
}
}
2014-01-31 04:26:39 +00:00
private void HexEditor_KeyPress ( object sender , KeyPressEventArgs e )
2013-11-28 20:02:32 +00:00
{
2014-01-31 04:26:39 +00:00
if ( ! IsHexKeyCode ( e . KeyChar ) )
2013-11-28 20:02:32 +00:00
{
e . Handled = true ;
return ;
}
2014-05-04 14:10:28 +00:00
if ( ( ModifierKeys & ( Keys . Control | Keys . Shift | Keys . Alt ) ) ! = 0 )
2013-11-28 20:02:32 +00:00
{
return ;
}
2019-11-03 18:25:36 +00:00
if ( ! _domain . CanPoke ( ) | | ! _highlightedAddress . HasValue )
2019-11-03 17:20:50 +00:00
{
return ;
}
var currentAddress = _highlightedAddress ? ? 0 ;
2019-11-03 17:56:02 +00:00
_nibbles . Add ( e . KeyChar ) ;
2019-11-03 18:25:36 +00:00
if ( _nibbles . Count = = DataSize * 2 )
2013-11-28 20:02:32 +00:00
{
2019-11-03 18:25:36 +00:00
var nibbleStr = MakeNibbles ( ) ;
switch ( DataSize )
{
default :
case 1 :
var byteVal = byte . Parse ( nibbleStr , NumberStyles . HexNumber ) ;
_domain . PokeByte ( currentAddress , byteVal ) ;
break ;
case 2 :
var ushortVal = ushort . Parse ( nibbleStr , NumberStyles . HexNumber ) ;
_domain . PokeUshort ( currentAddress , ushortVal , ! BigEndian ) ; // TODO: is this method backwards?
break ;
case 4 :
var uintVal = uint . Parse ( nibbleStr , NumberStyles . HexNumber ) ;
_domain . PokeUint ( currentAddress , uintVal , ! BigEndian ) ; // TODO: is this method backwards?
break ;
}
2013-11-28 22:06:38 +00:00
2019-11-03 18:25:36 +00:00
ClearNibbles ( ) ;
SetHighlighted ( currentAddress + DataSize ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2019-11-03 18:25:36 +00:00
Refresh ( ) ;
2012-09-26 04:25:45 +00:00
}
2013-11-28 22:06:38 +00:00
2019-11-03 17:31:53 +00:00
UpdateGroupBoxTitle ( ) ;
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2012-06-23 18:45:01 +00:00
}
2013-12-21 17:51:07 +00:00
private void ViewerContextMenuStrip_Opening ( object sender , CancelEventArgs e )
{
var data = Clipboard . GetDataObject ( ) ;
CopyContextItem . Visible =
AddToRamWatchContextItem . Visible =
2019-11-03 17:14:08 +00:00
_highlightedAddress . HasValue | | _secondaryHighlightedAddresses . Any ( ) ;
2015-01-25 15:42:07 +00:00
FreezeContextItem . Visible =
2013-12-21 17:51:07 +00:00
PokeContextItem . Visible =
IncrementContextItem . Visible =
DecrementContextItem . Visible =
ContextSeparator2 . Visible =
2019-11-03 17:14:08 +00:00
( _highlightedAddress . HasValue | | _secondaryHighlightedAddresses . Any ( ) ) & &
2015-01-25 15:42:07 +00:00
_domain . CanPoke ( ) ;
2013-12-21 17:51:07 +00:00
UnfreezeAllContextItem . Visible = Global . CheatList . ActiveCount > 0 ;
2015-01-25 15:42:07 +00:00
PasteContextItem . Visible = _domain . CanPoke ( ) & & data ! = null & & data . GetDataPresent ( DataFormats . Text ) ;
2013-12-21 17:51:07 +00:00
ContextSeparator1 . Visible =
2019-11-03 17:14:08 +00:00
_highlightedAddress . HasValue | |
2013-12-21 17:51:07 +00:00
_secondaryHighlightedAddresses . Any ( ) | |
( data ! = null & & data . GetDataPresent ( DataFormats . Text ) ) ;
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue & & IsFrozen ( _highlightedAddress . Value ) )
2013-12-21 17:51:07 +00:00
{
FreezeContextItem . Text = "Un&freeze" ;
FreezeContextItem . Image = Properties . Resources . Unfreeze ;
}
else
{
FreezeContextItem . Text = "&Freeze" ;
FreezeContextItem . Image = Properties . Resources . Freeze ;
}
2015-01-22 01:15:06 +00:00
2015-01-25 15:42:07 +00:00
toolStripMenuItem1 . Visible = viewN64MatrixToolStripMenuItem . Visible = DataSize = = 4 ;
2013-12-21 17:51:07 +00:00
}
2013-11-28 20:02:32 +00:00
private void IncrementContextItem_Click ( object sender , EventArgs e )
2012-06-23 18:45:01 +00:00
{
2015-01-25 15:42:07 +00:00
if ( ! _domain . CanPoke ( ) )
{
return ;
}
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2012-06-23 18:45:01 +00:00
{
2019-11-03 17:14:08 +00:00
IncrementAddress ( _highlightedAddress . Value ) ;
2012-06-23 18:45:01 +00:00
}
2013-11-28 20:02:32 +00:00
_secondaryHighlightedAddresses . ForEach ( IncrementAddress ) ;
2013-10-09 15:28:45 +00:00
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2012-06-23 18:45:01 +00:00
}
2013-11-28 20:02:32 +00:00
private void DecrementContextItem_Click ( object sender , EventArgs e )
2012-06-10 16:34:35 +00:00
{
2015-01-25 15:42:07 +00:00
if ( ! _domain . CanPoke ( ) )
{
return ;
}
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue )
2012-06-10 16:34:35 +00:00
{
2019-11-03 17:14:08 +00:00
DecrementAddress ( _highlightedAddress . Value ) ;
2012-06-10 16:34:35 +00:00
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
_secondaryHighlightedAddresses . ForEach ( DecrementAddress ) ;
2012-06-10 16:34:35 +00:00
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2012-06-19 02:42:07 +00:00
}
2013-11-28 20:02:32 +00:00
#endregion
2012-06-10 16:34:35 +00:00
2013-11-28 20:02:32 +00:00
#region MemoryViewer Events
2012-06-19 02:42:07 +00:00
2013-11-28 20:02:32 +00:00
private void HexEditor_MouseWheel ( object sender , MouseEventArgs e )
{
var delta = 0 ;
if ( e . Delta > 0 )
{
delta = - 1 ;
2012-06-10 16:34:35 +00:00
}
2013-11-28 20:02:32 +00:00
else if ( e . Delta < 0 )
2012-06-10 16:34:35 +00:00
{
2013-11-28 20:02:32 +00:00
delta = 1 ;
2012-06-10 16:34:35 +00:00
}
2013-11-28 20:02:32 +00:00
var newValue = HexScrollBar . Value + delta ;
2013-11-28 22:06:38 +00:00
if ( newValue < HexScrollBar . Minimum )
{
newValue = HexScrollBar . Minimum ;
}
if ( newValue > HexScrollBar . Maximum - HexScrollBar . LargeChange + 1 )
{
newValue = HexScrollBar . Maximum - HexScrollBar . LargeChange + 1 ;
}
2013-11-28 20:02:32 +00:00
if ( newValue ! = HexScrollBar . Value )
{
HexScrollBar . Value = newValue ;
MemoryViewerBox . Refresh ( ) ;
}
2012-06-19 02:42:07 +00:00
}
2019-11-03 16:46:45 +00:00
private readonly Pen _blackPen = new Pen ( Color . Black ) ;
private readonly SolidBrush _freezeBrush = new SolidBrush ( Global . Config . HexFreezeColor ) ;
private readonly SolidBrush _freezeHighlightBrush = new SolidBrush ( Global . Config . HexHighlightFreezeColor ) ;
private readonly SolidBrush _highlightBrush = new SolidBrush ( Global . Config . HexHighlightColor ) ;
private readonly SolidBrush _secondaryHighlightBrush = new SolidBrush ( Color . FromArgb ( 0x44 , Global . Config . HexHighlightColor ) ) ;
2019-10-26 20:08:54 +00:00
2013-11-28 20:02:32 +00:00
private void MemoryViewerBox_Paint ( object sender , PaintEventArgs e )
2012-06-10 16:34:35 +00:00
{
2013-11-28 20:02:32 +00:00
var activeCheats = Global . CheatList . Where ( x = > x . Enabled ) ;
foreach ( var cheat in activeCheats )
{
if ( IsVisible ( cheat . Address ? ? 0 ) )
{
if ( _domain . ToString ( ) = = cheat . Domain . Name )
{
2019-11-03 18:46:39 +00:00
var gaps = ( int ) cheat . Size - DataSize ;
2014-07-28 01:01:32 +00:00
2015-11-28 21:47:16 +00:00
if ( cheat . Size = = WatchSize . DWord & & DataSize = = 2 )
2014-07-28 01:01:32 +00:00
{
gaps - = 1 ;
}
if ( gaps < 0 ) { gaps = 0 ; }
2019-11-03 16:46:45 +00:00
var width = ( _fontWidth * 2 * ( int ) cheat . Size ) + ( gaps * _fontWidth ) ;
2014-07-28 01:01:32 +00:00
2019-11-03 16:46:45 +00:00
var rect = new Rectangle ( GetAddressCoordinates ( cheat . Address ? ? 0 ) , new Size ( width , _fontHeight ) ) ;
2019-10-26 20:08:54 +00:00
e . Graphics . DrawRectangle ( _blackPen , rect ) ;
_freezeBrush . Color = Global . Config . HexFreezeColor ;
e . Graphics . FillRectangle ( _freezeBrush , rect ) ;
2013-11-28 20:02:32 +00:00
}
}
}
2012-06-10 16:34:35 +00:00
2019-11-03 17:14:08 +00:00
if ( _highlightedAddress . HasValue & & IsVisible ( _highlightedAddress . Value ) )
2013-11-28 20:02:32 +00:00
{
2019-11-03 17:14:08 +00:00
long addressHighlighted = _highlightedAddress ? ? 0 ;
2019-11-03 18:46:39 +00:00
2014-09-13 16:18:36 +00:00
// Create a slight offset to increase rectangle sizes
2019-11-03 17:14:08 +00:00
var point = GetAddressCoordinates ( addressHighlighted ) ;
var textX = ( int ) GetTextX ( addressHighlighted ) ;
2019-11-03 16:46:45 +00:00
var textPoint = new Point ( textX , point . Y ) ;
2012-06-10 22:43:43 +00:00
2019-11-03 17:14:08 +00:00
var rect = new Rectangle ( point , new Size ( _fontWidth * 2 * DataSize + ( NeedsExtra ( addressHighlighted ) ? _fontWidth : 0 ) + 2 , _fontHeight ) ) ;
2019-10-26 20:08:54 +00:00
e . Graphics . DrawRectangle ( _blackPen , rect ) ;
2012-06-10 22:43:43 +00:00
2019-11-03 16:46:45 +00:00
var textRect = new Rectangle ( textPoint , new Size ( _fontWidth * DataSize , _fontHeight ) ) ;
2012-06-19 02:42:07 +00:00
2019-11-03 17:14:08 +00:00
if ( Global . CheatList . IsActive ( _domain , addressHighlighted ) )
2013-11-28 20:02:32 +00:00
{
2019-10-26 20:08:54 +00:00
_freezeHighlightBrush . Color = Global . Config . HexHighlightFreezeColor ;
e . Graphics . FillRectangle ( _freezeHighlightBrush , rect ) ;
2019-11-03 16:46:45 +00:00
e . Graphics . FillRectangle ( _freezeHighlightBrush , textRect ) ;
2013-11-28 20:02:32 +00:00
}
else
{
2019-10-26 20:08:54 +00:00
_highlightBrush . Color = Global . Config . HexHighlightColor ;
e . Graphics . FillRectangle ( _highlightBrush , rect ) ;
2019-11-03 16:46:45 +00:00
e . Graphics . FillRectangle ( _highlightBrush , textRect ) ;
2013-11-28 20:02:32 +00:00
}
}
2013-11-28 22:06:38 +00:00
2013-11-28 20:02:32 +00:00
foreach ( var address in _secondaryHighlightedAddresses )
{
2015-01-19 01:49:56 +00:00
if ( IsVisible ( address ) )
{
var point = GetAddressCoordinates ( address ) ;
var textX = ( int ) GetTextX ( address ) ;
2019-11-03 16:46:45 +00:00
var textPoint = new Point ( textX , point . Y ) ;
2012-06-19 02:42:07 +00:00
2019-11-03 16:46:45 +00:00
var rect = new Rectangle ( point , new Size ( _fontWidth * 2 * DataSize + 2 , _fontHeight ) ) ;
2019-10-26 20:08:54 +00:00
e . Graphics . DrawRectangle ( _blackPen , rect ) ;
2012-06-23 18:45:01 +00:00
2019-11-03 16:46:45 +00:00
var textRect = new Rectangle ( textPoint , new Size ( _fontWidth * DataSize , _fontHeight ) ) ;
2012-06-23 18:45:01 +00:00
2015-01-19 02:42:58 +00:00
if ( Global . CheatList . IsActive ( _domain , address ) )
2015-01-19 01:49:56 +00:00
{
2019-10-26 20:08:54 +00:00
_freezeHighlightBrush . Color = Global . Config . HexHighlightFreezeColor ;
e . Graphics . FillRectangle ( _freezeHighlightBrush , rect ) ;
2019-11-03 16:46:45 +00:00
e . Graphics . FillRectangle ( _freezeHighlightBrush , textRect ) ;
2015-01-19 01:49:56 +00:00
}
else
{
2019-10-26 20:08:54 +00:00
_secondaryHighlightBrush . Color = Color . FromArgb ( 0x44 , Global . Config . HexHighlightColor ) ;
e . Graphics . FillRectangle ( _secondaryHighlightBrush , rect ) ;
2019-11-03 16:46:45 +00:00
e . Graphics . FillRectangle ( _secondaryHighlightBrush , textRect ) ;
2015-01-19 01:49:56 +00:00
}
2013-11-28 20:02:32 +00:00
}
}
2012-06-23 18:45:01 +00:00
}
2013-11-28 20:02:32 +00:00
private void AddressesLabel_MouseUp ( object sender , MouseEventArgs e )
2012-06-23 18:45:01 +00:00
{
2013-11-28 20:02:32 +00:00
_mouseIsDown = false ;
2012-06-23 18:45:01 +00:00
}
2012-09-02 23:12:00 +00:00
2013-11-28 20:02:32 +00:00
private void AddressesLabel_MouseMove ( object sender , MouseEventArgs e )
2012-09-14 21:31:00 +00:00
{
2013-11-28 20:02:32 +00:00
_addressOver = GetPointedAddress ( e . X , e . Y ) ;
2012-09-14 21:31:00 +00:00
2013-11-28 20:02:32 +00:00
if ( _mouseIsDown )
{
DoShiftClick ( ) ;
2015-12-20 19:51:07 +00:00
UpdateFormText ( ) ;
2013-11-28 20:02:32 +00:00
MemoryViewerBox . Refresh ( ) ;
}
2012-09-14 21:31:00 +00:00
}
2012-09-21 06:33:57 +00:00
2013-11-28 20:02:32 +00:00
private void AddressesLabel_MouseLeave ( object sender , EventArgs e )
2012-09-21 06:33:57 +00:00
{
2013-11-28 20:02:32 +00:00
_addressOver = - 1 ;
MemoryViewerBox . Refresh ( ) ;
2012-09-21 06:33:57 +00:00
}
2012-09-29 21:13:11 +00:00
private void AddressesLabel_MouseDown ( object sender , MouseEventArgs e )
{
2012-10-15 00:56:47 +00:00
if ( e . Button = = MouseButtons . Left )
2012-09-29 21:13:11 +00:00
{
2015-01-18 20:15:03 +00:00
var pointedAddress = GetPointedAddress ( e . X , e . Y ) ;
if ( pointedAddress > = 0 )
2012-09-29 21:13:11 +00:00
{
2013-04-14 23:56:45 +00:00
if ( ( ModifierKeys & Keys . Control ) = = Keys . Control )
2012-09-29 21:13:11 +00:00
{
2019-11-03 17:14:08 +00:00
if ( pointedAddress = = _highlightedAddress )
2012-10-15 00:56:47 +00:00
{
ClearHighlighted ( ) ;
}
2015-01-18 20:15:03 +00:00
else if ( _secondaryHighlightedAddresses . Contains ( pointedAddress ) )
2012-10-15 00:56:47 +00:00
{
2015-01-18 20:15:03 +00:00
_secondaryHighlightedAddresses . Remove ( pointedAddress ) ;
2012-10-15 00:56:47 +00:00
}
else
{
2015-01-18 20:15:03 +00:00
_secondaryHighlightedAddresses . Add ( pointedAddress ) ;
2012-10-15 00:56:47 +00:00
}
2012-09-29 21:13:11 +00:00
}
2013-04-14 23:56:45 +00:00
else if ( ( ModifierKeys & Keys . Shift ) = = Keys . Shift )
2012-09-29 21:13:11 +00:00
{
2012-10-15 00:56:47 +00:00
DoShiftClick ( ) ;
2012-09-29 21:13:11 +00:00
}
else
{
2013-11-28 14:43:27 +00:00
_secondaryHighlightedAddresses . Clear ( ) ;
2017-05-10 11:45:23 +00:00
_findStr = "" ;
2016-10-06 00:31:30 +00:00
SetHighlighted ( pointedAddress ) ;
2012-09-29 21:13:11 +00:00
}
2012-10-15 00:56:47 +00:00
MemoryViewerBox . Refresh ( ) ;
2012-09-29 21:13:11 +00:00
}
2013-11-28 14:43:27 +00:00
_mouseIsDown = true ;
2012-09-29 21:13:11 +00:00
}
}
2012-09-21 06:33:57 +00:00
2019-11-03 18:46:39 +00:00
private bool _programmaticallyChangingValue ;
2013-11-28 20:02:32 +00:00
private void HexScrollBar_ValueChanged ( object sender , EventArgs e )
2013-11-28 14:58:15 +00:00
{
2014-09-13 13:50:29 +00:00
if ( ! _programmaticallyChangingValue )
{
if ( HexScrollBar . Value < 0 )
{
_programmaticallyChangingValue = true ;
HexScrollBar . Value = 0 ;
_programmaticallyChangingValue = false ;
}
2019-12-07 18:59:01 +00:00
FullUpdate ( ) ;
2014-09-13 13:50:29 +00:00
}
2013-11-28 14:58:15 +00:00
}
#endregion
2013-11-28 20:02:32 +00:00
2013-11-28 14:58:15 +00:00
#endregion
2015-01-22 01:15:06 +00:00
private void viewN64MatrixToolStripMenuItem_Click ( object sender , EventArgs e )
{
2019-11-03 17:14:08 +00:00
if ( ! _highlightedAddress . HasValue )
2019-11-03 18:46:39 +00:00
{
2015-01-22 01:15:06 +00:00
return ;
2019-11-03 18:46:39 +00:00
}
2015-01-22 01:15:06 +00:00
2019-11-03 16:46:45 +00:00
bool bigEndian = true ;
2019-11-03 17:14:08 +00:00
long addr = _highlightedAddress . Value ;
2019-11-03 16:46:45 +00:00
//ushort = _domain.PeekWord(addr, bigEndian);
2015-01-22 01:15:06 +00:00
float [ , ] matVals = new float [ 4 , 4 ] ;
2015-01-25 13:24:18 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
for ( int j = 0 ; j < 4 ; j + + )
{
2019-11-03 16:46:45 +00:00
ushort hi = _domain . PeekUshort ( ( ( addr + ( i < < 3 ) + ( j < < 1 ) ) ^ 0x0 ) , bigEndian ) ;
ushort lo = _domain . PeekUshort ( ( ( addr + ( i < < 3 ) + ( j < < 1 ) + 32 ) ^ 0x0 ) , bigEndian ) ;
2015-01-25 13:24:18 +00:00
matVals [ i , j ] = ( int ) ( ( ( hi < < 16 ) | lo ) ) / 65536.0f ;
}
2015-01-22 01:15:06 +00:00
}
2019-11-03 16:46:45 +00:00
// if needed
////var mat = new SlimDX.Matrix();
////mat.M11 = matVals[0, 0]; mat.M12 = matVals[0, 1]; mat.M13 = matVals[0, 2]; mat.M14 = matVals[0, 3];
////mat.M21 = matVals[1, 0]; mat.M22 = matVals[1, 1]; mat.M23 = matVals[1, 2]; mat.M24 = matVals[1, 3];
////mat.M31 = matVals[2, 0]; mat.M32 = matVals[2, 1]; mat.M33 = matVals[2, 2]; mat.M34 = matVals[2, 3];
////mat.M41 = matVals[3, 0]; mat.M42 = matVals[3, 1]; mat.M43 = matVals[3, 2]; mat.M44 = matVals[3, 3];
////MessageBox.Show(mat.ToString());
2015-01-22 01:15:06 +00:00
2019-11-02 04:29:09 +00:00
using var sw = new StringWriter ( ) ;
2019-11-03 16:46:45 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
sw . WriteLine ( "{0,18:0.00000} {1,18:0.00000} {2,18:0.00000} {3,18:0.00000}" , matVals [ i , 0 ] , matVals [ i , 1 ] , matVals [ i , 2 ] , matVals [ i , 3 ] ) ;
}
2015-01-22 01:15:06 +00:00
var str = sw . ToString ( ) ;
MessageBox . Show ( str ) ;
}
2011-06-19 23:39:25 +00:00
}
2012-06-25 03:10:04 +00:00
}