2013-09-14 19:07:11 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2013-11-04 01:39:19 +00:00
2013-10-27 07:54:00 +00:00
using BizHawk.Common ;
2014-07-03 18:43:49 +00:00
using BizHawk.Common.CollectionExtensions ;
2013-11-04 01:39:19 +00:00
using BizHawk.Emulation.Common ;
2014-12-05 00:32:29 +00:00
using BizHawk.Emulation.Common.IEmulatorExtensions ;
2013-10-25 00:57:23 +00:00
2013-10-27 07:54:00 +00:00
namespace BizHawk.Client.Common
2013-09-14 19:07:11 +00:00
{
2013-09-25 04:07:41 +00:00
public class RamSearchEngine
2013-09-14 19:07:11 +00:00
{
2013-12-30 01:17:11 +00:00
public enum ComparisonOperator { Equal , GreaterThan , GreaterThanEqual , LessThan , LessThanEqual , NotEqual , DifferentBy }
2013-09-21 23:55:17 +00:00
public enum Compare { Previous , SpecificValue , SpecificAddress , Changes , Difference }
2013-09-29 18:19:47 +00:00
2014-09-07 06:17:10 +00:00
private int? _differentBy ; //zero 07-sep-2014 - this isnt ideal. but dont bother changing it (to a long, for instance) until it can support floats. maybe store it as a double here.
2013-09-29 18:19:47 +00:00
private Compare _compareTo = Compare . Previous ;
2013-10-27 17:47:54 +00:00
private long? _compareValue ;
2013-09-29 18:19:47 +00:00
private ComparisonOperator _operator = ComparisonOperator . Equal ;
2013-09-21 14:09:37 +00:00
2013-09-25 04:07:41 +00:00
private List < IMiniWatch > _watchList = new List < IMiniWatch > ( ) ;
2014-09-01 18:43:41 +00:00
private readonly Settings _settings ;
2013-10-27 17:47:54 +00:00
private readonly UndoHistory < IMiniWatch > _history = new UndoHistory < IMiniWatch > ( true ) ;
2013-09-26 01:09:08 +00:00
private bool _keepHistory = true ;
2014-01-01 21:56:35 +00:00
private bool _isSorted = true ; // Tracks whether or not the list is sorted by address, if it is, binary search can be used for finding watches
2013-09-16 01:24:06 +00:00
2014-12-16 01:50:22 +00:00
public RamSearchEngine ( Settings settings , IMemoryDomains memoryDomains )
2013-09-14 19:07:11 +00:00
{
2014-12-16 01:50:22 +00:00
_settings = new Settings ( memoryDomains ) ;
2013-09-29 19:41:03 +00:00
_settings . Mode = settings . Mode ;
_settings . Domain = settings . Domain ;
_settings . Size = settings . Size ;
_settings . CheckMisAligned = settings . CheckMisAligned ;
_settings . Type = settings . Type ;
_settings . BigEndian = settings . BigEndian ;
_settings . PreviousType = settings . PreviousType ;
2013-09-14 19:07:11 +00:00
}
2014-12-16 01:50:22 +00:00
public RamSearchEngine ( Settings settings , IMemoryDomains memoryDomains , Compare compareTo , long? compareValue , int? differentBy )
: this ( settings , memoryDomains )
2013-10-12 02:06:53 +00:00
{
_compareTo = compareTo ;
_differentBy = differentBy ;
_compareValue = compareValue ;
}
2013-09-22 01:53:20 +00:00
#region API
2013-09-14 23:30:23 +00:00
2015-01-18 18:59:23 +00:00
public IEnumerable < long > OutOfRangeAddress
2014-05-04 15:30:18 +00:00
{
get
{
return _watchList
. Where ( watch = > watch . Address > = Domain . Size )
. Select ( watch = > watch . Address ) ;
}
}
2013-09-14 23:30:23 +00:00
public void Start ( )
{
2013-09-25 04:07:41 +00:00
_history . Clear ( ) ;
2013-10-07 14:54:29 +00:00
var domain = _settings . Domain ;
2013-12-31 16:59:38 +00:00
var listSize = domain . Size ;
if ( ! _settings . CheckMisAligned )
{
listSize / = ( int ) _settings . Size ;
}
2015-01-18 15:25:47 +00:00
_watchList = new List < IMiniWatch > ( ( int ) listSize ) ;
2013-10-07 14:54:29 +00:00
2013-09-19 23:45:29 +00:00
switch ( _settings . Size )
2013-09-14 23:30:23 +00:00
{
2013-09-19 23:45:29 +00:00
default :
case Watch . WatchSize . Byte :
2013-09-20 01:18:55 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed )
2013-09-19 23:45:29 +00:00
{
2013-12-27 16:48:47 +00:00
for ( int i = 0 ; i < domain . Size ; i + + )
2013-09-20 01:18:55 +00:00
{
2013-10-07 14:54:29 +00:00
_watchList . Add ( new MiniByteWatchDetailed ( domain , i ) ) ;
2013-09-20 01:18:55 +00:00
}
}
else
{
2013-12-27 16:48:47 +00:00
for ( int i = 0 ; i < domain . Size ; i + + )
2013-09-20 01:18:55 +00:00
{
2013-10-07 14:54:29 +00:00
_watchList . Add ( new MiniByteWatch ( domain , i ) ) ;
2013-09-20 01:18:55 +00:00
}
2013-09-19 23:45:29 +00:00
}
2013-12-27 16:48:47 +00:00
2013-09-19 23:45:29 +00:00
break ;
case Watch . WatchSize . Word :
2013-09-20 01:18:55 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2014-05-15 00:33:18 +00:00
for ( int i = 0 ; i < domain . Size - 1 ; i + = _settings . CheckMisAligned ? 1 : 2 )
2013-09-20 01:18:55 +00:00
{
2013-10-07 14:54:29 +00:00
_watchList . Add ( new MiniWordWatchDetailed ( domain , i , _settings . BigEndian ) ) ;
2013-09-20 01:18:55 +00:00
}
}
else
2013-09-19 23:45:29 +00:00
{
2014-05-15 00:33:18 +00:00
for ( int i = 0 ; i < domain . Size - 1 ; i + = _settings . CheckMisAligned ? 1 : 2 )
2013-09-20 01:18:55 +00:00
{
2013-10-07 14:54:29 +00:00
_watchList . Add ( new MiniWordWatch ( domain , i , _settings . BigEndian ) ) ;
2013-09-20 01:18:55 +00:00
}
2013-09-19 23:45:29 +00:00
}
2013-12-27 16:48:47 +00:00
2013-09-19 23:45:29 +00:00
break ;
case Watch . WatchSize . DWord :
2013-09-20 01:18:55 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2014-05-15 00:33:18 +00:00
for ( int i = 0 ; i < domain . Size - 3 ; i + = _settings . CheckMisAligned ? 1 : 4 )
2013-09-20 01:18:55 +00:00
{
2013-10-07 14:54:29 +00:00
_watchList . Add ( new MiniDWordWatchDetailed ( domain , i , _settings . BigEndian ) ) ;
2013-09-20 01:18:55 +00:00
}
}
else
2013-09-19 23:45:29 +00:00
{
2014-05-15 00:33:18 +00:00
for ( int i = 0 ; i < domain . Size - 3 ; i + = _settings . CheckMisAligned ? 1 : 4 )
2013-09-20 01:18:55 +00:00
{
2013-10-07 14:54:29 +00:00
_watchList . Add ( new MiniDWordWatch ( domain , i , _settings . BigEndian ) ) ;
2013-09-20 01:18:55 +00:00
}
2013-09-19 23:45:29 +00:00
}
2013-12-27 16:48:47 +00:00
2013-09-19 23:45:29 +00:00
break ;
2013-09-14 23:30:23 +00:00
}
}
2013-09-14 19:07:11 +00:00
/// <summary>
/// Exposes the current watch state based on index
/// </summary>
public Watch this [ int index ]
{
get
{
2013-09-20 01:18:55 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
return Watch . GenerateWatch (
_settings . Domain ,
_watchList [ index ] . Address ,
_settings . Size ,
_settings . Type ,
_settings . BigEndian ,
_watchList [ index ] . Previous ,
( _watchList [ index ] as IMiniWatchDetails ) . ChangeCount
) ;
}
else
{
return Watch . GenerateWatch (
_settings . Domain ,
_watchList [ index ] . Address ,
_settings . Size ,
_settings . Type ,
_settings . BigEndian ,
_watchList [ index ] . Previous ,
0
) ;
}
2013-09-14 19:07:11 +00:00
}
}
2013-09-22 01:53:20 +00:00
public int DoSearch ( )
2013-09-21 23:55:17 +00:00
{
2013-09-22 01:53:20 +00:00
int before = _watchList . Count ;
2013-12-27 16:48:47 +00:00
2013-09-29 18:19:47 +00:00
switch ( _compareTo )
2013-09-21 23:55:17 +00:00
{
default :
2013-10-27 17:47:54 +00:00
case Compare . Previous :
2013-09-25 01:30:27 +00:00
_watchList = ComparePrevious ( _watchList ) . ToList ( ) ;
2013-09-21 23:55:17 +00:00
break ;
2013-10-27 17:47:54 +00:00
case Compare . SpecificValue :
2013-09-25 01:30:27 +00:00
_watchList = CompareSpecificValue ( _watchList ) . ToList ( ) ;
2013-09-21 23:55:17 +00:00
break ;
2013-10-27 17:47:54 +00:00
case Compare . SpecificAddress :
2013-09-25 01:30:27 +00:00
_watchList = CompareSpecificAddress ( _watchList ) . ToList ( ) ;
2013-09-21 23:55:17 +00:00
break ;
2013-10-27 17:47:54 +00:00
case Compare . Changes :
2013-09-25 01:30:27 +00:00
_watchList = CompareChanges ( _watchList ) . ToList ( ) ;
2013-09-21 23:55:17 +00:00
break ;
2013-10-27 17:47:54 +00:00
case Compare . Difference :
2013-09-25 01:30:27 +00:00
_watchList = CompareDifference ( _watchList ) . ToList ( ) ;
2013-09-22 17:00:05 +00:00
break ;
2013-09-21 23:55:17 +00:00
}
if ( _settings . PreviousType = = Watch . PreviousType . LastSearch )
{
2014-12-16 00:41:47 +00:00
SetPreviousToCurrent ( ) ;
2013-09-21 23:55:17 +00:00
}
2013-09-22 01:53:20 +00:00
2013-09-26 01:09:08 +00:00
if ( _keepHistory )
{
_history . AddState ( _watchList ) ;
}
2013-09-25 04:07:41 +00:00
2013-09-22 01:53:20 +00:00
return before - _watchList . Count ;
2013-09-21 23:55:17 +00:00
}
2015-01-18 18:59:23 +00:00
public bool Preview ( long address )
2013-09-23 16:51:35 +00:00
{
2014-01-01 21:56:35 +00:00
IEnumerable < IMiniWatch > listOfOne ;
if ( _isSorted )
{
listOfOne = Enumerable . Repeat ( _watchList . BinarySearch ( x = > x . Address , address ) , 1 ) ;
}
else
{
listOfOne = Enumerable . Repeat ( _watchList . FirstOrDefault ( x = > x . Address = = address ) , 1 ) ;
}
2013-10-07 18:32:53 +00:00
2013-09-29 18:19:47 +00:00
switch ( _compareTo )
2013-09-25 01:30:27 +00:00
{
default :
2013-10-27 17:47:54 +00:00
case Compare . Previous :
return ! ComparePrevious ( listOfOne ) . Any ( ) ;
case Compare . SpecificValue :
return ! CompareSpecificValue ( listOfOne ) . Any ( ) ;
case Compare . SpecificAddress :
return ! CompareSpecificAddress ( listOfOne ) . Any ( ) ;
case Compare . Changes :
return ! CompareChanges ( listOfOne ) . Any ( ) ;
case Compare . Difference :
return ! CompareDifference ( listOfOne ) . Any ( ) ;
2013-09-25 01:30:27 +00:00
}
2013-09-23 16:51:35 +00:00
}
2013-09-14 19:07:11 +00:00
public int Count
{
2013-09-21 14:09:37 +00:00
get { return _watchList . Count ; }
2013-09-14 19:07:11 +00:00
}
2013-09-29 19:41:03 +00:00
public Settings . SearchMode Mode { get { return _settings . Mode ; } }
2013-09-29 16:09:48 +00:00
public MemoryDomain Domain
2013-09-14 19:07:11 +00:00
{
2013-09-29 16:09:48 +00:00
get { return _settings . Domain ; }
2013-09-14 19:07:11 +00:00
}
2013-09-29 18:19:47 +00:00
public Compare CompareTo
{
2013-12-30 01:17:11 +00:00
get
{
return _compareTo ;
}
2013-09-29 18:52:11 +00:00
set
{
if ( CanDoCompareType ( value ) )
{
_compareTo = value ;
}
else
{
throw new InvalidOperationException ( ) ;
}
}
2013-09-29 18:19:47 +00:00
}
public long? CompareValue
{
get { return _compareValue ; }
set { _compareValue = value ; }
}
public ComparisonOperator Operator
{
get { return _operator ; }
set { _operator = value ; }
}
public int? DifferentBy
{
get { return _differentBy ; }
set { _differentBy = value ; }
}
2013-09-14 23:30:23 +00:00
public void Update ( )
{
2013-09-20 01:18:55 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2013-09-21 14:09:37 +00:00
foreach ( IMiniWatchDetails watch in _watchList )
2013-09-20 01:18:55 +00:00
{
2013-09-29 19:17:41 +00:00
watch . Update ( _settings . PreviousType , _settings . Domain , _settings . BigEndian ) ;
2013-09-20 01:18:55 +00:00
}
}
else
{
2013-09-22 17:00:05 +00:00
return ;
2013-09-20 01:18:55 +00:00
}
2013-09-14 23:30:23 +00:00
}
2013-09-19 23:45:29 +00:00
public void SetType ( Watch . DisplayType type )
{
if ( Watch . AvailableTypes ( _settings . Size ) . Contains ( type ) )
{
_settings . Type = type ;
}
}
public void SetEndian ( bool bigendian )
{
_settings . BigEndian = bigendian ;
}
2013-09-20 01:18:55 +00:00
public void SetPreviousType ( Watch . PreviousType type )
{
2013-09-20 15:33:46 +00:00
if ( _settings . Mode = = Settings . SearchMode . Fast )
{
2013-09-29 21:15:47 +00:00
if ( type = = Watch . PreviousType . LastFrame )
2013-09-20 15:33:46 +00:00
{
throw new InvalidOperationException ( ) ;
}
}
2013-09-21 14:09:37 +00:00
2013-09-20 01:18:55 +00:00
_settings . PreviousType = type ;
}
2014-12-16 00:41:47 +00:00
public void SetPreviousToCurrent ( )
2013-09-22 01:53:20 +00:00
{
_watchList . ForEach ( x = > x . SetPreviousToCurrent ( _settings . Domain , _settings . BigEndian ) ) ;
}
public void ClearChangeCounts ( )
{
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2013-12-30 01:17:11 +00:00
foreach ( var watch in _watchList . Cast < IMiniWatchDetails > ( ) )
2013-09-22 01:53:20 +00:00
{
watch . ClearChangeCount ( ) ;
}
}
}
2014-07-03 01:46:14 +00:00
/// <summary>
/// Remove a set of watches
/// However, this should not be used with large data sets (100k or more) as it uses a contains logic to perform the task
/// </summary>
public void RemoveSmallWatchRange ( IEnumerable < Watch > watches )
{
if ( _keepHistory )
{
_history . AddState ( _watchList ) ;
}
var addresses = watches . Select ( x = > x . Address ? ? 0 ) ;
var removeList = _watchList . Where ( x = > ! addresses . Contains ( x . Address ) ) . ToList ( ) ;
}
public void RemoveRange ( IEnumerable < int > indices )
2013-09-22 01:53:20 +00:00
{
2013-12-27 16:48:47 +00:00
if ( _keepHistory )
{
_history . AddState ( _watchList ) ;
}
2015-01-18 18:59:23 +00:00
var removeList = indices . Select ( i = > _watchList [ i ] ) ; // This will fail after int.MaxValue but Ram Search fails on domains that large anyway
2014-07-03 01:46:14 +00:00
_watchList = _watchList . Except ( removeList ) . ToList ( ) ;
2013-09-22 01:53:20 +00:00
}
2015-01-18 18:59:23 +00:00
public void AddRange ( List < long > addresses , bool append )
2013-09-22 12:50:47 +00:00
{
if ( ! append )
{
_watchList . Clear ( ) ;
}
2013-12-30 01:17:11 +00:00
switch ( _settings . Size )
2013-09-22 12:50:47 +00:00
{
default :
case Watch . WatchSize . Byte :
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2013-12-30 01:17:11 +00:00
foreach ( var addr in addresses )
{
_watchList . Add ( new MiniByteWatchDetailed ( _settings . Domain , addr ) ) ;
}
2013-09-22 12:50:47 +00:00
}
else
{
2013-12-30 01:17:11 +00:00
foreach ( var addr in addresses )
{
_watchList . Add ( new MiniByteWatch ( _settings . Domain , addr ) ) ;
}
2013-09-22 12:50:47 +00:00
}
2013-12-30 01:17:11 +00:00
2013-09-22 12:50:47 +00:00
break ;
case Watch . WatchSize . Word :
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2013-12-30 01:17:11 +00:00
foreach ( var addr in addresses )
{
_watchList . Add ( new MiniWordWatchDetailed ( _settings . Domain , addr , _settings . BigEndian ) ) ;
}
2013-09-22 12:50:47 +00:00
}
else
{
2013-12-30 01:17:11 +00:00
foreach ( var addr in addresses )
{
_watchList . Add ( new MiniWordWatch ( _settings . Domain , addr , _settings . BigEndian ) ) ;
}
2013-09-22 12:50:47 +00:00
}
2013-12-30 01:17:11 +00:00
2013-09-22 12:50:47 +00:00
break ;
case Watch . WatchSize . DWord :
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
2013-12-30 01:17:11 +00:00
foreach ( var addr in addresses )
{
_watchList . Add ( new MiniDWordWatchDetailed ( _settings . Domain , addr , _settings . BigEndian ) ) ;
}
2013-09-22 12:50:47 +00:00
}
else
{
2013-12-30 01:17:11 +00:00
foreach ( var addr in addresses )
{
_watchList . Add ( new MiniDWordWatch ( _settings . Domain , addr , _settings . BigEndian ) ) ;
}
2013-09-22 12:50:47 +00:00
}
2013-12-30 01:17:11 +00:00
2013-09-22 12:50:47 +00:00
break ;
}
}
2013-09-26 01:39:12 +00:00
public void Sort ( string column , bool reverse )
{
2014-01-01 21:56:35 +00:00
_isSorted = false ;
2013-12-30 01:17:11 +00:00
switch ( column )
2013-09-26 01:39:12 +00:00
{
2013-10-27 07:54:00 +00:00
case WatchList . ADDRESS :
2013-09-26 01:39:12 +00:00
if ( reverse )
{
_watchList = _watchList . OrderByDescending ( x = > x . Address ) . ToList ( ) ;
}
else
{
_watchList = _watchList . OrderBy ( x = > x . Address ) . ToList ( ) ;
2014-01-01 21:56:35 +00:00
_isSorted = true ;
2013-09-26 01:39:12 +00:00
}
2013-12-30 01:17:11 +00:00
2013-09-26 01:39:12 +00:00
break ;
2013-10-27 07:54:00 +00:00
case WatchList . VALUE :
2013-09-26 01:39:12 +00:00
if ( reverse )
{
_watchList = _watchList . OrderByDescending ( x = > GetValue ( x . Address ) ) . ToList ( ) ;
}
else
{
_watchList = _watchList . OrderBy ( x = > GetValue ( x . Address ) ) . ToList ( ) ;
}
2013-12-30 01:17:11 +00:00
2013-09-26 01:39:12 +00:00
break ;
2013-10-27 07:54:00 +00:00
case WatchList . PREV :
2013-09-26 01:39:12 +00:00
if ( reverse )
{
_watchList = _watchList . OrderByDescending ( x = > x . Previous ) . ToList ( ) ;
}
else
{
_watchList = _watchList . OrderBy ( x = > x . Previous ) . ToList ( ) ;
}
2013-12-30 01:17:11 +00:00
2013-09-26 01:39:12 +00:00
break ;
2013-10-27 07:54:00 +00:00
case WatchList . CHANGES :
2013-09-26 01:39:12 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed )
{
if ( reverse )
{
_watchList = _watchList
. Cast < IMiniWatchDetails > ( )
. OrderByDescending ( x = > x . ChangeCount )
. Cast < IMiniWatch > ( ) . ToList ( ) ;
}
else
{
_watchList = _watchList
. Cast < IMiniWatchDetails > ( )
. OrderBy ( x = > x . ChangeCount )
. Cast < IMiniWatch > ( ) . ToList ( ) ;
}
}
2013-12-30 01:17:11 +00:00
2013-09-26 01:39:12 +00:00
break ;
2013-10-27 07:54:00 +00:00
case WatchList . DIFF :
2013-09-26 01:39:12 +00:00
if ( reverse )
{
_watchList = _watchList . OrderByDescending ( x = > ( GetValue ( x . Address ) - x . Previous ) ) . ToList ( ) ;
}
else
{
_watchList = _watchList . OrderBy ( x = > ( GetValue ( x . Address ) - x . Previous ) ) . ToList ( ) ;
}
2013-12-30 01:17:11 +00:00
2013-09-26 01:39:12 +00:00
break ;
}
}
2013-09-25 04:07:41 +00:00
#endregion
#region Undo API
2013-09-26 01:09:08 +00:00
public bool UndoEnabled
{
get { return _keepHistory ; }
set { _keepHistory = value ; }
}
public bool CanUndo
{
get { return _keepHistory & & _history . CanUndo ; }
}
public bool CanRedo
{
get { return _keepHistory & & _history . CanRedo ; }
}
2013-09-25 04:07:41 +00:00
public void ClearHistory ( )
{
_history . Clear ( ) ;
}
public void Undo ( )
{
2013-09-26 01:09:08 +00:00
if ( _keepHistory )
{
2013-10-27 07:54:00 +00:00
_watchList = _history . Undo ( ) . ToList ( ) ;
2013-09-26 01:09:08 +00:00
}
2013-09-25 04:07:41 +00:00
}
public void Redo ( )
{
2013-09-26 01:09:08 +00:00
if ( _keepHistory )
{
2013-10-27 07:54:00 +00:00
_watchList = _history . Redo ( ) . ToList ( ) ;
2013-09-26 01:09:08 +00:00
}
2013-09-25 04:07:41 +00:00
}
2013-09-14 23:30:23 +00:00
#endregion
#region Comparisons
2013-09-25 01:30:27 +00:00
private IEnumerable < IMiniWatch > ComparePrevious ( IEnumerable < IMiniWatch > watchList )
2013-09-14 23:30:23 +00:00
{
2013-09-29 18:19:47 +00:00
switch ( _operator )
2013-09-21 14:09:37 +00:00
{
2013-09-25 01:30:27 +00:00
default :
2013-09-21 14:09:37 +00:00
case ComparisonOperator . Equal :
2013-09-25 01:30:27 +00:00
return watchList . Where ( x = > GetValue ( x . Address ) = = x . Previous ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . NotEqual :
2013-09-25 01:30:27 +00:00
return watchList . Where ( x = > GetValue ( x . Address ) ! = x . Previous ) ;
2014-09-07 06:33:21 +00:00
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThan :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) > ToFloat ( x . Previous ) ) ;
}
2014-09-07 06:33:21 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) > SignExtendAsNeeded ( x . Previous ) ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThanEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) > = ToFloat ( x . Previous ) ) ;
}
2014-09-07 06:33:21 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) > = SignExtendAsNeeded ( x . Previous ) ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThan :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) < ToFloat ( x . Previous ) ) ;
}
2014-09-07 06:33:21 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) < SignExtendAsNeeded ( x . Previous ) ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThanEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) < = ToFloat ( x . Previous ) ) ;
}
2014-09-07 06:33:21 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) < = SignExtendAsNeeded ( x . Previous ) ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . DifferentBy :
2013-09-29 18:19:47 +00:00
if ( _differentBy . HasValue )
2013-09-21 23:55:17 +00:00
{
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) + _differentBy . Value = = ToFloat ( x . Previous ) )
| | ( ToFloat ( GetValue ( x . Address ) ) - _differentBy . Value = = ToFloat ( x . Previous ) ) ) ;
}
2014-09-07 06:33:21 +00:00
return watchList . Where ( x = > {
long val = SignExtendAsNeeded ( GetValue ( x . Address ) ) ;
long prev = SignExtendAsNeeded ( x . Previous ) ;
return ( val + _differentBy . Value = = prev ) | | ( val - _differentBy . Value = = prev ) ;
}
) ;
2013-09-21 23:55:17 +00:00
}
else
{
throw new InvalidOperationException ( ) ;
}
2013-09-21 14:09:37 +00:00
}
2013-09-14 23:30:23 +00:00
}
2013-09-25 01:30:27 +00:00
private IEnumerable < IMiniWatch > CompareSpecificValue ( IEnumerable < IMiniWatch > watchList )
2013-09-14 23:30:23 +00:00
{
2013-09-29 18:19:47 +00:00
if ( _compareValue . HasValue )
2013-09-21 23:55:17 +00:00
{
2013-09-29 18:19:47 +00:00
switch ( _operator )
2013-09-21 23:55:17 +00:00
{
2013-09-25 01:30:27 +00:00
default :
2013-09-21 23:55:17 +00:00
case ComparisonOperator . Equal :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) = = _compareValue . Value ) ;
}
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > GetValue ( x . Address ) = = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . NotEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) ! = _compareValue . Value ) ;
}
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > GetValue ( x . Address ) ! = _compareValue . Value ) ;
2014-05-18 23:59:15 +00:00
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThan :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) > ToFloat ( _compareValue . Value ) ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) > _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThanEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) > = ToFloat ( _compareValue . Value ) ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) > = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThan :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) < ToFloat ( _compareValue . Value ) ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) < _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThanEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ToFloat ( GetValue ( x . Address ) ) < = ToFloat ( _compareValue . Value ) ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > SignExtendAsNeeded ( GetValue ( x . Address ) ) < = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . DifferentBy :
2013-09-29 18:19:47 +00:00
if ( _differentBy . HasValue )
2013-09-21 23:55:17 +00:00
{
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) + _differentBy . Value = = _compareValue . Value ) | |
( ToFloat ( GetValue ( x . Address ) ) - _differentBy . Value = = _compareValue . Value ) ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x
= > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) + _differentBy . Value = = _compareValue . Value )
| | ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - _differentBy . Value = = _compareValue . Value ) ) ;
2013-09-21 23:55:17 +00:00
}
else
{
throw new InvalidOperationException ( ) ;
}
}
}
else
{
throw new InvalidOperationException ( ) ;
}
2013-09-14 23:30:23 +00:00
}
2013-09-25 01:30:27 +00:00
private IEnumerable < IMiniWatch > CompareSpecificAddress ( IEnumerable < IMiniWatch > watchList )
2013-09-14 23:30:23 +00:00
{
2013-09-29 18:19:47 +00:00
if ( _compareValue . HasValue )
2013-09-21 23:55:17 +00:00
{
2013-09-29 18:19:47 +00:00
switch ( _operator )
2013-09-21 23:55:17 +00:00
{
2013-09-25 01:30:27 +00:00
default :
2013-09-21 23:55:17 +00:00
case ComparisonOperator . Equal :
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > x . Address = = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . NotEqual :
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > x . Address ! = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThan :
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > x . Address > _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThanEqual :
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > x . Address > = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThan :
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > x . Address < _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThanEqual :
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > x . Address < = _compareValue . Value ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . DifferentBy :
2013-09-29 18:19:47 +00:00
if ( _differentBy . HasValue )
2013-09-21 23:55:17 +00:00
{
2013-09-29 18:19:47 +00:00
return watchList . Where ( x = > ( x . Address + _differentBy . Value = = _compareValue . Value ) | | ( x . Address - _differentBy . Value = = _compareValue . Value ) ) ;
2013-09-21 23:55:17 +00:00
}
else
{
throw new InvalidOperationException ( ) ;
}
}
}
else
{
throw new InvalidOperationException ( ) ;
}
2013-09-14 23:30:23 +00:00
}
2013-09-25 01:30:27 +00:00
private IEnumerable < IMiniWatch > CompareChanges ( IEnumerable < IMiniWatch > watchList )
2013-09-14 23:30:23 +00:00
{
2013-09-29 18:19:47 +00:00
if ( _settings . Mode = = Settings . SearchMode . Detailed & & _compareValue . HasValue )
2013-09-21 23:55:17 +00:00
{
2013-09-29 18:19:47 +00:00
switch ( _operator )
2013-09-21 23:55:17 +00:00
{
2013-09-25 01:30:27 +00:00
default :
2013-09-21 23:55:17 +00:00
case ComparisonOperator . Equal :
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > x . ChangeCount = = _compareValue . Value )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . NotEqual :
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > x . ChangeCount ! = _compareValue . Value )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThan :
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > x . ChangeCount > _compareValue . Value )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . GreaterThanEqual :
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > x . ChangeCount > = _compareValue . Value )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThan :
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > x . ChangeCount < _compareValue . Value )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . LessThanEqual :
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > x . ChangeCount < = _compareValue . Value )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
case ComparisonOperator . DifferentBy :
2013-09-29 18:19:47 +00:00
if ( _differentBy . HasValue )
2013-09-21 23:55:17 +00:00
{
2013-09-25 01:30:27 +00:00
return watchList
2013-09-22 15:54:31 +00:00
. Cast < IMiniWatchDetails > ( )
2013-09-29 18:19:47 +00:00
. Where ( x = > ( x . ChangeCount + _differentBy . Value = = _compareValue . Value ) | | ( x . ChangeCount - _differentBy . Value = = _compareValue . Value ) )
2013-09-25 01:30:27 +00:00
. Cast < IMiniWatch > ( ) ;
2013-09-21 23:55:17 +00:00
}
else
{
throw new InvalidOperationException ( ) ;
}
}
}
else
{
throw new InvalidCastException ( ) ;
}
2013-09-14 23:30:23 +00:00
}
2013-09-25 01:30:27 +00:00
private IEnumerable < IMiniWatch > CompareDifference ( IEnumerable < IMiniWatch > watchList )
2013-09-14 23:30:23 +00:00
{
2013-09-29 18:19:47 +00:00
if ( _compareValue . HasValue )
2013-09-22 15:54:31 +00:00
{
2013-09-29 18:19:47 +00:00
switch ( _operator )
2013-09-22 15:54:31 +00:00
{
2013-09-25 01:30:27 +00:00
default :
2013-09-22 15:54:31 +00:00
case ComparisonOperator . Equal :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - ToFloat ( x . Previous ) ) = = _compareValue . Value ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) ) = = _compareValue . Value ) ;
2013-09-22 15:54:31 +00:00
case ComparisonOperator . NotEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - x . Previous ) ! = _compareValue . Value ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) ) ! = _compareValue . Value ) ;
2013-09-22 15:54:31 +00:00
case ComparisonOperator . GreaterThan :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - x . Previous ) > _compareValue . Value ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) ) > _compareValue . Value ) ;
2013-09-22 15:54:31 +00:00
case ComparisonOperator . GreaterThanEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - x . Previous ) > = _compareValue . Value ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) ) > = _compareValue . Value ) ;
2013-09-22 15:54:31 +00:00
case ComparisonOperator . LessThan :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - x . Previous ) < _compareValue . Value ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) ) < _compareValue . Value ) ;
2013-09-22 15:54:31 +00:00
case ComparisonOperator . LessThanEqual :
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - x . Previous ) < = _compareValue . Value ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x = > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) ) < = _compareValue . Value ) ;
2013-09-22 15:54:31 +00:00
case ComparisonOperator . DifferentBy :
2013-09-29 18:19:47 +00:00
if ( _differentBy . HasValue )
2013-09-22 15:54:31 +00:00
{
2014-05-18 23:59:15 +00:00
if ( _settings . Type = = Watch . DisplayType . Float )
{
return watchList . Where ( x = > ( ToFloat ( GetValue ( x . Address ) ) - x . Previous + _differentBy . Value = = _compareValue ) | |
( ToFloat ( GetValue ( x . Address ) ) - x . Previous - _differentBy . Value = = x . Previous ) ) ;
}
2014-12-16 00:41:47 +00:00
return watchList . Where ( x
= > ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) + _differentBy . Value = = _compareValue )
| | ( SignExtendAsNeeded ( GetValue ( x . Address ) ) - SignExtendAsNeeded ( x . Previous ) - _differentBy . Value = = _compareValue ) ) ;
2013-09-22 15:54:31 +00:00
}
else
{
throw new InvalidOperationException ( ) ;
}
}
}
else
{
throw new InvalidCastException ( ) ;
}
2013-09-14 23:30:23 +00:00
}
2013-09-14 19:07:11 +00:00
#endregion
#region Private parts
2013-09-21 14:09:37 +00:00
2014-05-18 23:59:15 +00:00
private float ToFloat ( long val )
{
var bytes = BitConverter . GetBytes ( ( int ) val ) ;
return BitConverter . ToSingle ( bytes , 0 ) ;
}
2014-09-07 06:33:21 +00:00
private long SignExtendAsNeeded ( long val )
{
if ( _settings . Type ! = Watch . DisplayType . Signed ) return val ;
switch ( _settings . Size )
{
default :
case Watch . WatchSize . Byte :
return ( sbyte ) val ;
case Watch . WatchSize . Word :
return ( short ) val ;
case Watch . WatchSize . DWord :
return ( int ) val ;
}
}
2015-01-18 18:59:23 +00:00
private long GetValue ( long addr )
2013-09-21 14:09:37 +00:00
{
2014-09-07 06:33:21 +00:00
//do not return sign extended variables from here.
2013-09-21 14:09:37 +00:00
switch ( _settings . Size )
{
default :
case Watch . WatchSize . Byte :
2014-05-04 15:30:18 +00:00
var theByte = _settings . Domain . PeekByte ( addr % Domain . Size ) ;
2014-09-07 06:17:10 +00:00
return theByte ;
2013-12-30 01:17:11 +00:00
2013-09-21 14:09:37 +00:00
case Watch . WatchSize . Word :
2014-05-15 00:33:18 +00:00
var theWord = _settings . Domain . PeekWord ( addr % Domain . Size , _settings . BigEndian ) ;
2014-09-07 06:17:10 +00:00
return theWord ;
2013-12-30 01:17:11 +00:00
2013-09-21 14:09:37 +00:00
case Watch . WatchSize . DWord :
2014-05-15 00:33:18 +00:00
var theDWord = _settings . Domain . PeekDWord ( addr % Domain . Size , _settings . BigEndian ) ;
2014-09-07 06:17:10 +00:00
return theDWord ;
2013-09-21 14:09:37 +00:00
}
}
2013-09-29 18:52:11 +00:00
private bool CanDoCompareType ( Compare compareType )
{
switch ( _settings . Mode )
{
default :
case Settings . SearchMode . Detailed :
return true ;
case Settings . SearchMode . Fast :
2013-10-27 17:47:54 +00:00
return compareType ! = Compare . Changes ;
2013-09-29 18:52:11 +00:00
}
}
2013-09-14 19:07:11 +00:00
#endregion
2013-09-16 01:24:06 +00:00
#region Classes
2013-09-20 01:18:55 +00:00
2013-09-25 04:07:41 +00:00
public interface IMiniWatch
2013-09-19 23:45:29 +00:00
{
2015-01-18 18:59:23 +00:00
long Address { get ; }
2014-09-07 06:33:21 +00:00
long Previous { get ; } //do not store sign extended variables in here.
2013-09-21 23:55:17 +00:00
void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian ) ;
2013-09-20 01:18:55 +00:00
}
private interface IMiniWatchDetails
{
int ChangeCount { get ; }
2013-09-22 15:54:31 +00:00
2013-09-22 01:53:20 +00:00
void ClearChangeCount ( ) ;
2013-09-29 19:17:41 +00:00
void Update ( Watch . PreviousType type , MemoryDomain domain , bool bigendian ) ;
2013-09-19 23:45:29 +00:00
}
2013-12-30 01:17:11 +00:00
private sealed class MiniByteWatch : IMiniWatch
2013-09-19 23:45:29 +00:00
{
2015-01-18 18:59:23 +00:00
public long Address { get ; private set ; }
2013-09-20 01:18:55 +00:00
private byte _previous ;
2013-09-19 23:45:29 +00:00
2015-01-18 18:59:23 +00:00
public MiniByteWatch ( MemoryDomain domain , long addr )
2013-09-19 23:45:29 +00:00
{
Address = addr ;
2014-05-04 15:30:18 +00:00
_previous = domain . PeekByte ( Address % domain . Size ) ;
2013-09-19 23:45:29 +00:00
}
2014-09-07 06:17:10 +00:00
public long Previous
2013-09-19 23:45:29 +00:00
{
2013-09-20 01:18:55 +00:00
get { return _previous ; }
2013-09-19 23:45:29 +00:00
}
2013-09-21 23:55:17 +00:00
public void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian )
{
2014-05-04 15:30:18 +00:00
_previous = domain . PeekByte ( Address % domain . Size ) ;
2013-09-21 23:55:17 +00:00
}
2013-09-19 23:45:29 +00:00
}
2013-12-30 01:17:11 +00:00
private sealed class MiniWordWatch : IMiniWatch
2013-09-19 23:45:29 +00:00
{
2015-01-18 18:59:23 +00:00
public long Address { get ; private set ; }
2013-09-20 01:18:55 +00:00
private ushort _previous ;
2013-09-19 23:45:29 +00:00
2015-01-18 18:59:23 +00:00
public MiniWordWatch ( MemoryDomain domain , long addr , bool bigEndian )
2013-09-19 23:45:29 +00:00
{
Address = addr ;
2014-05-15 00:33:18 +00:00
_previous = domain . PeekWord ( Address % domain . Size , bigEndian ) ;
2013-09-19 23:45:29 +00:00
}
2014-09-07 06:17:10 +00:00
public long Previous
2013-09-19 23:45:29 +00:00
{
2013-09-20 01:18:55 +00:00
get { return _previous ; }
2013-09-19 23:45:29 +00:00
}
2013-09-21 23:55:17 +00:00
public void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian )
{
2013-11-04 02:11:40 +00:00
_previous = domain . PeekWord ( Address , bigendian ) ;
2013-09-21 23:55:17 +00:00
}
2013-09-19 23:45:29 +00:00
}
2013-12-30 01:17:11 +00:00
public sealed class MiniDWordWatch : IMiniWatch
2013-09-19 23:45:29 +00:00
{
2015-01-18 18:59:23 +00:00
public long Address { get ; private set ; }
2013-09-20 01:18:55 +00:00
private uint _previous ;
2013-09-19 23:45:29 +00:00
2015-01-18 18:59:23 +00:00
public MiniDWordWatch ( MemoryDomain domain , long addr , bool bigEndian )
2013-09-19 23:45:29 +00:00
{
Address = addr ;
2014-05-15 00:33:18 +00:00
_previous = domain . PeekDWord ( Address % domain . Size , bigEndian ) ;
2013-09-20 01:18:55 +00:00
}
2014-09-07 06:17:10 +00:00
public long Previous
2013-09-20 01:18:55 +00:00
{
2014-09-07 06:17:10 +00:00
get { return _previous ; }
2013-09-20 01:18:55 +00:00
}
2013-09-21 23:55:17 +00:00
public void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian )
{
2013-11-04 02:11:40 +00:00
_previous = domain . PeekDWord ( Address , bigendian ) ;
2013-09-21 23:55:17 +00:00
}
2013-09-20 01:18:55 +00:00
}
2013-09-21 23:55:17 +00:00
private sealed class MiniByteWatchDetailed : IMiniWatch , IMiniWatchDetails
2013-09-20 01:18:55 +00:00
{
2015-01-18 18:59:23 +00:00
public long Address { get ; private set ; }
2013-12-30 01:17:11 +00:00
2013-09-20 01:18:55 +00:00
private byte _previous ;
2014-01-02 17:56:57 +00:00
private byte _prevFrame ;
2013-12-30 01:17:11 +00:00
private int _changecount ;
2013-09-20 01:18:55 +00:00
2015-01-18 18:59:23 +00:00
public MiniByteWatchDetailed ( MemoryDomain domain , long addr )
2013-09-20 01:18:55 +00:00
{
Address = addr ;
2013-09-21 23:55:17 +00:00
SetPreviousToCurrent ( domain , false ) ;
}
public void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian )
{
2014-05-04 15:30:18 +00:00
_previous = _prevFrame = domain . PeekByte ( Address % domain . Size ) ;
2013-09-20 01:18:55 +00:00
}
2014-09-07 06:17:10 +00:00
public long Previous
2013-09-20 01:18:55 +00:00
{
get { return _previous ; }
}
public int ChangeCount
{
get { return _changecount ; }
}
2013-09-29 19:17:41 +00:00
public void Update ( Watch . PreviousType type , MemoryDomain domain , bool bigendian )
2013-09-20 01:18:55 +00:00
{
2014-05-04 15:30:18 +00:00
var value = domain . PeekByte ( Address % domain . Size ) ;
2014-01-02 17:56:57 +00:00
if ( value ! = _prevFrame )
2013-09-29 19:17:41 +00:00
{
_changecount + + ;
}
2013-09-21 14:09:37 +00:00
switch ( type )
{
case Watch . PreviousType . Original :
case Watch . PreviousType . LastSearch :
break ;
case Watch . PreviousType . LastFrame :
2014-01-02 17:56:57 +00:00
_previous = _prevFrame ;
2013-09-21 14:09:37 +00:00
break ;
2014-12-16 01:19:29 +00:00
case Watch . PreviousType . LastChange :
if ( _prevFrame ! = value )
_previous = _prevFrame ;
break ;
2013-09-21 14:09:37 +00:00
}
2014-01-02 17:56:57 +00:00
_prevFrame = value ;
2013-09-20 01:18:55 +00:00
}
2013-09-22 01:53:20 +00:00
public void ClearChangeCount ( )
{
_changecount = 0 ;
}
2013-09-20 01:18:55 +00:00
}
2013-09-21 23:55:17 +00:00
private sealed class MiniWordWatchDetailed : IMiniWatch , IMiniWatchDetails
2013-09-20 01:18:55 +00:00
{
2015-01-18 18:59:23 +00:00
public long Address { get ; private set ; }
2013-12-30 01:17:11 +00:00
2013-09-20 01:18:55 +00:00
private ushort _previous ;
2014-01-02 17:56:57 +00:00
private ushort _prevFrame ;
2013-12-30 01:17:11 +00:00
private int _changecount ;
2013-09-20 01:18:55 +00:00
2015-01-18 18:59:23 +00:00
public MiniWordWatchDetailed ( MemoryDomain domain , long addr , bool bigEndian )
2013-09-20 01:18:55 +00:00
{
Address = addr ;
2013-09-21 23:55:17 +00:00
SetPreviousToCurrent ( domain , bigEndian ) ;
}
public void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian )
{
2014-05-15 00:33:18 +00:00
_previous = _prevFrame = domain . PeekWord ( Address % domain . Size , bigendian ) ;
2013-09-20 01:18:55 +00:00
}
2014-09-07 06:17:10 +00:00
public long Previous
2013-09-20 01:18:55 +00:00
{
get { return _previous ; }
}
public int ChangeCount
{
get { return _changecount ; }
}
2013-09-29 19:17:41 +00:00
public void Update ( Watch . PreviousType type , MemoryDomain domain , bool bigendian )
2013-09-20 01:18:55 +00:00
{
2014-05-15 00:33:18 +00:00
var value = domain . PeekWord ( Address % domain . Size , bigendian ) ;
2013-09-29 19:17:41 +00:00
if ( value ! = Previous )
{
_changecount + + ;
}
2013-12-30 01:17:11 +00:00
2013-09-21 14:09:37 +00:00
switch ( type )
{
2013-09-29 19:17:41 +00:00
case Watch . PreviousType . Original :
case Watch . PreviousType . LastSearch :
2013-09-21 14:09:37 +00:00
break ;
case Watch . PreviousType . LastFrame :
2014-01-02 17:56:57 +00:00
_previous = _prevFrame ;
2013-09-29 19:17:41 +00:00
break ;
2014-12-16 01:19:29 +00:00
case Watch . PreviousType . LastChange :
if ( _prevFrame ! = value )
_previous = _prevFrame ;
break ;
2013-09-21 14:09:37 +00:00
}
2014-01-02 17:56:57 +00:00
_prevFrame = value ;
2013-09-20 01:18:55 +00:00
}
2013-09-22 01:53:20 +00:00
public void ClearChangeCount ( )
{
_changecount = 0 ;
}
2013-09-20 01:18:55 +00:00
}
2013-09-21 23:55:17 +00:00
public sealed class MiniDWordWatchDetailed : IMiniWatch , IMiniWatchDetails
2013-09-20 01:18:55 +00:00
{
2015-01-18 18:59:23 +00:00
public long Address { get ; private set ; }
2013-12-30 01:17:11 +00:00
2013-09-20 01:18:55 +00:00
private uint _previous ;
2014-01-02 17:56:57 +00:00
private uint _prevFrame ;
2013-12-30 01:17:11 +00:00
private int _changecount ;
2013-09-20 01:18:55 +00:00
2015-01-18 18:59:23 +00:00
public MiniDWordWatchDetailed ( MemoryDomain domain , long addr , bool bigEndian )
2013-09-20 01:18:55 +00:00
{
Address = addr ;
2013-09-21 23:55:17 +00:00
SetPreviousToCurrent ( domain , bigEndian ) ;
}
2013-09-20 01:18:55 +00:00
2013-09-21 23:55:17 +00:00
public void SetPreviousToCurrent ( MemoryDomain domain , bool bigendian )
{
2014-05-15 00:33:18 +00:00
_previous = _prevFrame = domain . PeekDWord ( Address % domain . Size , bigendian ) ;
2013-09-19 23:45:29 +00:00
}
2014-09-07 06:17:10 +00:00
public long Previous
2013-09-20 01:18:55 +00:00
{
get { return ( int ) _previous ; }
}
public int ChangeCount
{
get { return _changecount ; }
}
2013-09-29 19:17:41 +00:00
public void Update ( Watch . PreviousType type , MemoryDomain domain , bool bigendian )
2013-09-19 23:45:29 +00:00
{
2014-05-15 00:33:18 +00:00
var value = domain . PeekDWord ( Address % domain . Size , bigendian ) ;
2013-09-29 19:17:41 +00:00
if ( value ! = Previous )
{
_changecount + + ;
}
2013-12-30 01:17:11 +00:00
2013-09-21 14:09:37 +00:00
switch ( type )
{
2013-09-29 19:17:41 +00:00
case Watch . PreviousType . Original :
case Watch . PreviousType . LastSearch :
2013-09-21 14:09:37 +00:00
break ;
case Watch . PreviousType . LastFrame :
2014-01-02 17:56:57 +00:00
_previous = _prevFrame ;
2013-09-29 19:17:41 +00:00
break ;
2014-12-16 01:19:29 +00:00
case Watch . PreviousType . LastChange :
if ( _prevFrame ! = value )
_previous = _prevFrame ;
break ;
2013-09-21 14:09:37 +00:00
}
2014-01-02 17:56:57 +00:00
_prevFrame = value ;
2013-09-19 23:45:29 +00:00
}
2013-09-22 01:53:20 +00:00
public void ClearChangeCount ( )
{
_changecount = 0 ;
}
2013-09-19 23:45:29 +00:00
}
2013-09-16 01:24:06 +00:00
public class Settings
{
2015-01-14 21:55:48 +00:00
public Settings ( IMemoryDomains memoryDomains )
2014-09-01 18:43:41 +00:00
{
2015-01-14 21:55:48 +00:00
BigEndian = memoryDomains . MainMemory . EndianType = = MemoryDomain . Endian . Big ;
2015-02-22 15:19:38 +00:00
Size = ( Watch . WatchSize ) memoryDomains . MainMemory . ByteSize ;
2014-09-01 18:43:41 +00:00
Type = Watch . DisplayType . Unsigned ;
2015-01-14 21:55:48 +00:00
Mode = memoryDomains . MainMemory . Size > ( 1024 * 1024 ) ?
2014-09-01 18:43:41 +00:00
SearchMode . Fast :
SearchMode . Detailed ;
2015-01-14 21:55:48 +00:00
Domain = memoryDomains . MainMemory ;
2014-09-01 18:43:41 +00:00
CheckMisAligned = false ;
PreviousType = Watch . PreviousType . LastSearch ;
}
2013-09-16 01:24:06 +00:00
/*Require restart*/
public enum SearchMode { Fast , Detailed }
2013-09-21 14:09:37 +00:00
2013-12-30 01:17:11 +00:00
public SearchMode Mode { get ; set ; }
public MemoryDomain Domain { get ; set ; }
public Watch . WatchSize Size { get ; set ; }
public bool CheckMisAligned { get ; set ; }
2013-09-16 01:24:06 +00:00
/*Can be changed mid-search*/
2013-12-30 01:17:11 +00:00
public Watch . DisplayType Type { get ; set ; }
public bool BigEndian { get ; set ; }
public Watch . PreviousType PreviousType { get ; set ; }
2013-09-16 01:24:06 +00:00
}
2013-09-20 01:18:55 +00:00
2013-09-16 01:24:06 +00:00
#endregion
2013-09-14 19:07:11 +00:00
}
}