Mercurial > vba-linux
diff src/win32/ram_search.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/ram_search.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,2127 @@ 1.4 +// A few notes about this implementation of a RAM search window: 1.5 +// 1.6 +// Speed of update was one of the highest priories. 1.7 +// This is because I wanted the RAM search window to be able to 1.8 +// update every single value in RAM every single frame, and 1.9 +// keep track of the exact number of frames across which each value has changed, 1.10 +// without causing the emulation to run noticeably slower than normal. 1.11 +// 1.12 +// The data representation was changed from one entry per valid address 1.13 +// to one entry per contiguous range of uneliminated addresses 1.14 +// which references uniform pools of per-address properties. 1.15 +// - This saves time when there are many items because 1.16 +// it minimizes the amount of data that needs to be stored and processed per address. 1.17 +// - It also saves time when there are few items because 1.18 +// it ensures that no time is wasted in iterating through 1.19 +// addresses that have already been eliminated from the search. 1.20 +// 1.21 +// The worst-case scenario is when every other item has been 1.22 +// eliminated from the search, maximizing the number of regions. 1.23 +// This implementation manages to handle even that pathological case 1.24 +// acceptably well. In fact, it still updates faster than the previous implementation. 1.25 +// The time spent setting up or clearing such a large number of regions 1.26 +// is somewhat horrendous, but it seems reasonable to have poor worst-case speed 1.27 +// during these sporadic "setup" steps to achieve an all-around faster per-update speed. 1.28 +// (You can test this case by performing the search: Modulo 2 Is Specific Address 0) 1.29 + 1.30 + 1.31 +#ifdef _WIN32 1.32 + #include "stdafx.h" 1.33 + #include "resource.h" 1.34 + #include "VBA.h" 1.35 + //#include <windows.h> 1.36 + #include <commctrl.h> 1.37 + #include "BaseTsd.h" 1.38 + #include "GBACheatsDlg.h" 1.39 + #include "GBCheatsDlg.h" 1.40 + typedef INT_PTR intptr_t; 1.41 +#else 1.42 + #include "stdint.h" 1.43 +#endif 1.44 +#include <cassert> 1.45 +#include <list> 1.46 +#include <vector> 1.47 + 1.48 +#include "ram_search.h" 1.49 +#include "ramwatch.h" 1.50 +#include "../gba/GBAGlobals.h" 1.51 +#include "../gb/gbGlobals.h" 1.52 +#include "../common/vbalua.h" 1.53 +#include "Reg.h" 1.54 + 1.55 +static inline u8* HardwareToSoftwareAddress(HWAddressType address) 1.56 +{ 1.57 + if(!emulating) 1.58 + return NULL; 1.59 + 1.60 + // note: this currently follows the "quick" memory rules, 1.61 + // meaning it will miss whatever special cases aren't handled by read/writeMemoryQuick. 1.62 + // if this is made more accurate, it may be necessary to reduce regionSearchGranularity. 1.63 + if(systemCartridgeType == 0) 1.64 + { 1.65 + // GBA 1.66 + HWAddressType mask = ::map[address >> 24].mask; 1.67 + if(!mask || (address & 0xFFFFFF) > mask) 1.68 + return NULL; 1.69 + return &::map[address >> 24].address[address & mask]; 1.70 + } 1.71 + else 1.72 + { 1.73 + // GB 1.74 + extern int32 gbEchoRAMFixOn; 1.75 + if (gbEchoRAMFixOn) 1.76 + if (address >= 0xe000 && address < 0xfe00) 1.77 + address -= 0x2000; 1.78 + if((address>>12) >= sizeof(gbMemoryMap)/sizeof(*gbMemoryMap)) 1.79 + return NULL; 1.80 + return &gbMemoryMap[address>>12][address&0xfff]; 1.81 + } 1.82 +} 1.83 + 1.84 + 1.85 +struct MemoryRegion 1.86 +{ 1.87 + HWAddressType hardwareAddress; // hardware address of the start of this region 1.88 + unsigned int size; // number of bytes to the end of this region 1.89 + unsigned char* softwareAddress; // pointer to the start of the live emulator source values for this region 1.90 + 1.91 + unsigned int virtualIndex; // index into s_prevValues, s_curValues, and s_numChanges, valid after being initialized in ResetMemoryRegions() 1.92 + unsigned int itemIndex; // index into listbox items, valid when s_itemIndicesInvalid is false 1.93 +}; 1.94 + 1.95 +int MAX_RAM_SIZE = 0; 1.96 +static unsigned char* s_prevValues = 0; // values at last search or reset 1.97 +static unsigned char* s_curValues = 0; // values at last frame update 1.98 +static unsigned short* s_numChanges = 0; // number of changes of the item starting at this virtual index address 1.99 +static MemoryRegion** s_itemIndexToRegionPointer = 0; // used for random access into the memory list (trading memory size to get speed here, too bad it's so much memory), only valid when s_itemIndicesInvalid is false 1.100 +static BOOL s_itemIndicesInvalid = true; // if true, the link from listbox items to memory regions (s_itemIndexToRegionPointer) and the link from memory regions to list box items (MemoryRegion::itemIndex) both need to be recalculated 1.101 +static BOOL s_prevValuesNeedUpdate = true; // if true, the "prev" values should be updated using the "cur" values on the next frame update signaled 1.102 +static unsigned int s_maxItemIndex = 0; // max currently valid item index, the listbox sometimes tries to update things past the end of the list so we need to know this to ignore those attempts 1.103 +static int s_prevSelCount = -1; 1.104 + 1.105 +HWND RamSearchHWnd; 1.106 +#define hWnd AfxGetMainWnd()->GetSafeHwnd() 1.107 +#define hInst AfxGetInstanceHandle() 1.108 +static char Str_Tmp [1024]; 1.109 + 1.110 +int disableRamSearchUpdate = false; 1.111 + 1.112 + 1.113 + 1.114 +//static const MemoryRegion s_prgRegion = { 0x020000, SEGACD_RAM_PRG_SIZE, (unsigned char*)Ram_Prg, true}; 1.115 +//static const MemoryRegion s_word1MRegion = { 0x200000, SEGACD_1M_RAM_SIZE, (unsigned char*)Ram_Word_1M, true}; 1.116 +//static const MemoryRegion s_word2MRegion = { 0x200000, SEGACD_2M_RAM_SIZE, (unsigned char*)Ram_Word_2M, true}; 1.117 +//static const MemoryRegion s_z80Region = { 0xA00000, Z80_RAM_SIZE, (unsigned char*)Ram_Z80, true}; 1.118 +//static const MemoryRegion s_68kRegion = { 0xFF0000, _68K_RAM_SIZE, (unsigned char*)Ram_68k, true}; 1.119 +//static const MemoryRegion s_32xRegion = {0x06000000, _32X_RAM_SIZE, (unsigned char*)_32X_Ram, false}; 1.120 + 1.121 +// list of contiguous uneliminated memory regions 1.122 +typedef std::list<MemoryRegion> MemoryList; 1.123 +static MemoryList s_activeMemoryRegions; 1.124 +static CRITICAL_SECTION s_activeMemoryRegionsCS; 1.125 + 1.126 +// for undo support (could be better, but this way was really easy) 1.127 +static MemoryList s_activeMemoryRegionsBackup; 1.128 +static int s_undoType = 0; // 0 means can't undo, 1 means can undo, 2 means can redo 1.129 + 1.130 +void RamSearchSaveUndoStateIfNotTooBig(HWND hDlg); 1.131 +static const int tooManyRegionsForUndo = 10000; 1.132 + 1.133 +void ResetMemoryRegions() 1.134 +{ 1.135 + systemSoundClearBuffer(); 1.136 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.137 + 1.138 + s_activeMemoryRegions.clear(); 1.139 + 1.140 + // use HardwareToSoftwareAddress to figure out what all the possible memory regions are, 1.141 + // split up wherever there's a discontinuity in the address in our software RAM. 1.142 + static const int regionSearchGranularity = 0x100; // if this is too small, we'll waste time (in this function only), but if any region in RAM isn't evenly divisible by this, we might crash. 1.143 + HWAddressType hwRegionStart = 0; 1.144 + u8* regionStart = NULL; 1.145 + u8* regionEnd = NULL; 1.146 + for(HWAddressType addr = 0; addr != 0x10000000+regionSearchGranularity; addr += regionSearchGranularity) 1.147 + { 1.148 + u8* swAddr = HardwareToSoftwareAddress(addr); 1.149 + if(regionEnd && swAddr != regionEnd+regionSearchGranularity) 1.150 + { 1.151 + // hit end of region 1.152 + // check to see if it mirrors an existing one (in which case we discard it) 1.153 + bool discard = false; 1.154 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ++iter) 1.155 + { 1.156 + MemoryRegion& region = *iter; 1.157 + if(region.softwareAddress == regionStart) 1.158 + { 1.159 + unsigned int size = regionSearchGranularity + (regionEnd - regionStart); 1.160 + if(size <= region.size) 1.161 + { 1.162 + discard = true; 1.163 + } 1.164 + else 1.165 + { 1.166 + hwRegionStart += region.size; 1.167 + regionStart += region.size; 1.168 + } 1.169 + break; 1.170 + } 1.171 + } 1.172 + 1.173 + // don't include ROM in our RAM search (it's too huge) 1.174 + if(regionStart == rom || regionStart == gbRom) 1.175 + discard = true; 1.176 + 1.177 + // create the region 1.178 + if(!discard) 1.179 + { 1.180 + MemoryRegion region = { hwRegionStart, regionSearchGranularity + (regionEnd - regionStart), regionStart }; 1.181 + s_activeMemoryRegions.push_back(region); 1.182 + } 1.183 + 1.184 + hwRegionStart = 0; 1.185 + regionStart = NULL; 1.186 + regionEnd = NULL; 1.187 + } 1.188 + if(swAddr) 1.189 + { 1.190 + if(regionStart) 1.191 + { 1.192 + // continue region 1.193 + regionEnd = swAddr; 1.194 + } 1.195 + else 1.196 + { 1.197 + // start new region 1.198 + hwRegionStart = addr; 1.199 + regionStart = swAddr; 1.200 + regionEnd = swAddr; 1.201 + } 1.202 + } 1.203 + } 1.204 + 1.205 + 1.206 + int nextVirtualIndex = 0; 1.207 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ++iter) 1.208 + { 1.209 + MemoryRegion& region = *iter; 1.210 + region.virtualIndex = nextVirtualIndex; 1.211 + assert(((intptr_t)region.softwareAddress & 1) == 0 && "somebody needs to reimplement ReadValueAtSoftwareAddress()"); 1.212 + nextVirtualIndex = region.virtualIndex + region.size; 1.213 + } 1.214 + //assert(nextVirtualIndex <= MAX_RAM_SIZE); 1.215 + 1.216 + if(nextVirtualIndex > MAX_RAM_SIZE) 1.217 + { 1.218 + s_prevValues = (unsigned char*)realloc(s_prevValues, sizeof(char)*(nextVirtualIndex+4)); 1.219 + memset(s_prevValues, 0, sizeof(char)*(nextVirtualIndex+4)); 1.220 + 1.221 + s_curValues = (unsigned char*)realloc(s_curValues, sizeof(char)*(nextVirtualIndex+4)); 1.222 + memset(s_curValues, 0, sizeof(char)*(nextVirtualIndex+4)); 1.223 + 1.224 + s_numChanges = (unsigned short*)realloc(s_numChanges, sizeof(short)*(nextVirtualIndex+4)); 1.225 + memset(s_numChanges, 0, sizeof(short)*(nextVirtualIndex+4)); 1.226 + 1.227 + s_itemIndexToRegionPointer = (MemoryRegion**)realloc(s_itemIndexToRegionPointer, sizeof(MemoryRegion*)*(nextVirtualIndex+4)); 1.228 + memset(s_itemIndexToRegionPointer, 0, sizeof(MemoryRegion*)*(nextVirtualIndex+4)); 1.229 + 1.230 + MAX_RAM_SIZE = nextVirtualIndex; 1.231 + } 1.232 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.233 +} 1.234 + 1.235 +// eliminates a range of hardware addresses from the search results 1.236 +// returns 2 if it changed the region and moved the iterator to another region 1.237 +// returns 1 if it changed the region but didn't move the iterator 1.238 +// returns 0 if it had no effect 1.239 +// warning: don't call anything that takes an itemIndex in a loop that calls DeactivateRegion... 1.240 +// doing so would be tremendously slow because DeactivateRegion invalidates the index cache 1.241 +int DeactivateRegion(MemoryRegion& region, MemoryList::iterator& iter, HWAddressType hardwareAddress, unsigned int size) 1.242 +{ 1.243 + if(hardwareAddress + size <= region.hardwareAddress || hardwareAddress >= region.hardwareAddress + region.size) 1.244 + { 1.245 + // region is unaffected 1.246 + return 0; 1.247 + } 1.248 + else if(hardwareAddress > region.hardwareAddress && hardwareAddress + size >= region.hardwareAddress + region.size) 1.249 + { 1.250 + // erase end of region 1.251 + region.size = hardwareAddress - region.hardwareAddress; 1.252 + return 1; 1.253 + } 1.254 + else if(hardwareAddress <= region.hardwareAddress && hardwareAddress + size < region.hardwareAddress + region.size) 1.255 + { 1.256 + // erase start of region 1.257 + int eraseSize = (hardwareAddress + size) - region.hardwareAddress; 1.258 + region.hardwareAddress += eraseSize; 1.259 + region.size -= eraseSize; 1.260 + region.softwareAddress += eraseSize; 1.261 + region.virtualIndex += eraseSize; 1.262 + return 1; 1.263 + } 1.264 + else if(hardwareAddress <= region.hardwareAddress && hardwareAddress + size >= region.hardwareAddress + region.size) 1.265 + { 1.266 + // erase entire region 1.267 + iter = s_activeMemoryRegions.erase(iter); 1.268 + s_itemIndicesInvalid = TRUE; 1.269 + return 2; 1.270 + } 1.271 + else //if(hardwareAddress > region.hardwareAddress && hardwareAddress + size < region.hardwareAddress + region.size) 1.272 + { 1.273 + // split region 1.274 + int eraseSize = (hardwareAddress + size) - region.hardwareAddress; 1.275 + MemoryRegion region2 = {region.hardwareAddress + eraseSize, region.size - eraseSize, region.softwareAddress + eraseSize, region.virtualIndex + eraseSize}; 1.276 + region.size = hardwareAddress - region.hardwareAddress; 1.277 + iter = s_activeMemoryRegions.insert(++iter, region2); 1.278 + s_itemIndicesInvalid = TRUE; 1.279 + return 2; 1.280 + } 1.281 +} 1.282 + 1.283 +/* 1.284 +// eliminates a range of hardware addresses from the search results 1.285 +// this is a simpler but usually slower interface for the above function 1.286 +void DeactivateRegion(HWAddressType hardwareAddress, unsigned int size) 1.287 +{ 1.288 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ) 1.289 + { 1.290 + MemoryRegion& region = *iter; 1.291 + if(2 != DeactivateRegion(region, iter, hardwareAddress, size)) 1.292 + ++iter; 1.293 + } 1.294 +} 1.295 +*/ 1.296 + 1.297 +struct AutoCritSect 1.298 +{ 1.299 + AutoCritSect(CRITICAL_SECTION* cs) : m_cs(cs) { EnterCriticalSection(m_cs); } 1.300 + ~AutoCritSect() { LeaveCriticalSection(m_cs); } 1.301 + CRITICAL_SECTION* m_cs; 1.302 +}; 1.303 + 1.304 +// warning: can be slow 1.305 +void CalculateItemIndices(int itemSize) 1.306 +{ 1.307 + AutoCritSect cs(&s_activeMemoryRegionsCS); 1.308 + unsigned int itemIndex = 0; 1.309 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ++iter) 1.310 + { 1.311 + MemoryRegion& region = *iter; 1.312 + region.itemIndex = itemIndex; 1.313 + int startSkipSize = ((unsigned int)(itemSize - (unsigned int)region.hardwareAddress)) % itemSize; // FIXME: is this still ok? 1.314 + unsigned int start = startSkipSize; 1.315 + unsigned int end = region.size; 1.316 + for(unsigned int i = start; i < end; i += itemSize) 1.317 + s_itemIndexToRegionPointer[itemIndex++] = ®ion; 1.318 + } 1.319 + s_maxItemIndex = itemIndex; 1.320 + s_itemIndicesInvalid = FALSE; 1.321 +} 1.322 + 1.323 +template<typename stepType, typename compareType> 1.324 +void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr) 1.325 +{ 1.326 + //if(GetAsyncKeyState(VK_SHIFT) & 0x8000) // speed hack 1.327 + // return; 1.328 + 1.329 + if(s_prevValuesNeedUpdate) 1.330 + memcpy(s_prevValues + region.virtualIndex, s_curValues + region.virtualIndex, region.size + sizeof(compareType) - sizeof(stepType)); 1.331 + 1.332 + unsigned int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.333 + 1.334 + 1.335 + unsigned char* sourceAddr = region.softwareAddress - region.virtualIndex; 1.336 + 1.337 + unsigned int indexStart = region.virtualIndex + startSkipSize; 1.338 + unsigned int indexEnd = region.virtualIndex + region.size; 1.339 + 1.340 + if(sizeof(compareType) == 1) 1.341 + { 1.342 + for(unsigned int i = indexStart; i < indexEnd; i++) 1.343 + { 1.344 + if(s_curValues[i] != sourceAddr[i]) // if value changed 1.345 + { 1.346 + s_curValues[i] = sourceAddr[i]; // update value 1.347 + //if(s_numChanges[i] != 0xFFFF) 1.348 + s_numChanges[i]++; // increase change count 1.349 + } 1.350 + } 1.351 + } 1.352 + else // it's more complicated for non-byte sizes because: 1.353 + { // - more than one byte can affect a given change count entry 1.354 + // - when more than one of those bytes changes simultaneously the entry's change count should only increase by 1 1.355 + // - a few of those bytes can be outside the region 1.356 + 1.357 + unsigned int endSkipSize = ((unsigned int)(startSkipSize - region.size)) % sizeof(stepType); 1.358 + unsigned int lastIndexToRead = indexEnd + endSkipSize + sizeof(compareType) - sizeof(stepType); 1.359 + unsigned int lastIndexToCopy = lastIndexToRead; 1.360 + if(nextRegionPtr) 1.361 + { 1.362 + const MemoryRegion& nextRegion = *nextRegionPtr; 1.363 + int nextStartSkipSize = ((unsigned int)(sizeof(stepType) - nextRegion.hardwareAddress)) % sizeof(stepType); 1.364 + unsigned int nextIndexStart = nextRegion.virtualIndex + nextStartSkipSize; 1.365 + if(lastIndexToCopy > nextIndexStart) 1.366 + lastIndexToCopy = nextIndexStart; 1.367 + } 1.368 + 1.369 + unsigned int nextValidChange [sizeof(compareType)]; 1.370 + for(unsigned int i = 0; i < sizeof(compareType); i++) 1.371 + nextValidChange[i] = indexStart + i; 1.372 + 1.373 + for(unsigned int i = indexStart, j = 0; i < lastIndexToRead; i++, j++) 1.374 + { 1.375 + if(s_curValues[i] != sourceAddr[i]) // if value of this byte changed 1.376 + { 1.377 + if(i < lastIndexToCopy) 1.378 + s_curValues[i] = sourceAddr[i]; // update value 1.379 + for(int k = 0; k < sizeof(compareType); k++) // loop through the previous entries that contain this byte 1.380 + { 1.381 + if(i >= indexEnd+k) 1.382 + continue; 1.383 + int m = (j-k+sizeof(compareType)) & (sizeof(compareType)-1); 1.384 + if(nextValidChange[m] <= i) // if we didn't already increase the change count for this entry 1.385 + { 1.386 + //if(s_numChanges[i-k] != 0xFFFF) 1.387 + s_numChanges[i-k]++; // increase the change count for this entry 1.388 + nextValidChange[m] = i-k+sizeof(compareType); // and remember not to increase it again 1.389 + } 1.390 + } 1.391 + } 1.392 + } 1.393 + } 1.394 +} 1.395 + 1.396 +template<typename stepType, typename compareType> 1.397 +void UpdateRegionsT() 1.398 +{ 1.399 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end();) 1.400 + { 1.401 + const MemoryRegion& region = *iter; 1.402 + ++iter; 1.403 + const MemoryRegion* nextRegion = (iter == s_activeMemoryRegions.end()) ? NULL : &*iter; 1.404 + 1.405 + UpdateRegionT<stepType, compareType>(region, nextRegion); 1.406 + } 1.407 + 1.408 + s_prevValuesNeedUpdate = false; 1.409 +} 1.410 + 1.411 +template<typename stepType, typename compareType> 1.412 +int CountRegionItemsT() 1.413 +{ 1.414 + AutoCritSect cs(&s_activeMemoryRegionsCS); 1.415 + if(sizeof(stepType) == 1) 1.416 + { 1.417 + if(s_activeMemoryRegions.empty()) 1.418 + return 0; 1.419 + 1.420 + if(s_itemIndicesInvalid) 1.421 + CalculateItemIndices(sizeof(stepType)); 1.422 + 1.423 + MemoryRegion& lastRegion = s_activeMemoryRegions.back(); 1.424 + return lastRegion.itemIndex + lastRegion.size; 1.425 + } 1.426 + else // the branch above is faster but won't work if the step size isn't 1 1.427 + { 1.428 + int total = 0; 1.429 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ++iter) 1.430 + { 1.431 + MemoryRegion& region = *iter; 1.432 + int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.433 + total += (region.size - startSkipSize + (sizeof(stepType)-1)) / sizeof(stepType); 1.434 + } 1.435 + return total; 1.436 + } 1.437 +} 1.438 + 1.439 +// returns information about the item in the form of a "fake" region 1.440 +// that has the item in it and nothing else 1.441 +template<typename stepType, typename compareType> 1.442 +void ItemIndexToVirtualRegion(unsigned int itemIndex, MemoryRegion& virtualRegion) 1.443 +{ 1.444 + if(s_itemIndicesInvalid) 1.445 + CalculateItemIndices(sizeof(stepType)); 1.446 + 1.447 + if(itemIndex >= s_maxItemIndex) 1.448 + { 1.449 + memset(&virtualRegion, 0, sizeof(MemoryRegion)); 1.450 + return; 1.451 + } 1.452 + 1.453 + const MemoryRegion* regionPtr = s_itemIndexToRegionPointer[itemIndex]; 1.454 + const MemoryRegion& region = *regionPtr; 1.455 + 1.456 + int bytesWithinRegion = (itemIndex - region.itemIndex) * sizeof(stepType); 1.457 + int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.458 + bytesWithinRegion += startSkipSize; 1.459 + 1.460 + virtualRegion.size = sizeof(compareType); 1.461 + virtualRegion.hardwareAddress = region.hardwareAddress + bytesWithinRegion; 1.462 + virtualRegion.softwareAddress = region.softwareAddress + bytesWithinRegion; 1.463 + virtualRegion.virtualIndex = region.virtualIndex + bytesWithinRegion; 1.464 + virtualRegion.itemIndex = itemIndex; 1.465 + return; 1.466 +} 1.467 + 1.468 +template<typename stepType, typename compareType> 1.469 +unsigned int ItemIndexToVirtualIndex(unsigned int itemIndex) 1.470 +{ 1.471 + MemoryRegion virtualRegion; 1.472 + ItemIndexToVirtualRegion<stepType,compareType>(itemIndex, virtualRegion); 1.473 + return virtualRegion.virtualIndex; 1.474 +} 1.475 + 1.476 +template<typename T> 1.477 +T ReadLocalValue(const unsigned char* data) 1.478 +{ 1.479 + return *(const T*)data; 1.480 +} 1.481 +//template<> signed char ReadLocalValue(const unsigned char* data) { return *data; } 1.482 +//template<> unsigned char ReadLocalValue(const unsigned char* data) { return *data; } 1.483 + 1.484 + 1.485 +template<typename stepType, typename compareType> 1.486 +compareType GetPrevValueFromVirtualIndex(unsigned int virtualIndex) 1.487 +{ 1.488 + return ReadLocalValue<compareType>(s_prevValues + virtualIndex); 1.489 + //return *(compareType*)(s_prevValues+virtualIndex); 1.490 +} 1.491 +template<typename stepType, typename compareType> 1.492 +compareType GetCurValueFromVirtualIndex(unsigned int virtualIndex) 1.493 +{ 1.494 + return ReadLocalValue<compareType>(s_curValues + virtualIndex); 1.495 +// return *(compareType*)(s_curValues+virtualIndex); 1.496 +} 1.497 +template<typename stepType, typename compareType> 1.498 +unsigned short GetNumChangesFromVirtualIndex(unsigned int virtualIndex) 1.499 +{ 1.500 + unsigned short num = s_numChanges[virtualIndex]; 1.501 + //for(unsigned int i = 1; i < sizeof(stepType); i++) 1.502 + // if(num < s_numChanges[virtualIndex+i]) 1.503 + // num = s_numChanges[virtualIndex+i]; 1.504 + return num; 1.505 +} 1.506 + 1.507 +template<typename stepType, typename compareType> 1.508 +compareType GetPrevValueFromItemIndex(unsigned int itemIndex) 1.509 +{ 1.510 + int virtualIndex = ItemIndexToVirtualIndex<stepType,compareType>(itemIndex); 1.511 + return GetPrevValueFromVirtualIndex<stepType,compareType>(virtualIndex); 1.512 +} 1.513 +template<typename stepType, typename compareType> 1.514 +compareType GetCurValueFromItemIndex(unsigned int itemIndex) 1.515 +{ 1.516 + int virtualIndex = ItemIndexToVirtualIndex<stepType,compareType>(itemIndex); 1.517 + return GetCurValueFromVirtualIndex<stepType,compareType>(virtualIndex); 1.518 +} 1.519 +template<typename stepType, typename compareType> 1.520 +unsigned short GetNumChangesFromItemIndex(unsigned int itemIndex) 1.521 +{ 1.522 + int virtualIndex = ItemIndexToVirtualIndex<stepType,compareType>(itemIndex); 1.523 + return GetNumChangesFromVirtualIndex<stepType,compareType>(virtualIndex); 1.524 +} 1.525 +template<typename stepType, typename compareType> 1.526 +unsigned int GetHardwareAddressFromItemIndex(unsigned int itemIndex) 1.527 +{ 1.528 + MemoryRegion virtualRegion; 1.529 + ItemIndexToVirtualRegion<stepType,compareType>(itemIndex, virtualRegion); 1.530 + return virtualRegion.hardwareAddress; 1.531 +} 1.532 + 1.533 +// this one might be unreliable, haven't used it much 1.534 +template<typename stepType, typename compareType> 1.535 +unsigned int HardwareAddressToItemIndex(HWAddressType hardwareAddress) 1.536 +{ 1.537 + if(s_itemIndicesInvalid) 1.538 + CalculateItemIndices(sizeof(stepType)); 1.539 + 1.540 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ++iter) 1.541 + { 1.542 + MemoryRegion& region = *iter; 1.543 + if(hardwareAddress >= region.hardwareAddress && hardwareAddress < region.hardwareAddress + region.size) 1.544 + { 1.545 + int indexWithinRegion = (hardwareAddress - region.hardwareAddress) / sizeof(stepType); 1.546 + return region.itemIndex + indexWithinRegion; 1.547 + } 1.548 + } 1.549 + 1.550 + return -1; 1.551 +} 1.552 + 1.553 + 1.554 + 1.555 +// workaround for MSVC 7 that doesn't support varadic C99 macros 1.556 +#define CALL_WITH_T_SIZE_TYPES_0(functionName, sizeTypeID, isSigned, requiresAligned) \ 1.557 + (sizeTypeID == 'b' \ 1.558 + ? (isSigned \ 1.559 + ? functionName<char, signed char>() \ 1.560 + : functionName<char, unsigned char>()) \ 1.561 + : sizeTypeID == 'w' \ 1.562 + ? (isSigned \ 1.563 + ? (requiresAligned \ 1.564 + ? functionName<short, signed short>() \ 1.565 + : functionName<char, signed short>()) \ 1.566 + : (requiresAligned \ 1.567 + ? functionName<short, unsigned short>() \ 1.568 + : functionName<char, unsigned short>())) \ 1.569 + : sizeTypeID == 'd' \ 1.570 + ? (isSigned \ 1.571 + ? (requiresAligned \ 1.572 + ? functionName<short, signed long>() \ 1.573 + : functionName<char, signed long>()) \ 1.574 + : (requiresAligned \ 1.575 + ? functionName<short, unsigned long>() \ 1.576 + : functionName<char, unsigned long>())) \ 1.577 + : functionName<char, signed char>()) 1.578 + 1.579 +#define CALL_WITH_T_SIZE_TYPES_1(functionName, sizeTypeID, isSigned, requiresAligned, p0) \ 1.580 + (sizeTypeID == 'b' \ 1.581 + ? (isSigned \ 1.582 + ? functionName<char, signed char>(p0) \ 1.583 + : functionName<char, unsigned char>(p0)) \ 1.584 + : sizeTypeID == 'w' \ 1.585 + ? (isSigned \ 1.586 + ? (requiresAligned \ 1.587 + ? functionName<short, signed short>(p0) \ 1.588 + : functionName<char, signed short>(p0)) \ 1.589 + : (requiresAligned \ 1.590 + ? functionName<short, unsigned short>(p0) \ 1.591 + : functionName<char, unsigned short>(p0))) \ 1.592 + : sizeTypeID == 'd' \ 1.593 + ? (isSigned \ 1.594 + ? (requiresAligned \ 1.595 + ? functionName<short, signed long>(p0) \ 1.596 + : functionName<char, signed long>(p0)) \ 1.597 + : (requiresAligned \ 1.598 + ? functionName<short, unsigned long>(p0) \ 1.599 + : functionName<char, unsigned long>(p0))) \ 1.600 + : functionName<char, signed char>(p0)) 1.601 + 1.602 +#define CALL_WITH_T_SIZE_TYPES_3(functionName, sizeTypeID, isSigned, requiresAligned, p0, p1, p2) \ 1.603 + (sizeTypeID == 'b' \ 1.604 + ? (isSigned \ 1.605 + ? functionName<char, signed char>(p0, p1, p2) \ 1.606 + : functionName<char, unsigned char>(p0, p1, p2)) \ 1.607 + : sizeTypeID == 'w' \ 1.608 + ? (isSigned \ 1.609 + ? (requiresAligned \ 1.610 + ? functionName<short, signed short>(p0, p1, p2) \ 1.611 + : functionName<char, signed short>(p0, p1, p2)) \ 1.612 + : (requiresAligned \ 1.613 + ? functionName<short, unsigned short>(p0, p1, p2) \ 1.614 + : functionName<char, unsigned short>(p0, p1, p2))) \ 1.615 + : sizeTypeID == 'd' \ 1.616 + ? (isSigned \ 1.617 + ? (requiresAligned \ 1.618 + ? functionName<short, signed long>(p0, p1, p2) \ 1.619 + : functionName<char, signed long>(p0, p1, p2)) \ 1.620 + : (requiresAligned \ 1.621 + ? functionName<short, unsigned long>(p0, p1, p2) \ 1.622 + : functionName<char, unsigned long>(p0, p1, p2))) \ 1.623 + : functionName<char, signed char>(p0, p1, p2)) 1.624 + 1.625 +#define CALL_WITH_T_SIZE_TYPES_4(functionName, sizeTypeID, isSigned, requiresAligned, p0, p1, p2, p3) \ 1.626 + (sizeTypeID == 'b' \ 1.627 + ? (isSigned \ 1.628 + ? functionName<char, signed char>(p0, p1, p2, p3) \ 1.629 + : functionName<char, unsigned char>(p0, p1, p2, p3)) \ 1.630 + : sizeTypeID == 'w' \ 1.631 + ? (isSigned \ 1.632 + ? (requiresAligned \ 1.633 + ? functionName<short, signed short>(p0, p1, p2, p3) \ 1.634 + : functionName<char, signed short>(p0, p1, p2, p3)) \ 1.635 + : (requiresAligned \ 1.636 + ? functionName<short, unsigned short>(p0, p1, p2, p3) \ 1.637 + : functionName<char, unsigned short>(p0, p1, p2, p3))) \ 1.638 + : sizeTypeID == 'd' \ 1.639 + ? (isSigned \ 1.640 + ? (requiresAligned \ 1.641 + ? functionName<short, signed long>(p0, p1, p2, p3) \ 1.642 + : functionName<char, signed long>(p0, p1, p2, p3)) \ 1.643 + : (requiresAligned \ 1.644 + ? functionName<short, unsigned long>(p0, p1, p2, p3) \ 1.645 + : functionName<char, unsigned long>(p0, p1, p2, p3))) \ 1.646 + : functionName<char, signed char>(p0, p1, p2, p3)) 1.647 + 1.648 +// version that takes a forced comparison type 1.649 +#define CALL_WITH_T_STEP_3(functionName, sizeTypeID, type, requiresAligned, p0, p1, p2) \ 1.650 + (sizeTypeID == 'b' \ 1.651 + ? functionName<char, type>(p0, p1, p2) \ 1.652 + : sizeTypeID == 'w' \ 1.653 + ? (requiresAligned \ 1.654 + ? functionName<short, type>(p0, p1, p2) \ 1.655 + : functionName<char, type>(p0, p1, p2)) \ 1.656 + : sizeTypeID == 'd' \ 1.657 + ? (requiresAligned \ 1.658 + ? functionName<short, type>(p0, p1, p2) \ 1.659 + : functionName<char, type>(p0, p1, p2)) \ 1.660 + : functionName<char, type>(p0, p1, p2)) 1.661 + 1.662 +// version that takes a forced comparison type 1.663 +#define CALL_WITH_T_STEP_4(functionName, sizeTypeID, type, requiresAligned, p0, p1, p2, p3) \ 1.664 + (sizeTypeID == 'b' \ 1.665 + ? functionName<char, type>(p0, p1, p2, p3) \ 1.666 + : sizeTypeID == 'w' \ 1.667 + ? (requiresAligned \ 1.668 + ? functionName<short, type>(p0, p1, p2, p3) \ 1.669 + : functionName<char, type>(p0, p1, p2, p3)) \ 1.670 + : sizeTypeID == 'd' \ 1.671 + ? (requiresAligned \ 1.672 + ? functionName<short, type>(p0, p1, p2, p3) \ 1.673 + : functionName<char, type>(p0, p1, p2, p3)) \ 1.674 + : functionName<char, type>(p0, p1, p2, p3)) 1.675 + 1.676 +// basic comparison functions: 1.677 +template <typename T> inline bool LessCmp (T x, T y, T i) { return x < y; } 1.678 +template <typename T> inline bool MoreCmp (T x, T y, T i) { return x > y; } 1.679 +template <typename T> inline bool LessEqualCmp (T x, T y, T i) { return x <= y; } 1.680 +template <typename T> inline bool MoreEqualCmp (T x, T y, T i) { return x >= y; } 1.681 +template <typename T> inline bool EqualCmp (T x, T y, T i) { return x == y; } 1.682 +template <typename T> inline bool UnequalCmp (T x, T y, T i) { return x != y; } 1.683 +template <typename T> inline bool DiffByCmp (T x, T y, T p) { return x - y == p || y - x == p; } 1.684 +template <typename T> inline bool ModIsCmp (T x, T y, T p) { return p && x % p == y; } 1.685 + 1.686 +// compare-to type functions: 1.687 +template<typename stepType, typename T> 1.688 +void SearchRelative (bool(*cmpFun)(T,T,T), T ignored, T param) 1.689 +{ 1.690 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ) 1.691 + { 1.692 + MemoryRegion& region = *iter; 1.693 + int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.694 + unsigned int start = region.virtualIndex + startSkipSize; 1.695 + unsigned int end = region.virtualIndex + region.size; 1.696 + for(unsigned int i = start, hwaddr = region.hardwareAddress; i < end; i += sizeof(stepType), hwaddr += sizeof(stepType)) 1.697 + if(!cmpFun(GetCurValueFromVirtualIndex<stepType,T>(i), GetPrevValueFromVirtualIndex<stepType,T>(i), param)) 1.698 + if(2 == DeactivateRegion(region, iter, hwaddr, sizeof(stepType))) 1.699 + goto outerContinue; 1.700 + ++iter; 1.701 +outerContinue: 1.702 + continue; 1.703 + } 1.704 +} 1.705 +template<typename stepType, typename T> 1.706 +void SearchSpecific (bool(*cmpFun)(T,T,T), T value, T param) 1.707 +{ 1.708 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ) 1.709 + { 1.710 + MemoryRegion& region = *iter; 1.711 + int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.712 + unsigned int start = region.virtualIndex + startSkipSize; 1.713 + unsigned int end = region.virtualIndex + region.size; 1.714 + for(unsigned int i = start, hwaddr = region.hardwareAddress; i < end; i += sizeof(stepType), hwaddr += sizeof(stepType)) 1.715 + if(!cmpFun(GetCurValueFromVirtualIndex<stepType,T>(i), value, param)) 1.716 + if(2 == DeactivateRegion(region, iter, hwaddr, sizeof(stepType))) 1.717 + goto outerContinue; 1.718 + ++iter; 1.719 +outerContinue: 1.720 + continue; 1.721 + } 1.722 +} 1.723 +template<typename stepType, typename T> 1.724 +void SearchAddress (bool(*cmpFun)(T,T,T), T address, T param) 1.725 +{ 1.726 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ) 1.727 + { 1.728 + MemoryRegion& region = *iter; 1.729 + int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.730 + unsigned int start = region.virtualIndex + startSkipSize; 1.731 + unsigned int end = region.virtualIndex + region.size; 1.732 + for(unsigned int i = start, hwaddr = region.hardwareAddress; i < end; i += sizeof(stepType), hwaddr += sizeof(stepType)) 1.733 + if(!cmpFun(hwaddr, address, param)) 1.734 + if(2 == DeactivateRegion(region, iter, hwaddr, sizeof(stepType))) 1.735 + goto outerContinue; 1.736 + ++iter; 1.737 +outerContinue: 1.738 + continue; 1.739 + } 1.740 +} 1.741 +template<typename stepType, typename T> 1.742 +void SearchChanges (bool(*cmpFun)(T,T,T), T changes, T param) 1.743 +{ 1.744 + for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ) 1.745 + { 1.746 + MemoryRegion& region = *iter; 1.747 + int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType); 1.748 + unsigned int start = region.virtualIndex + startSkipSize; 1.749 + unsigned int end = region.virtualIndex + region.size; 1.750 + for(unsigned int i = start, hwaddr = region.hardwareAddress; i < end; i += sizeof(stepType), hwaddr += sizeof(stepType)) 1.751 + if(!cmpFun(GetNumChangesFromVirtualIndex<stepType,T>(i), changes, param)) 1.752 + if(2 == DeactivateRegion(region, iter, hwaddr, sizeof(stepType))) 1.753 + goto outerContinue; 1.754 + ++iter; 1.755 +outerContinue: 1.756 + continue; 1.757 + } 1.758 +} 1.759 + 1.760 +char rs_c='s'; 1.761 +char rs_o='='; 1.762 +char rs_t='s'; 1.763 +int rs_param=0, rs_val=0, rs_val_valid=0; 1.764 +char rs_type_size = 'b', rs_last_type_size = rs_type_size; 1.765 +bool noMisalign = true, rs_last_no_misalign = noMisalign; 1.766 +//bool littleEndian = false; 1.767 +int last_rs_possible = -1; 1.768 +int last_rs_regions = -1; 1.769 + 1.770 +void prune(char c,char o,char t,int v,int p) 1.771 +{ 1.772 + // repetition-reducing macros 1.773 + #define DO_SEARCH(sf) \ 1.774 + switch (o) \ 1.775 + { \ 1.776 + case '<': DO_SEARCH_2(LessCmp,sf); break; \ 1.777 + case '>': DO_SEARCH_2(MoreCmp,sf); break; \ 1.778 + case '=': DO_SEARCH_2(EqualCmp,sf); break; \ 1.779 + case '!': DO_SEARCH_2(UnequalCmp,sf); break; \ 1.780 + case 'l': DO_SEARCH_2(LessEqualCmp,sf); break; \ 1.781 + case 'm': DO_SEARCH_2(MoreEqualCmp,sf); break; \ 1.782 + case 'd': DO_SEARCH_2(DiffByCmp,sf); break; \ 1.783 + case '%': DO_SEARCH_2(ModIsCmp,sf); break; \ 1.784 + default: assert(!"Invalid operator for this search type."); break; \ 1.785 + } 1.786 + 1.787 + // perform the search, eliminating nonmatching values 1.788 + switch (c) 1.789 + { 1.790 + #define DO_SEARCH_2(CmpFun,sf) CALL_WITH_T_SIZE_TYPES_3(sf, rs_type_size, t, noMisalign, CmpFun,v,p) 1.791 + case 'r': DO_SEARCH(SearchRelative); break; 1.792 + case 's': DO_SEARCH(SearchSpecific); break; 1.793 + 1.794 + #undef DO_SEARCH_2 1.795 + #define DO_SEARCH_2(CmpFun,sf) CALL_WITH_T_STEP_3(sf, rs_type_size, unsigned int, noMisalign, CmpFun,v,p) 1.796 + case 'a': DO_SEARCH(SearchAddress); break; 1.797 + 1.798 + #undef DO_SEARCH_2 1.799 + #define DO_SEARCH_2(CmpFun,sf) CALL_WITH_T_STEP_3(sf, rs_type_size, unsigned short, noMisalign, CmpFun,v,p) 1.800 + case 'n': DO_SEARCH(SearchChanges); break; 1.801 + 1.802 + default: assert(!"Invalid search comparison type."); break; 1.803 + } 1.804 + 1.805 + s_prevValuesNeedUpdate = true; 1.806 + 1.807 + int prevNumItems = last_rs_possible; 1.808 + 1.809 + CompactAddrs(); 1.810 + 1.811 + if(prevNumItems == last_rs_possible) 1.812 + { 1.813 + SetRamSearchUndoType(RamSearchHWnd, 0); // nothing to undo 1.814 + } 1.815 +} 1.816 + 1.817 + 1.818 + 1.819 + 1.820 +template<typename stepType, typename T> 1.821 +bool CompareRelativeAtItem (bool(*cmpFun)(T,T,T), int itemIndex, T ignored, T param) 1.822 +{ 1.823 + return cmpFun(GetCurValueFromItemIndex<stepType,T>(itemIndex), GetPrevValueFromItemIndex<stepType,T>(itemIndex), param); 1.824 +} 1.825 +template<typename stepType, typename T> 1.826 +bool CompareSpecificAtItem (bool(*cmpFun)(T,T,T), int itemIndex, T value, T param) 1.827 +{ 1.828 + return cmpFun(GetCurValueFromItemIndex<stepType,T>(itemIndex), value, param); 1.829 +} 1.830 +template<typename stepType, typename T> 1.831 +bool CompareAddressAtItem (bool(*cmpFun)(T,T,T), int itemIndex, T address, T param) 1.832 +{ 1.833 + return cmpFun(GetHardwareAddressFromItemIndex<stepType,T>(itemIndex), address, param); 1.834 +} 1.835 +template<typename stepType, typename T> 1.836 +bool CompareChangesAtItem (bool(*cmpFun)(T,T,T), int itemIndex, T changes, T param) 1.837 +{ 1.838 + return cmpFun(GetNumChangesFromItemIndex<stepType,T>(itemIndex), changes, param); 1.839 +} 1.840 + 1.841 +int ReadControlInt(int controlID, bool forceHex, BOOL& success) 1.842 +{ 1.843 + int rv = 0; 1.844 + BOOL ok = false; 1.845 + 1.846 + if(!forceHex) 1.847 + { 1.848 + rv = GetDlgItemInt(RamSearchHWnd,controlID,&ok,(rs_t == 's')); 1.849 + } 1.850 + 1.851 + if(!ok) 1.852 + { 1.853 + if(GetDlgItemText(RamSearchHWnd,controlID,Str_Tmp,16)) 1.854 + { 1.855 + for(int i = 0; Str_Tmp[i]; i++) {if(toupper(Str_Tmp[i]) == 'O') Str_Tmp[i] = '0';} 1.856 + const char* strPtr = Str_Tmp; 1.857 + bool negate = false; 1.858 + while(strPtr[0] == '-') 1.859 + strPtr++, negate = !negate; 1.860 + if(strPtr[0] == '+') 1.861 + strPtr++; 1.862 + if(strPtr[0] == '0' && tolower(strPtr[1]) == 'x') 1.863 + strPtr += 2, forceHex = true; 1.864 + if(strPtr[0] == '$') 1.865 + strPtr++, forceHex = true; 1.866 + if(!forceHex) 1.867 + { 1.868 + const char* strSearchPtr = strPtr; 1.869 + while(*strSearchPtr) 1.870 + { 1.871 + int c = tolower(*strSearchPtr++); 1.872 + if(c >= 'a' && c <= 'f') 1.873 + forceHex = true; 1.874 + } 1.875 + } 1.876 + const char* formatString = forceHex ? "%X" : ((rs_t=='s') ? "%d" : "%u"); 1.877 + if(sscanf(strPtr, formatString, &rv) > 0) 1.878 + ok = true; 1.879 + if(negate) 1.880 + rv = -rv; 1.881 + } 1.882 + } 1.883 + 1.884 + success = ok; 1.885 + return rv; 1.886 +} 1.887 + 1.888 + 1.889 +bool Set_RS_Val() 1.890 +{ 1.891 + BOOL success; 1.892 + 1.893 + // update rs_val 1.894 + switch(rs_c) 1.895 + { 1.896 + case 'r': 1.897 + default: 1.898 + rs_val = 0; 1.899 + break; 1.900 + case 's': 1.901 + rs_val = ReadControlInt(IDC_EDIT_COMPAREVALUE, rs_t == 'h', success); 1.902 + if(!success) 1.903 + return false; 1.904 + if((rs_type_size == 'b' && rs_t == 's' && (rs_val < -128 || rs_val > 127)) || 1.905 + (rs_type_size == 'b' && rs_t != 's' && (rs_val < 0 || rs_val > 255)) || 1.906 + (rs_type_size == 'w' && rs_t == 's' && (rs_val < -32768 || rs_val > 32767)) || 1.907 + (rs_type_size == 'w' && rs_t != 's' && (rs_val < 0 || rs_val > 65535))) 1.908 + return false; 1.909 + break; 1.910 + case 'a': 1.911 + rs_val = ReadControlInt(IDC_EDIT_COMPAREADDRESS, true, success); 1.912 + if(!success || rs_val < 0 || rs_val > 0x06040000) 1.913 + return false; 1.914 + break; 1.915 + case 'n': { 1.916 + rs_val = ReadControlInt(IDC_EDIT_COMPARECHANGES, false, success); 1.917 + if(!success || rs_val < 0 || rs_val > 0xFFFF) 1.918 + return false; 1.919 + } break; 1.920 + } 1.921 + 1.922 + // also update rs_param 1.923 + switch(rs_o) 1.924 + { 1.925 + default: 1.926 + rs_param = 0; 1.927 + break; 1.928 + case 'd': 1.929 + rs_param = ReadControlInt(IDC_EDIT_DIFFBY, false, success); 1.930 + if(!success) 1.931 + return false; 1.932 + if(rs_param < 0) 1.933 + rs_param = -rs_param; 1.934 + break; 1.935 + case '%': 1.936 + rs_param = ReadControlInt(IDC_EDIT_MODBY, false, success); 1.937 + if(!success || rs_param == 0) 1.938 + return false; 1.939 + break; 1.940 + } 1.941 + 1.942 + // validate that rs_param fits in the comparison data type 1.943 + { 1.944 + int appliedSize = rs_type_size; 1.945 + int appliedSign = rs_t; 1.946 + if(rs_c == 'n') 1.947 + appliedSize = 'w', appliedSign = 'u'; 1.948 + if(rs_c == 'a') 1.949 + appliedSize = 'd', appliedSign = 'u'; 1.950 + if((appliedSize == 'b' && appliedSize == 's' && (rs_param < -128 || rs_param > 127)) || 1.951 + (appliedSize == 'b' && appliedSize != 's' && (rs_param < 0 || rs_param > 255)) || 1.952 + (appliedSize == 'w' && appliedSize == 's' && (rs_param < -32768 || rs_param > 32767)) || 1.953 + (appliedSize == 'w' && appliedSize != 's' && (rs_param < 0 || rs_param > 65535))) 1.954 + return false; 1.955 + } 1.956 + 1.957 + return true; 1.958 +} 1.959 + 1.960 +bool IsSatisfied(int itemIndex) 1.961 +{ 1.962 + if(!rs_val_valid) 1.963 + return true; 1.964 + int o = rs_o; 1.965 + switch (rs_c) 1.966 + { 1.967 + #undef DO_SEARCH_2 1.968 + #define DO_SEARCH_2(CmpFun,sf) return CALL_WITH_T_SIZE_TYPES_4(sf, rs_type_size,(rs_t=='s'),noMisalign, CmpFun,itemIndex,rs_val,rs_param); 1.969 + case 'r': DO_SEARCH(CompareRelativeAtItem); break; 1.970 + case 's': DO_SEARCH(CompareSpecificAtItem); break; 1.971 + 1.972 + #undef DO_SEARCH_2 1.973 + #define DO_SEARCH_2(CmpFun,sf) return CALL_WITH_T_STEP_4(sf, rs_type_size, unsigned int, noMisalign, CmpFun,itemIndex,rs_val,rs_param); 1.974 + case 'a': DO_SEARCH(CompareAddressAtItem); break; 1.975 + 1.976 + #undef DO_SEARCH_2 1.977 + #define DO_SEARCH_2(CmpFun,sf) return CALL_WITH_T_STEP_4(sf, rs_type_size, unsigned short, noMisalign, CmpFun,itemIndex,rs_val,rs_param); 1.978 + case 'n': DO_SEARCH(CompareChangesAtItem); break; 1.979 + } 1.980 + return false; 1.981 +} 1.982 + 1.983 + 1.984 + 1.985 +unsigned int ReadValueAtSoftwareAddress(const unsigned char* address, unsigned int size) 1.986 +{ 1.987 + unsigned int value = 0; 1.988 + if(address) 1.989 + { 1.990 + // assumes we're little-endian 1.991 + memcpy(&value, address, size); 1.992 + } 1.993 + return value; 1.994 +} 1.995 +void WriteValueAtSoftwareAddress(unsigned char* address, unsigned int value, unsigned int size) 1.996 +{ 1.997 + if(address) 1.998 + { 1.999 + // assumes we're little-endian 1.1000 + memcpy(address, &value, size); 1.1001 + } 1.1002 +} 1.1003 +unsigned int ReadValueAtHardwareAddress(HWAddressType address, unsigned int size) 1.1004 +{ 1.1005 + return ReadValueAtSoftwareAddress(HardwareToSoftwareAddress(address), size); 1.1006 +} 1.1007 +bool WriteValueAtHardwareAddress(HWAddressType address, unsigned int value, unsigned int size) 1.1008 +{ 1.1009 + WriteValueAtSoftwareAddress(HardwareToSoftwareAddress(address), value, size); 1.1010 + return true; 1.1011 +} 1.1012 +bool IsHardwareAddressValid(HWAddressType address) 1.1013 +{ 1.1014 + return HardwareToSoftwareAddress(address) != NULL; 1.1015 +} 1.1016 + 1.1017 + 1.1018 + 1.1019 +int ResultCount=0; 1.1020 +bool AutoSearch=false; 1.1021 +bool AutoSearchAutoRetry=false; 1.1022 +LRESULT CALLBACK PromptWatchNameProc(HWND, UINT, WPARAM, LPARAM); 1.1023 +void UpdatePossibilities(int rs_possible, int regions); 1.1024 + 1.1025 + 1.1026 +void CompactAddrs() 1.1027 +{ 1.1028 + int size = (rs_type_size=='b' || !noMisalign) ? 1 : 2; 1.1029 + int prevResultCount = ResultCount; 1.1030 + 1.1031 + CalculateItemIndices(size); 1.1032 + ResultCount = CALL_WITH_T_SIZE_TYPES_0(CountRegionItemsT, rs_type_size,rs_t=='s',noMisalign); 1.1033 + 1.1034 + UpdatePossibilities(ResultCount, (int)s_activeMemoryRegions.size()); 1.1035 + 1.1036 + if(ResultCount != prevResultCount) 1.1037 + ListView_SetItemCount(GetDlgItem(RamSearchHWnd,IDC_RAMLIST),ResultCount); 1.1038 +} 1.1039 + 1.1040 +void soft_reset_address_info () 1.1041 +{ 1.1042 + s_prevValuesNeedUpdate = false; 1.1043 + ResetMemoryRegions(); 1.1044 + if(!RamSearchHWnd) 1.1045 + { 1.1046 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.1047 + s_activeMemoryRegions.clear(); 1.1048 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.1049 + ResultCount = 0; 1.1050 + } 1.1051 + else 1.1052 + { 1.1053 + // force s_prevValues to be valid 1.1054 + signal_new_frame(); 1.1055 + s_prevValuesNeedUpdate = true; 1.1056 + signal_new_frame(); 1.1057 + } 1.1058 + if(s_numChanges) 1.1059 + memset(s_numChanges, 0, (sizeof(*s_numChanges)*(MAX_RAM_SIZE))); 1.1060 + CompactAddrs(); 1.1061 +} 1.1062 +void reset_address_info () 1.1063 +{ 1.1064 + SetRamSearchUndoType(RamSearchHWnd, 0); 1.1065 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.1066 + s_activeMemoryRegionsBackup.clear(); // not necessary, but we'll take the time hit here instead of at the next thing that sets up an undo 1.1067 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.1068 + if(s_prevValues) 1.1069 + memcpy(s_prevValues, s_curValues, (sizeof(*s_prevValues)*(MAX_RAM_SIZE))); 1.1070 + s_prevValuesNeedUpdate = false; 1.1071 + ResetMemoryRegions(); 1.1072 + if(!RamSearchHWnd) 1.1073 + { 1.1074 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.1075 + s_activeMemoryRegions.clear(); 1.1076 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.1077 + ResultCount = 0; 1.1078 + } 1.1079 + else 1.1080 + { 1.1081 + // force s_prevValues to be valid 1.1082 + signal_new_frame(); 1.1083 + s_prevValuesNeedUpdate = true; 1.1084 + signal_new_frame(); 1.1085 + } 1.1086 + memset(s_numChanges, 0, (sizeof(*s_numChanges)*(MAX_RAM_SIZE))); 1.1087 + CompactAddrs(); 1.1088 +} 1.1089 + 1.1090 +void signal_new_frame () 1.1091 +{ 1.1092 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.1093 + CALL_WITH_T_SIZE_TYPES_0(UpdateRegionsT, rs_type_size, rs_t=='s', noMisalign); 1.1094 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.1095 +} 1.1096 + 1.1097 + 1.1098 + 1.1099 + 1.1100 + 1.1101 +bool RamSearchClosed = false; 1.1102 +bool RamWatchClosed = false; 1.1103 + 1.1104 +void ResetResults() 1.1105 +{ 1.1106 + reset_address_info(); 1.1107 + ResultCount = 0; 1.1108 + if (RamSearchHWnd) 1.1109 + ListView_SetItemCount(GetDlgItem(RamSearchHWnd,IDC_RAMLIST),ResultCount); 1.1110 +} 1.1111 +void CloseRamWindows() //Close the Ram Search & Watch windows when rom closes 1.1112 +{ 1.1113 + ResetWatches(); 1.1114 + ResetResults(); 1.1115 + if (RamSearchHWnd) 1.1116 + { 1.1117 + SendMessage(RamSearchHWnd,WM_CLOSE,NULL,NULL); 1.1118 + RamSearchClosed = true; 1.1119 + } 1.1120 + if (RamWatchHWnd) 1.1121 + { 1.1122 + SendMessage(RamWatchHWnd,WM_CLOSE,NULL,NULL); 1.1123 + RamWatchClosed = true; 1.1124 + } 1.1125 +} 1.1126 +void ReopenRamWindows() //Reopen them when a new Rom is loaded 1.1127 +{ 1.1128 + HWND hwnd = GetActiveWindow(); 1.1129 + 1.1130 + if (RamSearchClosed) 1.1131 + { 1.1132 + RamSearchClosed = false; 1.1133 + if(!RamSearchHWnd) 1.1134 + { 1.1135 + reset_address_info(); 1.1136 + LRESULT CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 1.1137 + RamSearchHWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_RAMSEARCH), hWnd, (DLGPROC) RamSearchProc); 1.1138 + } 1.1139 + else 1.1140 + ::SetForegroundWindow(RamSearchHWnd); 1.1141 + } 1.1142 + if (RamWatchClosed || AutoRWLoad) 1.1143 + { 1.1144 + RamWatchClosed = false; 1.1145 + if(!RamWatchHWnd) 1.1146 + { 1.1147 + if (AutoRWLoad) OpenRWRecentFile(0); 1.1148 + LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 1.1149 + RamWatchHWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_RAMWATCH), hWnd, (DLGPROC) RamWatchProc); 1.1150 + } 1.1151 + else 1.1152 + ::SetForegroundWindow(RamWatchHWnd); 1.1153 + } 1.1154 + 1.1155 + if (hwnd == hWnd && hwnd != GetActiveWindow()) 1.1156 + SetActiveWindow(hWnd); // restore focus to the main window if it had it before 1.1157 +} 1.1158 + 1.1159 + 1.1160 + 1.1161 + 1.1162 + 1.1163 +void RefreshRamListSelectedCountControlStatus(HWND hDlg) 1.1164 +{ 1.1165 + int selCount = ListView_GetSelectedCount(GetDlgItem(hDlg,IDC_RAMLIST)); 1.1166 + if(selCount != s_prevSelCount) 1.1167 + { 1.1168 + if(selCount < 2 || s_prevSelCount < 2) 1.1169 + { 1.1170 + EnableWindow(GetDlgItem(hDlg, IDC_C_WATCH), (WatchCount < MAX_WATCH_COUNT) ? TRUE : FALSE); 1.1171 + EnableWindow(GetDlgItem(hDlg, IDC_C_ADDCHEAT), (selCount >= 1) ? TRUE : FALSE); 1.1172 + EnableWindow(GetDlgItem(hDlg, IDC_C_ELIMINATE), (selCount >= 1) ? TRUE : FALSE); 1.1173 + } 1.1174 + s_prevSelCount = selCount; 1.1175 + } 1.1176 +} 1.1177 + 1.1178 + 1.1179 + 1.1180 + 1.1181 +struct AddrRange 1.1182 +{ 1.1183 + unsigned int addr; 1.1184 + unsigned int size; 1.1185 + unsigned int End() const { return addr + size; } 1.1186 + AddrRange(unsigned int a, unsigned int s) : addr(a),size(s){} 1.1187 +}; 1.1188 + 1.1189 +void signal_new_size () 1.1190 +{ 1.1191 + HWND lv = GetDlgItem(RamSearchHWnd,IDC_RAMLIST); 1.1192 + 1.1193 + int oldSize = (rs_last_type_size=='b' || !rs_last_no_misalign) ? 1 : 2; 1.1194 + int newSize = (rs_type_size=='b' || !noMisalign) ? 1 : 2; 1.1195 + bool numberOfItemsChanged = (oldSize != newSize); 1.1196 + 1.1197 + unsigned int itemsPerPage = ListView_GetCountPerPage(lv); 1.1198 + unsigned int oldTopIndex = ListView_GetTopIndex(lv); 1.1199 + unsigned int oldSelectionIndex = ListView_GetSelectionMark(lv); 1.1200 + unsigned int oldTopAddr = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_last_type_size,rs_t=='s',rs_last_no_misalign, oldTopIndex); 1.1201 + unsigned int oldSelectionAddr = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_last_type_size,rs_t=='s',rs_last_no_misalign, oldSelectionIndex); 1.1202 + 1.1203 + std::vector<AddrRange> selHardwareAddrs; 1.1204 + if(numberOfItemsChanged) 1.1205 + { 1.1206 + // store selection ranges 1.1207 + // unfortunately this can take a while if the user has a huge range of items selected 1.1208 + systemSoundClearBuffer(); 1.1209 + int selCount = ListView_GetSelectedCount(lv); 1.1210 + int size = (rs_last_type_size=='b' || !rs_last_no_misalign) ? 1 : 2; 1.1211 + int watchIndex = -1; 1.1212 + for(int i = 0; i < selCount; ++i) 1.1213 + { 1.1214 + watchIndex = ListView_GetNextItem(lv, watchIndex, LVNI_SELECTED); 1.1215 + int addr = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_last_type_size,rs_t=='s',rs_last_no_misalign, watchIndex); 1.1216 + if(!selHardwareAddrs.empty() && addr == selHardwareAddrs.back().End()) 1.1217 + selHardwareAddrs.back().size += size; 1.1218 + else if (!(noMisalign && oldSize < newSize && addr % newSize != 0)) 1.1219 + selHardwareAddrs.push_back(AddrRange(addr,size)); 1.1220 + } 1.1221 + } 1.1222 + 1.1223 + CompactAddrs(); 1.1224 + 1.1225 + rs_last_type_size = rs_type_size; 1.1226 + rs_last_no_misalign = noMisalign; 1.1227 + 1.1228 + if(numberOfItemsChanged) 1.1229 + { 1.1230 + // restore selection ranges 1.1231 + unsigned int newTopIndex = CALL_WITH_T_SIZE_TYPES_1(HardwareAddressToItemIndex, rs_type_size,rs_t=='s',noMisalign, oldTopAddr); 1.1232 + unsigned int newBottomIndex = newTopIndex + itemsPerPage - 1; 1.1233 + SendMessage(lv, WM_SETREDRAW, FALSE, 0); 1.1234 + ListView_SetItemState(lv, -1, 0, LVIS_SELECTED|LVIS_FOCUSED); // deselect all 1.1235 + for(unsigned int i = 0; i < selHardwareAddrs.size(); i++) 1.1236 + { 1.1237 + // calculate index ranges of this selection 1.1238 + const AddrRange& range = selHardwareAddrs[i]; 1.1239 + int selRangeTop = CALL_WITH_T_SIZE_TYPES_1(HardwareAddressToItemIndex, rs_type_size,rs_t=='s',noMisalign, range.addr); 1.1240 + int selRangeBottom = -1; 1.1241 + for(int endAddr = range.End()-1; endAddr >= selRangeTop && selRangeBottom == -1; endAddr--) 1.1242 + selRangeBottom = CALL_WITH_T_SIZE_TYPES_1(HardwareAddressToItemIndex, rs_type_size,rs_t=='s',noMisalign, endAddr); 1.1243 + if(selRangeBottom == -1) 1.1244 + selRangeBottom = selRangeTop; 1.1245 + if(selRangeTop == -1) 1.1246 + continue; 1.1247 + 1.1248 + // select the entire range 1.1249 + for (int j = selRangeTop; j <= selRangeBottom; j++) 1.1250 + { 1.1251 + ListView_SetItemState(lv, j, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); 1.1252 + } 1.1253 + } 1.1254 + 1.1255 + // restore previous scroll position 1.1256 + if(newBottomIndex != -1) 1.1257 + ListView_EnsureVisible(lv, newBottomIndex, 0); 1.1258 + if(newTopIndex != -1) 1.1259 + ListView_EnsureVisible(lv, newTopIndex, 0); 1.1260 + 1.1261 + SendMessage(lv, WM_SETREDRAW, TRUE, 0); 1.1262 + 1.1263 + RefreshRamListSelectedCountControlStatus(RamSearchHWnd); 1.1264 + 1.1265 + EnableWindow(GetDlgItem(RamSearchHWnd,IDC_MISALIGN), rs_type_size != 'b'); 1.1266 + } 1.1267 + else 1.1268 + { 1.1269 + ListView_Update(lv, -1); 1.1270 + } 1.1271 + InvalidateRect(lv, NULL, TRUE); 1.1272 + //SetFocus(lv); 1.1273 +} 1.1274 + 1.1275 + 1.1276 + 1.1277 + 1.1278 +LRESULT CustomDraw (LPARAM lParam) 1.1279 +{ 1.1280 + LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam; 1.1281 + 1.1282 + switch(lplvcd->nmcd.dwDrawStage) 1.1283 + { 1.1284 + case CDDS_PREPAINT : 1.1285 + return CDRF_NOTIFYITEMDRAW; 1.1286 + 1.1287 + case CDDS_ITEMPREPAINT: 1.1288 + { 1.1289 + int rv = CDRF_DODEFAULT; 1.1290 + 1.1291 + if(lplvcd->nmcd.dwItemSpec % 2) 1.1292 + { 1.1293 + // alternate the background color slightly 1.1294 + lplvcd->clrTextBk = RGB(248,248,255); 1.1295 + rv = CDRF_NEWFONT; 1.1296 + } 1.1297 + 1.1298 + if(!IsSatisfied(lplvcd->nmcd.dwItemSpec)) 1.1299 + { 1.1300 + // tint red any items that would be eliminated if a search were to run now 1.1301 + lplvcd->clrText = RGB(192,64,64); 1.1302 + rv = CDRF_NEWFONT; 1.1303 + } 1.1304 + 1.1305 + return rv; 1.1306 + } break; 1.1307 + } 1.1308 + return CDRF_DODEFAULT; 1.1309 +} 1.1310 + 1.1311 +void Update_RAM_Search() //keeps RAM values up to date in the search and watch windows 1.1312 +{ 1.1313 + if(disableRamSearchUpdate) 1.1314 + return; 1.1315 + 1.1316 + int prevValuesNeededUpdate; 1.1317 + if (AutoSearch && !ResultCount) 1.1318 + { 1.1319 + if(!AutoSearchAutoRetry) 1.1320 + { 1.1321 + systemSoundClearBuffer(); 1.1322 + int answer = MessageBox(RamSearchHWnd,"Choosing Retry will reset the search once and continue autosearching.\nChoose Ignore will reset the search whenever necessary and continue autosearching.\nChoosing Abort will reset the search once and stop autosearching.","Autosearch - out of results.",MB_ABORTRETRYIGNORE|MB_DEFBUTTON2|MB_ICONINFORMATION); 1.1323 + if(answer == IDABORT) 1.1324 + { 1.1325 + SendDlgItemMessage(RamSearchHWnd, IDC_C_AUTOSEARCH, BM_SETCHECK, BST_UNCHECKED, 0); 1.1326 + SendMessage(RamSearchHWnd, WM_COMMAND, IDC_C_AUTOSEARCH, 0); 1.1327 + } 1.1328 + if(answer == IDIGNORE) 1.1329 + AutoSearchAutoRetry = true; 1.1330 + } 1.1331 + reset_address_info(); 1.1332 + prevValuesNeededUpdate = s_prevValuesNeedUpdate; 1.1333 + } 1.1334 + else 1.1335 + { 1.1336 + prevValuesNeededUpdate = s_prevValuesNeedUpdate; 1.1337 + if (RamSearchHWnd) 1.1338 + { 1.1339 + // update active RAM values 1.1340 + signal_new_frame(); 1.1341 + } 1.1342 + 1.1343 + if (AutoSearch && ResultCount) 1.1344 + { 1.1345 + systemSoundClearBuffer(); 1.1346 + if(!rs_val_valid) 1.1347 + rs_val_valid = Set_RS_Val(); 1.1348 + if(rs_val_valid) 1.1349 + prune(rs_c,rs_o,rs_t=='s',rs_val,rs_param); 1.1350 + } 1.1351 + } 1.1352 + 1.1353 + if(RamSearchHWnd) 1.1354 + { 1.1355 + HWND lv = GetDlgItem(RamSearchHWnd,IDC_RAMLIST); 1.1356 + if(prevValuesNeededUpdate != s_prevValuesNeedUpdate) 1.1357 + { 1.1358 + // previous values got updated, refresh everything visible 1.1359 + ListView_Update(lv, -1); 1.1360 + } 1.1361 + else 1.1362 + { 1.1363 + // refresh any visible parts of the listview box that changed 1.1364 + static int changes[128]; 1.1365 + int top = ListView_GetTopIndex(lv); 1.1366 + int count = ListView_GetCountPerPage(lv); 1.1367 + int start = -1; 1.1368 + for(int i = top; i <= top+count; i++) 1.1369 + { 1.1370 + int changeNum = CALL_WITH_T_SIZE_TYPES_1(GetNumChangesFromItemIndex, rs_type_size,rs_t=='s',noMisalign, i); //s_numChanges[i]; 1.1371 + int changed = changeNum != changes[i-top]; 1.1372 + if(changed) 1.1373 + changes[i-top] = changeNum; 1.1374 + 1.1375 + if(start == -1) 1.1376 + { 1.1377 + if(i != top+count && changed) 1.1378 + { 1.1379 + start = i; 1.1380 + //somethingChanged = true; 1.1381 + } 1.1382 + } 1.1383 + else 1.1384 + { 1.1385 + if(i == top+count || !changed) 1.1386 + { 1.1387 + ListView_RedrawItems(lv, start, i-1); 1.1388 + start = -1; 1.1389 + } 1.1390 + } 1.1391 + } 1.1392 + } 1.1393 + } 1.1394 + 1.1395 + if(RamWatchHWnd) 1.1396 + { 1.1397 + Update_RAM_Watch(); 1.1398 + } 1.1399 +} 1.1400 + 1.1401 +static int rs_lastPercent = -1; 1.1402 +inline void UpdateRamSearchProgressBar(int percent) 1.1403 +{ 1.1404 + if(rs_lastPercent != percent) 1.1405 + { 1.1406 + rs_lastPercent = percent; 1.1407 + UpdateRamSearchTitleBar(percent); 1.1408 + } 1.1409 +} 1.1410 + 1.1411 +static void SelectEditControl(int controlID) 1.1412 +{ 1.1413 + HWND hEdit = GetDlgItem(RamSearchHWnd,controlID); 1.1414 + SetFocus(hEdit); 1.1415 + SendMessage(hEdit, EM_SETSEL, 0, -1); 1.1416 +} 1.1417 + 1.1418 +static BOOL SelectingByKeyboard() 1.1419 +{ 1.1420 + int a = GetKeyState(VK_LEFT); 1.1421 + int b = GetKeyState(VK_RIGHT); 1.1422 + int c = GetKeyState(VK_UP); 1.1423 + int d = GetKeyState(VK_DOWN); // space and tab are intentionally omitted 1.1424 + return (a | b | c | d) & 0x80; 1.1425 +} 1.1426 + 1.1427 + 1.1428 +LRESULT CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 1.1429 +{ 1.1430 + static int watchIndex=0; 1.1431 + 1.1432 + switch(uMsg) 1.1433 + { 1.1434 + case WM_INITDIALOG: { 1.1435 + RamSearchHWnd = hDlg; 1.1436 + 1.1437 + SetWindowPos(hDlg, NULL, regQueryDwordValue("ramSearchX", 0), regQueryDwordValue("ramSearchY", 0), NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); 1.1438 + switch(rs_o) 1.1439 + { 1.1440 + case '<': 1.1441 + SendDlgItemMessage(hDlg, IDC_LESSTHAN, BM_SETCHECK, BST_CHECKED, 0); 1.1442 + break; 1.1443 + case '>': 1.1444 + SendDlgItemMessage(hDlg, IDC_MORETHAN, BM_SETCHECK, BST_CHECKED, 0); 1.1445 + break; 1.1446 + case 'l': 1.1447 + SendDlgItemMessage(hDlg, IDC_NOMORETHAN, BM_SETCHECK, BST_CHECKED, 0); 1.1448 + break; 1.1449 + case 'm': 1.1450 + SendDlgItemMessage(hDlg, IDC_NOLESSTHAN, BM_SETCHECK, BST_CHECKED, 0); 1.1451 + break; 1.1452 + case '=': 1.1453 + SendDlgItemMessage(hDlg, IDC_EQUALTO, BM_SETCHECK, BST_CHECKED, 0); 1.1454 + break; 1.1455 + case '!': 1.1456 + SendDlgItemMessage(hDlg, IDC_DIFFERENTFROM, BM_SETCHECK, BST_CHECKED, 0); 1.1457 + break; 1.1458 + case 'd': 1.1459 + SendDlgItemMessage(hDlg, IDC_DIFFERENTBY, BM_SETCHECK, BST_CHECKED, 0); 1.1460 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),true); 1.1461 + break; 1.1462 + case '%': 1.1463 + SendDlgItemMessage(hDlg, IDC_MODULO, BM_SETCHECK, BST_CHECKED, 0); 1.1464 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),true); 1.1465 + break; 1.1466 + } 1.1467 + switch (rs_c) 1.1468 + { 1.1469 + case 'r': 1.1470 + SendDlgItemMessage(hDlg, IDC_PREVIOUSVALUE, BM_SETCHECK, BST_CHECKED, 0); 1.1471 + break; 1.1472 + case 's': 1.1473 + SendDlgItemMessage(hDlg, IDC_SPECIFICVALUE, BM_SETCHECK, BST_CHECKED, 0); 1.1474 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREVALUE),true); 1.1475 + break; 1.1476 + case 'a': 1.1477 + SendDlgItemMessage(hDlg, IDC_SPECIFICADDRESS, BM_SETCHECK, BST_CHECKED, 0); 1.1478 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREADDRESS),true); 1.1479 + break; 1.1480 + case 'n': 1.1481 + SendDlgItemMessage(hDlg, IDC_NUMBEROFCHANGES, BM_SETCHECK, BST_CHECKED, 0); 1.1482 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPARECHANGES),true); 1.1483 + break; 1.1484 + } 1.1485 + switch (rs_t) 1.1486 + { 1.1487 + case 's': 1.1488 + SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0); 1.1489 + break; 1.1490 + case 'u': 1.1491 + SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0); 1.1492 + break; 1.1493 + case 'h': 1.1494 + SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_CHECKED, 0); 1.1495 + break; 1.1496 + } 1.1497 + switch (rs_type_size) 1.1498 + { 1.1499 + case 'b': 1.1500 + SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0); 1.1501 + break; 1.1502 + case 'w': 1.1503 + SendDlgItemMessage(hDlg, IDC_2_BYTES, BM_SETCHECK, BST_CHECKED, 0); 1.1504 + break; 1.1505 + case 'd': 1.1506 + SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_SETCHECK, BST_CHECKED, 0); 1.1507 + break; 1.1508 + } 1.1509 + 1.1510 + s_prevValuesNeedUpdate = true; 1.1511 + 1.1512 + SendDlgItemMessage(hDlg,IDC_C_AUTOSEARCH,BM_SETCHECK,AutoSearch?BST_CHECKED:BST_UNCHECKED,0); 1.1513 + //const char* names[5] = {"Address","Value","Previous","Changes","Notes"}; 1.1514 + //int widths[5] = {62,64,64,55,55}; 1.1515 + const char* names[] = {"Address","Value","Previous","Changes"}; 1.1516 + int widths[4] = {68,76,76,68}; 1.1517 + if (!ResultCount) 1.1518 + reset_address_info(); 1.1519 + else 1.1520 + { 1.1521 + signal_new_frame(); 1.1522 + CompactAddrs(); 1.1523 + } 1.1524 + void init_list_box(HWND Box, const char* Strs[], int numColumns, int *columnWidths); 1.1525 + init_list_box(GetDlgItem(hDlg,IDC_RAMLIST),names,4,widths); 1.1526 + //ListView_SetItemCount(GetDlgItem(hDlg,IDC_RAMLIST),ResultCount); 1.1527 + if (!noMisalign) SendDlgItemMessage(hDlg, IDC_MISALIGN, BM_SETCHECK, BST_CHECKED, 0); 1.1528 + //if (littleEndian) SendDlgItemMessage(hDlg, IDC_ENDIAN, BM_SETCHECK, BST_CHECKED, 0); 1.1529 + last_rs_possible = -1; 1.1530 + 1.1531 + s_prevSelCount = -1; 1.1532 + RefreshRamListSelectedCountControlStatus(hDlg); 1.1533 + 1.1534 + // force misalign checkbox to refresh 1.1535 + signal_new_size(); 1.1536 + 1.1537 + // force undo button to refresh 1.1538 + int undoType = s_undoType; 1.1539 + SetRamSearchUndoType(hDlg, -2); 1.1540 + SetRamSearchUndoType(hDlg, undoType); 1.1541 + 1.1542 + // force possibility count to refresh 1.1543 + last_rs_possible--; 1.1544 + UpdatePossibilities(ResultCount, (int)s_activeMemoryRegions.size()); 1.1545 + 1.1546 + rs_val_valid = Set_RS_Val(); 1.1547 + 1.1548 + ListView_SetCallbackMask(GetDlgItem(hDlg,IDC_RAMLIST), LVIS_FOCUSED|LVIS_SELECTED); 1.1549 + 1.1550 + return true; 1.1551 + } break; 1.1552 + 1.1553 + case WM_NOTIFY: 1.1554 + { 1.1555 + LPNMHDR lP = (LPNMHDR) lParam; 1.1556 + switch (lP->code) 1.1557 + { 1.1558 + case LVN_ITEMCHANGED: // selection changed event 1.1559 + { 1.1560 + NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lP; 1.1561 + if(pNMListView->uNewState & LVIS_FOCUSED || 1.1562 + (pNMListView->uNewState ^ pNMListView->uOldState) & LVIS_SELECTED) 1.1563 + { 1.1564 + // disable buttons that we don't have the right number of selected items for 1.1565 + RefreshRamListSelectedCountControlStatus(hDlg); 1.1566 + } 1.1567 + } break; 1.1568 + 1.1569 + case LVN_GETDISPINFO: 1.1570 + { 1.1571 + LV_DISPINFO *Item = (LV_DISPINFO *)lParam; 1.1572 + Item->item.mask = LVIF_TEXT; 1.1573 + Item->item.state = 0; 1.1574 + Item->item.iImage = 0; 1.1575 + const unsigned int iNum = Item->item.iItem; 1.1576 + static char num[11]; 1.1577 + switch (Item->item.iSubItem) 1.1578 + { 1.1579 + case 0: 1.1580 + { 1.1581 + int addr = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_type_size,rs_t=='s',noMisalign, iNum); 1.1582 + sprintf(num,"%08X",addr); 1.1583 + Item->item.pszText = num; 1.1584 + } return true; 1.1585 + case 1: 1.1586 + { 1.1587 + int i = CALL_WITH_T_SIZE_TYPES_1(GetCurValueFromItemIndex, rs_type_size,rs_t=='s',noMisalign, iNum); 1.1588 + const char* formatString = ((rs_t=='s') ? "%d" : (rs_t=='u') ? "%u" : (rs_type_size=='d' ? "%08X" : rs_type_size=='w' ? "%04X" : "%02X")); 1.1589 + switch (rs_type_size) 1.1590 + { 1.1591 + case 'b': 1.1592 + default: sprintf(num, formatString, rs_t=='s' ? (char)(i&0xff) : (unsigned char)(i&0xff)); break; 1.1593 + case 'w': sprintf(num, formatString, rs_t=='s' ? (short)(i&0xffff) : (unsigned short)(i&0xffff)); break; 1.1594 + case 'd': sprintf(num, formatString, rs_t=='s' ? (long)(i&0xffffffff) : (unsigned long)(i&0xffffffff)); break; 1.1595 + } 1.1596 + Item->item.pszText = num; 1.1597 + } return true; 1.1598 + case 2: 1.1599 + { 1.1600 + int i = CALL_WITH_T_SIZE_TYPES_1(GetPrevValueFromItemIndex, rs_type_size,rs_t=='s',noMisalign, iNum); 1.1601 + const char* formatString = ((rs_t=='s') ? "%d" : (rs_t=='u') ? "%u" : (rs_type_size=='d' ? "%08X" : rs_type_size=='w' ? "%04X" : "%02X")); 1.1602 + switch (rs_type_size) 1.1603 + { 1.1604 + case 'b': 1.1605 + default: sprintf(num, formatString, rs_t=='s' ? (char)(i&0xff) : (unsigned char)(i&0xff)); break; 1.1606 + case 'w': sprintf(num, formatString, rs_t=='s' ? (short)(i&0xffff) : (unsigned short)(i&0xffff)); break; 1.1607 + case 'd': sprintf(num, formatString, rs_t=='s' ? (long)(i&0xffffffff) : (unsigned long)(i&0xffffffff)); break; 1.1608 + } 1.1609 + Item->item.pszText = num; 1.1610 + } return true; 1.1611 + case 3: 1.1612 + { 1.1613 + int i = CALL_WITH_T_SIZE_TYPES_1(GetNumChangesFromItemIndex, rs_type_size,rs_t=='s',noMisalign, iNum); 1.1614 + sprintf(num,"%d",i); 1.1615 + 1.1616 + Item->item.pszText = num; 1.1617 + } return true; 1.1618 + //case 4: 1.1619 + // Item->item.pszText = rsaddrs[rsresults[iNum].Index].comment ? rsaddrs[rsresults[iNum].Index].comment : ""; 1.1620 + // return true; 1.1621 + default: 1.1622 + return false; 1.1623 + } 1.1624 + } 1.1625 + 1.1626 + case NM_CUSTOMDRAW: 1.1627 + { 1.1628 + SetWindowLong(hDlg, DWL_MSGRESULT, CustomDraw(lParam)); 1.1629 + return TRUE; 1.1630 + } break; 1.1631 + 1.1632 + //case LVN_ODCACHEHINT: //Copied this bit from the MSDN virtual listbox code sample. Eventually it should probably do something. 1.1633 + //{ 1.1634 + // LPNMLVCACHEHINT lpCacheHint = (LPNMLVCACHEHINT)lParam; 1.1635 + // return 0; 1.1636 + //} 1.1637 + //case LVN_ODFINDITEM: //Copied this bit from the MSDN virtual listbox code sample. Eventually it should probably do something. 1.1638 + //{ 1.1639 + // LPNMLVFINDITEM lpFindItem = (LPNMLVFINDITEM)lParam; 1.1640 + // return 0; 1.1641 + //} 1.1642 + } 1.1643 + } break; 1.1644 + 1.1645 + case WM_COMMAND: 1.1646 + { 1.1647 + int rv = false; 1.1648 + switch(LOWORD(wParam)) 1.1649 + { 1.1650 + case IDC_SIGNED: 1.1651 + rs_t='s'; 1.1652 + signal_new_size(); 1.1653 + {rv = true; break;} 1.1654 + case IDC_UNSIGNED: 1.1655 + rs_t='u'; 1.1656 + signal_new_size(); 1.1657 + {rv = true; break;} 1.1658 + case IDC_HEX: 1.1659 + rs_t='h'; 1.1660 + signal_new_size(); 1.1661 + {rv = true; break;} 1.1662 + case IDC_1_BYTE: 1.1663 + rs_type_size = 'b'; 1.1664 + signal_new_size(); 1.1665 + {rv = true; break;} 1.1666 + case IDC_2_BYTES: 1.1667 + rs_type_size = 'w'; 1.1668 + signal_new_size(); 1.1669 + {rv = true; break;} 1.1670 + case IDC_4_BYTES: 1.1671 + rs_type_size = 'd'; 1.1672 + signal_new_size(); 1.1673 + {rv = true; break;} 1.1674 + case IDC_MISALIGN: 1.1675 + noMisalign = !noMisalign; 1.1676 + //CompactAddrs(); 1.1677 + signal_new_size(); 1.1678 + {rv = true; break;} 1.1679 +// case IDC_ENDIAN: 1.1680 +//// littleEndian = !littleEndian; 1.1681 +//// signal_new_size(); 1.1682 +// {rv = true; break;} 1.1683 + case IDC_LESSTHAN: 1.1684 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1685 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1686 + rs_o = '<'; 1.1687 + {rv = true; break;} 1.1688 + case IDC_MORETHAN: 1.1689 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1690 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1691 + rs_o = '>'; 1.1692 + {rv = true; break;} 1.1693 + case IDC_NOMORETHAN: 1.1694 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1695 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1696 + rs_o = 'l'; 1.1697 + {rv = true; break;} 1.1698 + case IDC_NOLESSTHAN: 1.1699 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1700 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1701 + rs_o = 'm'; 1.1702 + {rv = true; break;} 1.1703 + case IDC_EQUALTO: 1.1704 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1705 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1706 + rs_o = '='; 1.1707 + {rv = true; break;} 1.1708 + case IDC_DIFFERENTFROM: 1.1709 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1710 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1711 + rs_o = '!'; 1.1712 + {rv = true; break;} 1.1713 + case IDC_DIFFERENTBY: 1.1714 + { 1.1715 + rs_o = 'd'; 1.1716 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),true); 1.1717 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),false); 1.1718 + if(!SelectingByKeyboard()) 1.1719 + SelectEditControl(IDC_EDIT_DIFFBY); 1.1720 + } {rv = true; break;} 1.1721 + case IDC_MODULO: 1.1722 + { 1.1723 + rs_o = '%'; 1.1724 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_DIFFBY),false); 1.1725 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_MODBY),true); 1.1726 + if(!SelectingByKeyboard()) 1.1727 + SelectEditControl(IDC_EDIT_MODBY); 1.1728 + } {rv = true; break;} 1.1729 + case IDC_PREVIOUSVALUE: 1.1730 + rs_c='r'; 1.1731 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREVALUE),false); 1.1732 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREADDRESS),false); 1.1733 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPARECHANGES),false); 1.1734 + {rv = true; break;} 1.1735 + case IDC_SPECIFICVALUE: 1.1736 + { 1.1737 + rs_c = 's'; 1.1738 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREVALUE),true); 1.1739 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREADDRESS),false); 1.1740 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPARECHANGES),false); 1.1741 + if(!SelectingByKeyboard()) 1.1742 + SelectEditControl(IDC_EDIT_COMPAREVALUE); 1.1743 + {rv = true; break;} 1.1744 + } 1.1745 + case IDC_SPECIFICADDRESS: 1.1746 + { 1.1747 + rs_c = 'a'; 1.1748 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREADDRESS),true); 1.1749 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREVALUE),false); 1.1750 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPARECHANGES),false); 1.1751 + if(!SelectingByKeyboard()) 1.1752 + SelectEditControl(IDC_EDIT_COMPAREADDRESS); 1.1753 + } {rv = true; break;} 1.1754 + case IDC_NUMBEROFCHANGES: 1.1755 + { 1.1756 + rs_c = 'n'; 1.1757 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPARECHANGES),true); 1.1758 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREVALUE),false); 1.1759 + EnableWindow(GetDlgItem(hDlg,IDC_EDIT_COMPAREADDRESS),false); 1.1760 + if(!SelectingByKeyboard()) 1.1761 + SelectEditControl(IDC_EDIT_COMPARECHANGES); 1.1762 + } {rv = true; break;} 1.1763 + case IDC_C_ADDCHEAT: 1.1764 + { 1.1765 + HWND ramListControl = GetDlgItem(hDlg,IDC_RAMLIST); 1.1766 + int watchItemIndex = ListView_GetNextItem(ramListControl, -1, LVNI_SELECTED); 1.1767 + while (watchItemIndex >= 0) 1.1768 + { 1.1769 + unsigned long address = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_type_size,rs_t=='s',noMisalign, watchItemIndex); 1.1770 + 1.1771 + int sizeType = -1; 1.1772 + if(rs_type_size == 'b') 1.1773 + sizeType = 0; 1.1774 + else if(rs_type_size == 'w') 1.1775 + sizeType = 1; 1.1776 + else if(rs_type_size == 'd') 1.1777 + sizeType = 2; 1.1778 + 1.1779 + int numberType = -1; 1.1780 + if(rs_t == 's') 1.1781 + numberType = 0; 1.1782 + else if(rs_t == 'u') 1.1783 + numberType = 1; 1.1784 + else if(rs_t == 'h') 1.1785 + numberType = 2; 1.1786 + 1.1787 + if(systemCartridgeType == 0) 1.1788 + { 1.1789 + AddCheat dlg (address/*, hDlg*/); 1.1790 + if(sizeType != -1) dlg.sizeType = sizeType; 1.1791 + if(numberType != -1) dlg.numberType = numberType; 1.1792 + dlg.DoModal(); 1.1793 + } 1.1794 + else 1.1795 + { 1.1796 + AddGBCheat dlg (address/*, hDlg*/); 1.1797 + if(sizeType != -1) dlg.sizeType = sizeType; 1.1798 + if(numberType != -1) dlg.numberType = numberType; 1.1799 + dlg.DoModal(); 1.1800 + } 1.1801 + watchItemIndex = ListView_GetNextItem(ramListControl, watchItemIndex, LVNI_SELECTED); 1.1802 + } 1.1803 + } {rv = true; break;} 1.1804 + case IDC_C_RESET: 1.1805 + { 1.1806 + RamSearchSaveUndoStateIfNotTooBig(RamSearchHWnd); 1.1807 + int prevNumItems = last_rs_possible; 1.1808 + 1.1809 + soft_reset_address_info(); 1.1810 + 1.1811 + if(prevNumItems == last_rs_possible) 1.1812 + SetRamSearchUndoType(RamSearchHWnd, 0); // nothing to undo 1.1813 + 1.1814 + ListView_SetItemState(GetDlgItem(hDlg,IDC_RAMLIST), -1, 0, LVIS_SELECTED); // deselect all 1.1815 + //ListView_SetItemCount(GetDlgItem(hDlg,IDC_RAMLIST),ResultCount); 1.1816 + ListView_SetSelectionMark(GetDlgItem(hDlg,IDC_RAMLIST), 0); 1.1817 + RefreshRamListSelectedCountControlStatus(hDlg); 1.1818 + {rv = true; break;} 1.1819 + } 1.1820 + case IDC_C_RESET_CHANGES: 1.1821 + memset(s_numChanges, 0, (sizeof(*s_numChanges)*(MAX_RAM_SIZE))); 1.1822 + ListView_Update(GetDlgItem(hDlg,IDC_RAMLIST), -1); 1.1823 + //SetRamSearchUndoType(hDlg, 0); 1.1824 + {rv = true; break;} 1.1825 + case IDC_C_UNDO: 1.1826 + if(s_undoType>0) 1.1827 + { 1.1828 + systemSoundClearBuffer(); 1.1829 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.1830 + if(s_activeMemoryRegions.size() < tooManyRegionsForUndo) 1.1831 + { 1.1832 + MemoryList tempMemoryList = s_activeMemoryRegions; 1.1833 + s_activeMemoryRegions = s_activeMemoryRegionsBackup; 1.1834 + s_activeMemoryRegionsBackup = tempMemoryList; 1.1835 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.1836 + SetRamSearchUndoType(hDlg, 3 - s_undoType); 1.1837 + } 1.1838 + else 1.1839 + { 1.1840 + s_activeMemoryRegions = s_activeMemoryRegionsBackup; 1.1841 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.1842 + SetRamSearchUndoType(hDlg, -1); 1.1843 + } 1.1844 + CompactAddrs(); 1.1845 + ListView_SetItemState(GetDlgItem(hDlg,IDC_RAMLIST), -1, 0, LVIS_SELECTED); // deselect all 1.1846 + ListView_SetSelectionMark(GetDlgItem(hDlg,IDC_RAMLIST), 0); 1.1847 + RefreshRamListSelectedCountControlStatus(hDlg); 1.1848 + } 1.1849 + {rv = true; break;} 1.1850 + case IDC_C_AUTOSEARCH: 1.1851 + AutoSearch = SendDlgItemMessage(hDlg, IDC_C_AUTOSEARCH, BM_GETCHECK, 0, 0) != 0; 1.1852 + AutoSearchAutoRetry = false; 1.1853 + if (!AutoSearch) {rv = true; break;} 1.1854 + case IDC_C_SEARCH: 1.1855 + { 1.1856 + systemSoundClearBuffer(); 1.1857 + 1.1858 + if(!rs_val_valid && !(rs_val_valid = Set_RS_Val())) 1.1859 + goto invalid_field; 1.1860 + 1.1861 + if(ResultCount) 1.1862 + { 1.1863 + RamSearchSaveUndoStateIfNotTooBig(hDlg); 1.1864 + 1.1865 + prune(rs_c,rs_o,rs_t=='s',rs_val,rs_param); 1.1866 + 1.1867 + RefreshRamListSelectedCountControlStatus(hDlg); 1.1868 + } 1.1869 + 1.1870 + if(!ResultCount) 1.1871 + { 1.1872 + 1.1873 + MessageBox(RamSearchHWnd,"Resetting search.","Out of results.",MB_OK|MB_ICONINFORMATION); 1.1874 + soft_reset_address_info(); 1.1875 + } 1.1876 + 1.1877 + {rv = true; break;} 1.1878 + 1.1879 +invalid_field: 1.1880 + MessageBox(RamSearchHWnd,"Invalid or out-of-bound entered value.","Error",MB_OK|MB_ICONSTOP); 1.1881 + if(AutoSearch) // stop autosearch if it just started 1.1882 + { 1.1883 + SendDlgItemMessage(hDlg, IDC_C_AUTOSEARCH, BM_SETCHECK, BST_UNCHECKED, 0); 1.1884 + SendMessage(hDlg, WM_COMMAND, IDC_C_AUTOSEARCH, 0); 1.1885 + } 1.1886 + {rv = true; break;} 1.1887 + } 1.1888 + case IDC_C_WATCH: 1.1889 + { 1.1890 + HWND ramListControl = GetDlgItem(hDlg,IDC_RAMLIST); 1.1891 + int selCount = ListView_GetSelectedCount(ramListControl); 1.1892 + 1.1893 + bool inserted = false; 1.1894 + int watchItemIndex = ListView_GetNextItem(ramListControl, -1, LVNI_SELECTED); 1.1895 + while (watchItemIndex >= 0) 1.1896 + { 1.1897 + AddressWatcher tempWatch; 1.1898 + tempWatch.Address = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_type_size,rs_t=='s',noMisalign, watchItemIndex); 1.1899 + tempWatch.Size = rs_type_size; 1.1900 + tempWatch.Type = rs_t; 1.1901 + tempWatch.WrongEndian = 0; //Replace when I get little endian working 1.1902 + tempWatch.comment = NULL; 1.1903 + 1.1904 + if (selCount == 1) 1.1905 + inserted |= InsertWatch(tempWatch, hDlg); 1.1906 + else 1.1907 + inserted |= InsertWatch(tempWatch, ""); 1.1908 + 1.1909 + watchItemIndex = ListView_GetNextItem(ramListControl, watchItemIndex, LVNI_SELECTED); 1.1910 + } 1.1911 + // bring up the ram watch window if it's not already showing so the user knows where the watch went 1.1912 + if(inserted && !RamWatchHWnd) 1.1913 + SendMessage(hWnd, WM_COMMAND, ID_RAM_WATCH, 0); 1.1914 + SetForegroundWindow(RamSearchHWnd); 1.1915 + {rv = true; break;} 1.1916 + } 1.1917 + 1.1918 + // eliminate all selected items 1.1919 + case IDC_C_ELIMINATE: 1.1920 + { 1.1921 + RamSearchSaveUndoStateIfNotTooBig(hDlg); 1.1922 + 1.1923 + HWND ramListControl = GetDlgItem(hDlg,IDC_RAMLIST); 1.1924 + int size = (rs_type_size=='b' || !noMisalign) ? 1 : 2; 1.1925 + int selCount = ListView_GetSelectedCount(ramListControl); 1.1926 + int watchIndex = -1; 1.1927 + 1.1928 + // time-saving trick #1: 1.1929 + // condense the selected items into an array of address ranges 1.1930 + std::vector<AddrRange> selHardwareAddrs; 1.1931 + for(int i = 0, j = 1024; i < selCount; ++i, --j) 1.1932 + { 1.1933 + watchIndex = ListView_GetNextItem(ramListControl, watchIndex, LVNI_SELECTED); 1.1934 + int addr = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_type_size,rs_t=='s',noMisalign, watchIndex); 1.1935 + if(!selHardwareAddrs.empty() && addr == selHardwareAddrs.back().End()) 1.1936 + selHardwareAddrs.back().size += size; 1.1937 + else 1.1938 + selHardwareAddrs.push_back(AddrRange(addr,size)); 1.1939 + 1.1940 + if(!j) UpdateRamSearchProgressBar(i * 50 / selCount), j = 1024; 1.1941 + } 1.1942 + 1.1943 + // now deactivate the ranges 1.1944 + 1.1945 + // time-saving trick #2: 1.1946 + // take advantage of the fact that the listbox items must be in the same order as the regions 1.1947 + MemoryList::iterator iter = s_activeMemoryRegions.begin(); 1.1948 + int numHardwareAddrRanges = selHardwareAddrs.size(); 1.1949 + for(int i = 0, j = 16; i < numHardwareAddrRanges; ++i, --j) 1.1950 + { 1.1951 + int addr = selHardwareAddrs[i].addr; 1.1952 + int size = selHardwareAddrs[i].size; 1.1953 + bool affected = false; 1.1954 + while(iter != s_activeMemoryRegions.end()) 1.1955 + { 1.1956 + MemoryRegion& region = *iter; 1.1957 + int affNow = DeactivateRegion(region, iter, addr, size); 1.1958 + if(affNow) 1.1959 + affected = true; 1.1960 + else if(affected) 1.1961 + break; 1.1962 + if(affNow != 2) 1.1963 + ++iter; 1.1964 + } 1.1965 + 1.1966 + if(!j) UpdateRamSearchProgressBar(50 + (i * 50 / selCount)), j = 16; 1.1967 + } 1.1968 + UpdateRamSearchTitleBar(); 1.1969 + 1.1970 + // careful -- if the above two time-saving tricks aren't working, 1.1971 + // the runtime can absolutely explode (seconds -> hours) when there are lots of regions 1.1972 + 1.1973 + ListView_SetItemState(ramListControl, -1, 0, LVIS_SELECTED); // deselect all 1.1974 + signal_new_size(); 1.1975 + {rv = true; break;} 1.1976 + } 1.1977 + //case IDOK: 1.1978 + case IDCANCEL: 1.1979 + RamSearchHWnd = NULL; 1.1980 +/* if (theApp.pauseDuringCheatSearch) 1.1981 + EndDialog(hDlg, true); // this should never be called on a modeless dialog 1.1982 + else 1.1983 +*/ 1.1984 + DestroyWindow(hDlg); 1.1985 + {rv = true; break;} 1.1986 + } 1.1987 + 1.1988 + // check refresh for comparison preview color update 1.1989 + // also, update rs_val if needed 1.1990 + bool needRefresh = false; 1.1991 + switch(LOWORD(wParam)) 1.1992 + { 1.1993 + case IDC_LESSTHAN: 1.1994 + case IDC_MORETHAN: 1.1995 + case IDC_NOMORETHAN: 1.1996 + case IDC_NOLESSTHAN: 1.1997 + case IDC_EQUALTO: 1.1998 + case IDC_DIFFERENTFROM: 1.1999 + case IDC_DIFFERENTBY: 1.2000 + case IDC_MODULO: 1.2001 + case IDC_PREVIOUSVALUE: 1.2002 + case IDC_SPECIFICVALUE: 1.2003 + case IDC_SPECIFICADDRESS: 1.2004 + case IDC_NUMBEROFCHANGES: 1.2005 + case IDC_SIGNED: 1.2006 + case IDC_UNSIGNED: 1.2007 + case IDC_HEX: 1.2008 + rs_val_valid = Set_RS_Val(); 1.2009 + needRefresh = true; 1.2010 + break; 1.2011 + case IDC_EDIT_COMPAREVALUE: 1.2012 + case IDC_EDIT_COMPAREADDRESS: 1.2013 + case IDC_EDIT_COMPARECHANGES: 1.2014 + case IDC_EDIT_DIFFBY: 1.2015 + case IDC_EDIT_MODBY: 1.2016 + if(HIWORD(wParam) == EN_CHANGE) 1.2017 + { 1.2018 + rs_val_valid = Set_RS_Val(); 1.2019 + needRefresh = true; 1.2020 + } 1.2021 + break; 1.2022 + } 1.2023 + if(needRefresh) 1.2024 + ListView_Update(GetDlgItem(hDlg,IDC_RAMLIST), -1); 1.2025 + 1.2026 + 1.2027 + return rv; 1.2028 + } break; 1.2029 + 1.2030 + case WM_CLOSE: 1.2031 + RECT r; 1.2032 + GetWindowRect(hDlg, &r); 1.2033 + regSetDwordValue("ramSearchX", r.left); 1.2034 + regSetDwordValue("ramSearchY", r.top); 1.2035 + SendMessage(RamSearchHWnd, WM_DESTROY, 0, 0); 1.2036 + break; 1.2037 + case WM_DESTROY: 1.2038 + RamSearchHWnd = NULL; 1.2039 +// theApp.modelessCheatDialogIsOpen = false; 1.2040 +// return true; 1.2041 + break; 1.2042 + } 1.2043 + 1.2044 + return false; 1.2045 +} 1.2046 + 1.2047 +void UpdateRamSearchTitleBar(int percent) 1.2048 +{ 1.2049 +#define HEADER_STR " RAM Search - " 1.2050 +#define PROGRESS_STR " %d%% ... " 1.2051 +#define STATUS_STR "%d Possibilit%s (%d Region%s)" 1.2052 + 1.2053 + int poss = last_rs_possible; 1.2054 + int regions = last_rs_regions; 1.2055 + if(poss <= 0) 1.2056 + strcpy(Str_Tmp," RAM Search"); 1.2057 + else if(percent <= 0) 1.2058 + sprintf(Str_Tmp, HEADER_STR STATUS_STR, poss, poss==1?"y":"ies", regions, regions==1?"":"s"); 1.2059 + else 1.2060 + sprintf(Str_Tmp, PROGRESS_STR STATUS_STR, percent, poss, poss==1?"y":"ies", regions, regions==1?"":"s"); 1.2061 + SetWindowText(RamSearchHWnd, Str_Tmp); 1.2062 +} 1.2063 + 1.2064 +void UpdatePossibilities(int rs_possible, int regions) 1.2065 +{ 1.2066 + if(rs_possible != last_rs_possible) 1.2067 + { 1.2068 + last_rs_possible = rs_possible; 1.2069 + last_rs_regions = regions; 1.2070 + UpdateRamSearchTitleBar(); 1.2071 + } 1.2072 +} 1.2073 + 1.2074 +void SetRamSearchUndoType(HWND hDlg, int type) 1.2075 +{ 1.2076 + if(s_undoType != type) 1.2077 + { 1.2078 + if((s_undoType!=2 && s_undoType!=-1)!=(type!=2 && type!=-1)) 1.2079 + SendDlgItemMessage(hDlg,IDC_C_UNDO,WM_SETTEXT,0,(LPARAM)((type == 2 || type == -1) ? "Redo" : "Undo")); 1.2080 + if((s_undoType>0)!=(type>0)) 1.2081 + EnableWindow(GetDlgItem(hDlg,IDC_C_UNDO),type>0); 1.2082 + s_undoType = type; 1.2083 + } 1.2084 +} 1.2085 + 1.2086 +void RamSearchSaveUndoStateIfNotTooBig(HWND hDlg) 1.2087 +{ 1.2088 + EnterCriticalSection(&s_activeMemoryRegionsCS); 1.2089 + if(s_activeMemoryRegions.size() < tooManyRegionsForUndo) 1.2090 + { 1.2091 + s_activeMemoryRegionsBackup = s_activeMemoryRegions; 1.2092 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.2093 + SetRamSearchUndoType(hDlg, 1); 1.2094 + } 1.2095 + else 1.2096 + { 1.2097 + LeaveCriticalSection(&s_activeMemoryRegionsCS); 1.2098 + SetRamSearchUndoType(hDlg, 0); 1.2099 + } 1.2100 +} 1.2101 + 1.2102 +struct InitRamSearch 1.2103 +{ 1.2104 + InitRamSearch() 1.2105 + { 1.2106 + InitializeCriticalSection(&s_activeMemoryRegionsCS); 1.2107 + } 1.2108 + ~InitRamSearch() 1.2109 + { 1.2110 + DeleteCriticalSection(&s_activeMemoryRegionsCS); 1.2111 + } 1.2112 +} initRamSearch; 1.2113 + 1.2114 + 1.2115 +void init_list_box(HWND Box, const char* Strs[], int numColumns, int *columnWidths) //initializes the ram search and/or ram watch listbox 1.2116 +{ 1.2117 + LVCOLUMN Col; 1.2118 + Col.mask = LVCF_FMT | LVCF_ORDER | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; 1.2119 + Col.fmt = LVCFMT_CENTER; 1.2120 + for (int i = 0; i < numColumns; i++) 1.2121 + { 1.2122 + Col.iOrder = i; 1.2123 + Col.iSubItem = i; 1.2124 + Col.pszText = (LPSTR)(Strs[i]); 1.2125 + Col.cx = columnWidths[i]; 1.2126 + ListView_InsertColumn(Box,i,&Col); 1.2127 + } 1.2128 + 1.2129 + ListView_SetExtendedListViewStyle(Box, LVS_EX_FULLROWSELECT); 1.2130 +}