Mercurial > vba-clojure
view src/win32/ramwatch.cpp @ 8:08a8e09ca414
add files required by automake
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:54:39 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 #include "stdafx.h"2 #include "VBA.h"3 #include "resource.h"4 #include "WinMiscUtil.h"5 #include "GBACheatsDlg.h"6 #include "GBCheatsDlg.h"7 #include "ram_search.h"8 #include "ramwatch.h"9 #include "reg.h"10 #include "Sound.h"11 #include <cassert>12 #include <windows.h>13 #include <string>15 /*16 #include <commctrl.h>17 #pragma comment(lib, "comctl32.lib")18 #include <shellapi.h>19 #pragma comment(lib, "shell32.lib")20 #include <commdlg.h>21 #pragma comment(lib, "comdlg32.lib")22 */24 static HMENU ramwatchmenu;25 static HMENU rwrecentmenu;26 /*static*/ HACCEL RamWatchAccels = NULL;27 char rw_recent_files[MAX_RECENT_WATCHES][1024];28 //char Watch_Dir[1024]="";29 bool RWfileChanged = false; //Keeps track of whether the current watch file has been changed, if so, ramwatch will prompt to save changes30 bool AutoRWLoad = false; //Keeps track of whether Auto-load is checked31 bool RWSaveWindowPos = false; //Keeps track of whether Save Window position is checked32 char currentWatch[1024];33 int ramw_x, ramw_y; //Used to store ramwatch dialog window positions34 AddressWatcher rswatches[MAX_WATCH_COUNT];35 int WatchCount=0;36 static int s_prevSelCount=-1;38 HWND RamWatchHWnd;39 #define gamefilename theApp.gameFilename40 #define hWnd AfxGetMainWnd()->GetSafeHwnd()41 #define hInst AfxGetInstanceHandle()42 static char Str_Tmp [1024];44 void init_list_box(HWND Box, const char* Strs[], int numColumns, int *columnWidths); //initializes the ram search and/or ram watch listbox46 #define MESSAGEBOXPARENT (RamWatchHWnd ? RamWatchHWnd : hWnd)48 bool QuickSaveWatches();49 bool ResetWatches();51 void RefreshWatchListSelectedCountControlStatus(HWND hDlg);53 unsigned int GetCurrentValue(AddressWatcher& watch)54 {55 return ReadValueAtHardwareAddress(watch.Address, watch.Size == 'd' ? 4 : watch.Size == 'w' ? 2 : 1);56 }58 bool IsSameWatch(const AddressWatcher& l, const AddressWatcher& r)59 {60 if (r.Size == 'S') return false;61 return ((l.Address == r.Address) && (l.Size == r.Size) && (l.Type == r.Type)/* && (l.WrongEndian == r.WrongEndian)*/);62 }64 bool VerifyWatchNotAlreadyAdded(const AddressWatcher& watch)65 {66 for (int j = 0; j < WatchCount; j++)67 {68 if (IsSameWatch(rswatches[j], watch))69 {70 if(RamWatchHWnd)71 SetForegroundWindow(RamWatchHWnd);72 return false;73 }74 }75 return true;76 }79 bool InsertWatch(const AddressWatcher& Watch, char *Comment)80 {81 if(WatchCount >= MAX_WATCH_COUNT)82 return false;84 int i = WatchCount++;85 AddressWatcher& NewWatch = rswatches[i];86 NewWatch = Watch;87 //if (NewWatch.comment) free(NewWatch.comment);88 NewWatch.comment = (char *) malloc(strlen(Comment)+2);89 NewWatch.CurValue = GetCurrentValue(NewWatch);90 strcpy(NewWatch.comment, Comment);91 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);92 RWfileChanged=true;94 return true;95 }97 LRESULT CALLBACK PromptWatchNameProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) //Gets the description of a watched address98 {99 RECT r;100 RECT r2;101 int dx1, dy1, dx2, dy2;103 switch(uMsg)104 {105 case WM_INITDIALOG:106 //Clear_Sound_Buffer();108 GetWindowRect(hWnd, &r);109 dx1 = (r.right - r.left) / 2;110 dy1 = (r.bottom - r.top) / 2;112 GetWindowRect(hDlg, &r2);113 dx2 = (r2.right - r2.left) / 2;114 dy2 = (r2.bottom - r2.top) / 2;116 //SetWindowPos(hDlg, NULL, max(0, r.left + (dx1 - dx2)), max(0, r.top + (dy1 - dy2)), NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);117 SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);118 strcpy(Str_Tmp,"Enter a name for this RAM address.");119 SendDlgItemMessage(hDlg,IDC_PROMPT_TEXT,WM_SETTEXT,0,(LPARAM)Str_Tmp);120 strcpy(Str_Tmp,"");121 SendDlgItemMessage(hDlg,IDC_PROMPT_TEXT2,WM_SETTEXT,0,(LPARAM)Str_Tmp);122 return true;123 break;125 case WM_COMMAND:126 switch(LOWORD(wParam))127 {128 case IDOK:129 {130 GetDlgItemText(hDlg,IDC_PROMPT_EDIT,Str_Tmp,80);131 InsertWatch(rswatches[WatchCount],Str_Tmp);132 EndDialog(hDlg, true);133 return true;134 break;135 }136 case ID_CANCEL:137 case IDCANCEL:138 EndDialog(hDlg, false);139 return false;140 break;141 }142 break;144 case WM_CLOSE:145 EndDialog(hDlg, false);146 return false;147 break;148 }150 return false;151 }153 bool InsertWatch(const AddressWatcher& Watch, HWND parent)154 {155 if(!VerifyWatchNotAlreadyAdded(Watch))156 return false;158 if(!parent)159 parent = RamWatchHWnd;160 if(!parent)161 parent = hWnd;163 int prevWatchCount = WatchCount;165 rswatches[WatchCount] = Watch;166 rswatches[WatchCount].CurValue = GetCurrentValue(rswatches[WatchCount]);167 systemSoundClearBuffer();168 DialogBox(hInst, MAKEINTRESOURCE(IDD_PROMPT), parent, (DLGPROC) PromptWatchNameProc);170 return WatchCount > prevWatchCount;171 }173 void Update_RAM_Watch()174 {175 BOOL watchChanged[MAX_WATCH_COUNT] = {0};177 if(WatchCount)178 {179 // update cached values and detect changes to displayed listview items181 for(int i = 0; i < WatchCount; i++)182 {183 unsigned int prevCurValue = rswatches[i].CurValue;184 unsigned int newCurValue = GetCurrentValue(rswatches[i]);185 if(prevCurValue != newCurValue)186 {187 rswatches[i].CurValue = newCurValue;188 watchChanged[i] = TRUE;189 }190 }191 }193 // refresh any visible parts of the listview box that changed194 HWND lv = GetDlgItem(RamWatchHWnd,IDC_WATCHLIST);195 int top = ListView_GetTopIndex(lv);196 int bottom = top + ListView_GetCountPerPage(lv) + 1; // +1 is so we will update a partially-displayed last item197 if(top < 0) top = 0;198 if(bottom > WatchCount) bottom = WatchCount;199 int start = -1;200 for(int i = top; i <= bottom; i++)201 {202 if(start == -1)203 {204 if(i != bottom && watchChanged[i])205 {206 start = i;207 //somethingChanged = true;208 }209 }210 else211 {212 if(i == bottom || !watchChanged[i])213 {214 ListView_RedrawItems(lv, start, i-1);215 start = -1;216 }217 }218 }219 }221 bool AskSave()222 {223 //This function asks to save changes if the watch file contents have changed224 //returns false only if a save was attempted but failed or was cancelled225 if (RWfileChanged)226 {227 systemSoundClearBuffer();228 int answer = MessageBox(MESSAGEBOXPARENT, "Save Changes?", "Ram Watch", MB_YESNOCANCEL);229 if(answer == IDYES)230 if(!QuickSaveWatches())231 return false;232 return (answer != IDCANCEL);233 }234 return true;235 }237 void WriteRecentRWFiles()238 {239 char str[2048];240 for (int i = 0; i < MAX_RECENT_WATCHES; i++)241 {242 sprintf(str, "recentWatch%d", i+1);243 regSetStringValue(str, &rw_recent_files[i][0]);244 }245 }247 void UpdateRW_RMenu(HMENU menu, unsigned int mitem, unsigned int baseid)248 {249 MENUITEMINFO moo;250 int x;252 moo.cbSize = sizeof(moo);253 moo.fMask = MIIM_SUBMENU | MIIM_STATE;255 GetMenuItemInfo(GetSubMenu(ramwatchmenu, 0), mitem, FALSE, &moo);256 moo.hSubMenu = menu;257 moo.fState = strlen(rw_recent_files[0]) ? MFS_ENABLED : MFS_GRAYED;259 SetMenuItemInfo(GetSubMenu(ramwatchmenu, 0), mitem, FALSE, &moo);261 // Remove all recent files submenus262 for(x = 0; x < MAX_RECENT_WATCHES; x++)263 {264 RemoveMenu(menu, baseid + x, MF_BYCOMMAND);265 }267 // Recreate the menus268 for(x = MAX_RECENT_WATCHES - 1; x >= 0; x--)269 {270 // Skip empty strings271 if(!strlen(rw_recent_files[x]))272 {273 continue;274 }276 moo.cbSize = sizeof(moo);277 moo.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE;279 #if 0280 const int TEMP_STRING_LENGTH = 128 + 5;281 char tmp[TEMP_STRING_LENGTH]; // FIXME?283 // Fill in the menu text.284 if(strlen(rw_recent_files[x]) < 128)285 {286 sprintf(tmp, "&%d. %s", ( x + 1 ) % 10, rw_recent_files[x]);287 }288 else289 {290 sprintf(tmp, "&%d. %s", ( x + 1 ) % 10, rw_recent_files[x] + strlen( rw_recent_files[x] ) - 127);291 }292 #endif293 // the ATL way; it is really pain to work out a MBCS-compatible string replace function in the pure c way294 CString atltmp(rw_recent_files[x]);295 atltmp.Replace("&", "&&");296 char *tmp = atltmp.GetBuffer(0);298 // Insert the menu item299 moo.cch = strlen(tmp);300 moo.fType = 0;301 moo.wID = baseid + x;302 moo.dwTypeData = tmp;303 InsertMenuItem(menu, 0, 1, &moo);305 // atltmp.ReleaseBuffer();306 }308 // I don't think one function shall do so many things in a row309 // WriteRecentRWFiles(); // write recent menu to ini310 }312 void UpdateRWRecentArray(const char* addString, unsigned int arrayLen, HMENU menu, unsigned int menuItem, unsigned int baseId)313 {314 const size_t len = 1024; // Avoid magic numbers316 // Try to find out if the filename is already in the recent files list.317 for(unsigned int x = 0; x < arrayLen; x++)318 {319 if(strlen(rw_recent_files[x]))320 {321 if(!strncmp(rw_recent_files[x], addString, 1024)) // Item is already in list.322 {323 // If the filename is in the file list don't add it again.324 // Move it up in the list instead.326 int y;327 char tmp[len];329 // Save pointer.330 strncpy(tmp, rw_recent_files[x], len - 1); // assuming rw_recent_files[n] is 0-terminated332 for(y = x; y; y--)333 {334 // Move items down.335 strncpy(rw_recent_files[y], rw_recent_files[y - 1], len);336 }338 // Put item on top.339 strncpy(rw_recent_files[0],tmp, len);341 // Update the recent files menu342 UpdateRW_RMenu(menu, menuItem, baseId);344 return;345 }346 }347 }349 // The filename wasn't found in the list. That means we need to add it.351 // Move the other items down.352 for(unsigned int x = arrayLen - 1; x; x--)353 {354 strncpy(rw_recent_files[x],rw_recent_files[x - 1], len);355 }357 // Add the new item.358 strncpy(rw_recent_files[0], addString, len);359 rw_recent_files[0][len - 1] = '\0'; // better not assume that361 // Update the recent files menu362 UpdateRW_RMenu(menu, menuItem, baseId);363 }365 void RWAddRecentFile(const char *filename)366 {367 UpdateRWRecentArray(filename, MAX_RECENT_WATCHES, rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE);368 }370 void OpenRWRecentFile(int memwRFileNumber)371 {372 if(!ResetWatches())373 return;375 int rnum = memwRFileNumber;376 if ((unsigned int)rnum >= MAX_RECENT_WATCHES)377 return; //just in case379 char* x;381 while(true)382 {383 x = rw_recent_files[rnum];384 if (!*x)385 return; //If no recent files exist just return. Useful for Load last file on startup (or if something goes screwy)387 if (rnum) //Change order of recent files if not most recent388 {389 RWAddRecentFile(x);390 rnum = 0;391 }392 else393 {394 break;395 }396 }398 strcpy(currentWatch,x);399 strcpy(Str_Tmp,currentWatch);401 //loadwatches here402 FILE *WatchFile = fopen(Str_Tmp,"rb");403 if (!WatchFile)404 {405 systemSoundClearBuffer();406 int answer = MessageBox(MESSAGEBOXPARENT,"Error opening file.","ERROR",MB_OKCANCEL);407 if (answer == IDOK)408 {409 rw_recent_files[rnum][0] = '\0'; //Clear file from list410 if (rnum) //Update the ramwatch list411 RWAddRecentFile(rw_recent_files[0]);412 else413 RWAddRecentFile(rw_recent_files[1]);414 }415 return;416 }417 const char DELIM = '\t';418 AddressWatcher Temp;419 char mode;420 fgets(Str_Tmp,1024,WatchFile);421 sscanf(Str_Tmp,"%c%*s",&mode);422 //if ((mode == '1' && !(SegaCD_Started)) || (mode == '2' && !(_32X_Started)))423 //{424 // char Device[8];425 // strcpy(Device,(mode > '1')?"32X":"SegaCD");426 // sprintf(Str_Tmp,"Warning: %s not started. \nWatches for %s addresses will be ignored.",Device,Device);427 // MessageBox(MESSAGEBOXPARENT,Str_Tmp,"Possible Device Mismatch",MB_OK);428 //}429 int WatchAdd;430 fgets(Str_Tmp,1024,WatchFile);431 sscanf(Str_Tmp,"%d%*s",&WatchAdd);432 WatchAdd+=WatchCount;433 for (int i = WatchCount; i < WatchAdd; i++)434 {435 while (i < 0)436 i++;437 do {438 fgets(Str_Tmp,1024,WatchFile);439 } while (Str_Tmp[0] == '\n');440 sscanf(Str_Tmp,"%*05X%*c%08X%*c%c%*c%c%*c%d",&(Temp.Address),&(Temp.Size),&(Temp.Type),&(Temp.WrongEndian));441 Temp.WrongEndian = 0;442 char *Comment = strrchr(Str_Tmp,DELIM) + 1;443 *strrchr(Comment,'\n') = '\0';444 InsertWatch(Temp,Comment);445 }447 fclose(WatchFile);448 if (RamWatchHWnd) {449 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);450 RefreshWatchListSelectedCountControlStatus(RamWatchHWnd);451 }452 RWfileChanged=false;453 return;454 }456 int Change_File_L(char *Dest, const char *Dir, const char *Titre, const char *Filter, const char *Ext, HWND hwnd)457 {458 if (!strcmp(Dest, ""))459 {460 strcpy(Dest, "default.");461 strcat(Dest, Ext);462 }464 SetCurrentDirectory(winGetDestDir(IDS_WATCH_DIR));466 OPENFILENAME ofn;468 memset(&ofn, 0, sizeof(OPENFILENAME));470 ofn.lStructSize = sizeof(OPENFILENAME);471 ofn.hwndOwner = hwnd;472 ofn.hInstance = hInst;473 ofn.lpstrFile = Dest;474 ofn.nMaxFile = 2047;475 ofn.lpstrFilter = Filter;476 ofn.nFilterIndex = 1;477 ofn.lpstrInitialDir = Dir;478 ofn.lpstrTitle = Titre;479 ofn.lpstrDefExt = Ext;480 ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;482 systemSoundClearBuffer();484 if (GetOpenFileName(&ofn)) return 1;486 return 0;487 }489 int Change_File_S(char *Dest, const char *Dir, const char *Titre, const char *Filter, const char *Ext, HWND hwnd)490 {491 if (!strcmp(Dest, ""))492 {493 strcpy(Dest, "default.");494 strcat(Dest, Ext);495 }497 SetCurrentDirectory(winGetDestDir(IDS_WATCH_DIR));499 OPENFILENAME ofn;501 memset(&ofn, 0, sizeof(OPENFILENAME));503 ofn.lStructSize = sizeof(OPENFILENAME);504 ofn.hwndOwner = hwnd;505 ofn.hInstance = hInst;506 ofn.lpstrFile = Dest;507 ofn.nMaxFile = 2047;508 ofn.lpstrFilter = Filter;509 ofn.nFilterIndex = 1;510 ofn.lpstrInitialDir = Dir;511 ofn.lpstrTitle = Titre;512 ofn.lpstrDefExt = Ext;513 ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;515 if (GetSaveFileName(&ofn)) return 1;517 return 0;518 }520 bool Save_Watches()521 {522 const char* slash = max(strrchr(gamefilename, '|'), max(strrchr(gamefilename, '\\'), strrchr(gamefilename, '/')));523 strcpy(Str_Tmp,slash ? slash+1 : gamefilename);524 char* dot = strrchr(Str_Tmp, '.');525 if(dot) *dot = 0;526 strcat(Str_Tmp,".wch");527 if(Change_File_S(Str_Tmp, winGetDestDir(IDS_WATCH_DIR), "Save Watches", "Watchlist\0*.wch\0All Files\0*.*\0\0", "wch", RamWatchHWnd))528 {529 FILE *WatchFile = fopen(Str_Tmp,"r+b");530 if (!WatchFile) WatchFile = fopen(Str_Tmp,"w+b");531 fputc('\n',WatchFile);532 strcpy(currentWatch,Str_Tmp);533 RWAddRecentFile(currentWatch);534 sprintf(Str_Tmp,"%d\n",WatchCount);535 fputs(Str_Tmp,WatchFile);536 const char DELIM = '\t';537 for (int i = 0; i < WatchCount; i++)538 {539 sprintf(Str_Tmp,"%05X%c%08X%c%c%c%c%c%d%c%s\n",i,DELIM,rswatches[i].Address,DELIM,rswatches[i].Size,DELIM,rswatches[i].Type,DELIM,rswatches[i].WrongEndian,DELIM,rswatches[i].comment);540 fputs(Str_Tmp,WatchFile);541 }543 fclose(WatchFile);544 RWfileChanged=false;545 //TODO: Add to recent list function call here546 return true;547 }548 return false;549 }551 bool QuickSaveWatches()552 {553 if (RWfileChanged==false) return true; //If file has not changed, no need to save changes554 if (currentWatch[0] == NULL) //If there is no currently loaded file, run to Save as and then return555 {556 return Save_Watches();557 }559 strcpy(Str_Tmp,currentWatch);560 FILE *WatchFile = fopen(Str_Tmp,"r+b");561 if (!WatchFile) WatchFile = fopen(Str_Tmp,"w+b");562 fputc('\n',WatchFile);563 sprintf(Str_Tmp,"%d\n",WatchCount);564 fputs(Str_Tmp,WatchFile);565 const char DELIM = '\t';566 for (int i = 0; i < WatchCount; i++)567 {568 sprintf(Str_Tmp,"%05X%c%08X%c%c%c%c%c%d%c%s\n",i,DELIM,rswatches[i].Address,DELIM,rswatches[i].Size,DELIM,rswatches[i].Type,DELIM,rswatches[i].WrongEndian,DELIM,rswatches[i].comment);569 fputs(Str_Tmp,WatchFile);570 }571 fclose(WatchFile);572 RWfileChanged=false;573 return true;574 }576 bool Load_Watches(bool clear, const char* filename)577 {578 const char DELIM = '\t';579 FILE* WatchFile = fopen(filename,"rb");580 if (!WatchFile)581 {582 systemSoundClearBuffer();583 MessageBox(MESSAGEBOXPARENT,"Error opening file.","ERROR",MB_OK);584 return false;585 }586 if(clear)587 {588 if(!ResetWatches())589 {590 fclose(WatchFile);591 return false;592 }593 }594 strcpy(currentWatch,filename);595 RWAddRecentFile(currentWatch);596 AddressWatcher Temp;597 char mode;598 fgets(Str_Tmp,1024,WatchFile);599 sscanf(Str_Tmp,"%c%*s",&mode);600 int WatchAdd;601 fgets(Str_Tmp,1024,WatchFile);602 sscanf(Str_Tmp,"%d%*s",&WatchAdd);603 WatchAdd+=WatchCount;604 for (int i = WatchCount; i < WatchAdd; i++)605 {606 while (i < 0)607 i++;608 do {609 fgets(Str_Tmp,1024,WatchFile);610 } while (Str_Tmp[0] == '\n');611 sscanf(Str_Tmp,"%*05X%*c%08X%*c%c%*c%c%*c%d",&(Temp.Address),&(Temp.Size),&(Temp.Type),&(Temp.WrongEndian));612 Temp.WrongEndian = 0;613 char *Comment = strrchr(Str_Tmp,DELIM) + 1;614 *strrchr(Comment,'\n') = '\0';615 InsertWatch(Temp,Comment);616 }618 fclose(WatchFile);619 if (RamWatchHWnd)620 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);621 RWfileChanged=false;622 return true;623 }625 bool Load_Watches(bool clear)626 {627 const char* slash = max(strrchr(gamefilename, '|'), max(strrchr(gamefilename, '\\'), strrchr(gamefilename, '/')));628 strcpy(Str_Tmp,slash ? slash+1 : gamefilename);629 char* dot = strrchr(Str_Tmp, '.');630 if(dot) *dot = 0;631 strcat(Str_Tmp,".wch");632 if(Change_File_L(Str_Tmp, winGetDestDir(IDS_WATCH_DIR), "Load Watches", "Watchlist\0*.wch\0All Files\0*.*\0\0", "wch", RamWatchHWnd))633 {634 return Load_Watches(clear, Str_Tmp);635 }636 return false;637 }639 bool ResetWatches()640 {641 if(!AskSave())642 return false;643 for (;WatchCount>=0;WatchCount--)644 {645 free(rswatches[WatchCount].comment);646 rswatches[WatchCount].comment = NULL;647 }648 WatchCount++;649 if (RamWatchHWnd) {650 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);651 RefreshWatchListSelectedCountControlStatus(RamWatchHWnd);652 }653 RWfileChanged = false;654 currentWatch[0] = NULL;655 return true;656 }658 void RemoveWatch(int watchIndex)659 {660 free(rswatches[watchIndex].comment);661 rswatches[watchIndex].comment = NULL;662 for (int i = watchIndex; i <= WatchCount; i++)663 rswatches[i] = rswatches[i+1];664 WatchCount--;665 }667 LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) //Gets info for a RAM Watch, and then inserts it into the Watch List668 {669 RECT r;670 RECT r2;671 int dx1, dy1, dx2, dy2;672 static int index;673 static char s,t = s = 0;675 switch(uMsg)676 {677 case WM_INITDIALOG:678 //Clear_Sound_Buffer();681 GetWindowRect(hWnd, &r);682 dx1 = (r.right - r.left) / 2;683 dy1 = (r.bottom - r.top) / 2;685 GetWindowRect(hDlg, &r2);686 dx2 = (r2.right - r2.left) / 2;687 dy2 = (r2.bottom - r2.top) / 2;689 //SetWindowPos(hDlg, NULL, max(0, r.left + (dx1 - dx2)), max(0, r.top + (dy1 - dy2)), NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);690 SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);691 index = (int)lParam;692 sprintf(Str_Tmp,"%08X",rswatches[index].Address);693 SetDlgItemText(hDlg,IDC_EDIT_COMPAREADDRESS,Str_Tmp);694 if (rswatches[index].comment != NULL)695 SetDlgItemText(hDlg,IDC_PROMPT_EDIT,rswatches[index].comment);696 s = rswatches[index].Size;697 t = rswatches[index].Type;698 switch (s)699 {700 case 'b':701 SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0);702 break;703 case 'w':704 SendDlgItemMessage(hDlg, IDC_2_BYTES, BM_SETCHECK, BST_CHECKED, 0);705 break;706 case 'd':707 SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_SETCHECK, BST_CHECKED, 0);708 break;709 default:710 s = 0;711 break;712 }713 switch (t)714 {715 case 's':716 SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0);717 break;718 case 'u':719 SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0);720 break;721 case 'h':722 SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_CHECKED, 0);723 break;724 default:725 t = 0;726 break;727 }729 return true;730 break;732 case WM_COMMAND:733 switch(LOWORD(wParam))734 {735 case IDC_SIGNED:736 t='s';737 return true;738 case IDC_UNSIGNED:739 t='u';740 return true;741 case IDC_HEX:742 t='h';743 return true;744 case IDC_1_BYTE:745 s = 'b';746 return true;747 case IDC_2_BYTES:748 s = 'w';749 return true;750 case IDC_4_BYTES:751 s = 'd';752 return true;753 case IDOK:754 {755 if (s && t)756 {757 AddressWatcher Temp;758 Temp.Size = s;759 Temp.Type = t;760 Temp.WrongEndian = false; //replace this when I get little endian working properly761 GetDlgItemText(hDlg,IDC_EDIT_COMPAREADDRESS,Str_Tmp,1024);762 char *addrstr = Str_Tmp;763 if (strlen(Str_Tmp) > 8) addrstr = &(Str_Tmp[strlen(Str_Tmp) - 9]);764 for(int i = 0; addrstr[i]; i++) {if(toupper(addrstr[i]) == 'O') addrstr[i] = '0';}765 sscanf(addrstr,"%08X",&(Temp.Address));767 if((Temp.Address & ~0xFFFFFF) == ~0xFFFFFF)768 Temp.Address &= 0xFFFFFF;770 if(IsHardwareAddressValid(Temp.Address))771 {772 GetDlgItemText(hDlg,IDC_PROMPT_EDIT,Str_Tmp,80);773 if (index < WatchCount) RemoveWatch(index);774 InsertWatch(Temp,Str_Tmp);775 if(RamWatchHWnd)776 {777 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);778 }779 EndDialog(hDlg, true);780 }781 else782 {783 MessageBox(hDlg,"Invalid Address","ERROR",MB_OK);784 }785 }786 else787 {788 strcpy(Str_Tmp,"Error:");789 if (!s)790 strcat(Str_Tmp," Size must be specified.");791 if (!t)792 strcat(Str_Tmp," Type must be specified.");793 MessageBox(hDlg,Str_Tmp,"ERROR",MB_OK);794 }795 RWfileChanged=true;796 return true;797 break;798 }799 case ID_CANCEL:800 case IDCANCEL:801 EndDialog(hDlg, false);802 return false;803 break;804 }805 break;807 case WM_CLOSE:808 EndDialog(hDlg, false);809 return false;810 break;811 }813 return false;814 }819 void RamWatchEnableCommand(HWND hDlg, HMENU hMenu, UINT uIDEnableItem, bool enable)820 {821 EnableWindow(GetDlgItem(hDlg, uIDEnableItem), (enable?TRUE:FALSE));822 if (hMenu != NULL) {823 if (uIDEnableItem == ID_WATCHES_UPDOWN) {824 EnableMenuItem(hMenu, IDC_C_WATCH_UP, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED));825 EnableMenuItem(hMenu, IDC_C_WATCH_DOWN, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED));826 }827 else828 EnableMenuItem(hMenu, uIDEnableItem, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED));829 }830 }832 void RefreshWatchListSelectedCountControlStatus(HWND hDlg)833 {834 int selCount = ListView_GetSelectedCount(GetDlgItem(hDlg,IDC_WATCHLIST));835 if(selCount != s_prevSelCount)836 {837 if(selCount < 2 || s_prevSelCount < 2)838 {839 RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_EDIT, selCount == 1);840 RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_REMOVE, selCount >= 1);841 RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH, WatchCount < MAX_WATCH_COUNT);842 RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_DUPLICATE, selCount == 1 && WatchCount < MAX_WATCH_COUNT);843 RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_ADDCHEAT, selCount == 1);844 RamWatchEnableCommand(hDlg, ramwatchmenu, ID_WATCHES_UPDOWN, selCount == 1);845 }846 s_prevSelCount = selCount;847 }848 }850 LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)851 {852 RECT r;853 RECT r2;854 int dx1, dy1, dx2, dy2;855 static int watchIndex=0;857 switch(uMsg)858 {859 case WM_MOVE: {860 RECT wrect;861 GetWindowRect(hDlg,&wrect);862 ramw_x = wrect.left;863 ramw_y = wrect.top;864 regSetDwordValue(RAMWX, ramw_x);865 regSetDwordValue(RAMWY, ramw_y);866 } break;868 case WM_INITDIALOG: {869 GetWindowRect(hWnd, &r); //Ramwatch window870 dx1 = (r.right - r.left) / 2;871 dy1 = (r.bottom - r.top) / 2;873 GetWindowRect(hDlg, &r2); // TASer window874 dx2 = (r2.right - r2.left) / 2;875 dy2 = (r2.bottom - r2.top) / 2;878 // push it away from the main window if we can879 const int width = (r.right-r.left);880 const int height = (r.bottom - r.top);881 const int width2 = (r2.right-r2.left);882 if(r.left+width2 + width < GetSystemMetrics(SM_CXSCREEN))883 {884 r.right += width;885 r.left += width;886 }887 else if((int)r.left - (int)width2 > 0)888 {889 r.right -= width2;890 r.left -= width2;891 }893 //-----------------------------------------------------------------------------------894 //If user has Save Window Pos selected, override default positioning895 if (RWSaveWindowPos)896 {897 //If ramwindow is for some reason completely off screen, use default instead898 if (ramw_x > (-width*2) || ramw_x < (width*2 + GetSystemMetrics(SM_CYSCREEN)) )899 r.left = ramw_x; //This also ignores cases of windows -32000 error codes900 //If ramwindow is for some reason completely off screen, use default instead901 if (ramw_y > (0-height*2) ||ramw_y < (height*2 + GetSystemMetrics(SM_CYSCREEN)) )902 r.top = ramw_y; //This also ignores cases of windows -32000 error codes903 }904 //-------------------------------------------------------------------------------------905 SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);907 ramwatchmenu=GetMenu(hDlg);908 rwrecentmenu=CreateMenu();909 UpdateRW_RMenu(rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE);911 const char* names[3] = {"Address","Value","Notes"};912 int widths[3] = {62,64,64+51+53};913 init_list_box(GetDlgItem(hDlg,IDC_WATCHLIST),names,3,widths);914 if (!ResultCount)915 reset_address_info();916 else917 signal_new_frame();918 ListView_SetItemCount(GetDlgItem(hDlg,IDC_WATCHLIST),WatchCount);919 if (!noMisalign) SendDlgItemMessage(hDlg, IDC_MISALIGN, BM_SETCHECK, BST_CHECKED, 0);920 //if (littleEndian) SendDlgItemMessage(hDlg, IDC_ENDIAN, BM_SETCHECK, BST_CHECKED, 0);922 RamWatchAccels = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATOR1));924 // due to some bug in windows, the arrow button width from the resource gets ignored, so we have to set it here925 SetWindowPos(GetDlgItem(hDlg,ID_WATCHES_UPDOWN), 0,0,0, 30,60, SWP_NOMOVE);927 Update_RAM_Watch();929 DragAcceptFiles(hDlg, TRUE);931 s_prevSelCount = -1;932 RefreshWatchListSelectedCountControlStatus(hDlg);933 return false;934 } break;936 case WM_INITMENU:937 CheckMenuItem(ramwatchmenu, RAMMENU_FILE_AUTOLOAD, AutoRWLoad ? MF_CHECKED : MF_UNCHECKED);938 CheckMenuItem(ramwatchmenu, RAMMENU_FILE_SAVEWINDOW, RWSaveWindowPos ? MF_CHECKED : MF_UNCHECKED);939 break;941 case WM_ENTERMENULOOP:942 systemSoundClearBuffer();943 break;945 case WM_MENUSELECT:946 case WM_ENTERSIZEMOVE:947 //Clear_Sound_Buffer();948 break;950 case WM_NOTIFY:951 {952 switch(wParam)953 {954 case ID_WATCHES_UPDOWN:955 {956 switch(((LPNMUPDOWN)lParam)->hdr.code)957 {958 case UDN_DELTAPOS: {959 int delta = ((LPNMUPDOWN)lParam)->iDelta;960 SendMessage(hDlg, WM_COMMAND, delta<0 ? IDC_C_WATCH_UP : IDC_C_WATCH_DOWN,0);961 } break;962 }963 } break;965 default:966 {967 LPNMHDR lP = (LPNMHDR) lParam;968 switch (lP->code)969 {970 case LVN_ITEMCHANGED: // selection changed event971 {972 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lP;973 if(pNMListView->uNewState & LVIS_FOCUSED ||974 (pNMListView->uNewState ^ pNMListView->uOldState) & LVIS_SELECTED)975 {976 // disable buttons that we don't have the right number of selected items for977 RefreshWatchListSelectedCountControlStatus(hDlg);978 }979 } break;981 case LVN_GETDISPINFO:982 {983 LV_DISPINFO *Item = (LV_DISPINFO *)lParam;984 Item->item.mask = LVIF_TEXT;985 Item->item.state = 0;986 Item->item.iImage = 0;987 const unsigned int iNum = Item->item.iItem;988 static char num[11];989 switch (Item->item.iSubItem)990 {991 case 0:992 sprintf(num,"%08X",rswatches[iNum].Address);993 Item->item.pszText = num;994 return true;995 case 1: {996 int i = rswatches[iNum].CurValue;997 int t = rswatches[iNum].Type;998 int size = rswatches[iNum].Size;999 const char* formatString = ((t=='s') ? "%d" : (t=='u') ? "%u" : (size=='d' ? "%08X" : size=='w' ? "%04X" : "%02X"));1000 switch (size)1001 {1002 case 'b':1003 default: sprintf(num, formatString, t=='s' ? (char)(i&0xff) : (unsigned char)(i&0xff)); break;1004 case 'w': sprintf(num, formatString, t=='s' ? (short)(i&0xffff) : (unsigned short)(i&0xffff)); break;1005 case 'd': sprintf(num, formatString, t=='s' ? (long)(i&0xffffffff) : (unsigned long)(i&0xffffffff)); break;1006 }1008 Item->item.pszText = num;1009 } return true;1010 case 2:1011 Item->item.pszText = rswatches[iNum].comment ? rswatches[iNum].comment : "";1012 return true;1014 default:1015 return false;1016 }1017 }1018 case LVN_ODFINDITEM:1019 {1020 // disable search by keyboard typing,1021 // because it interferes with some of the accelerators1022 // and it isn't very useful here anyway1023 SetWindowLong(hDlg, DWL_MSGRESULT, ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST)));1024 return 1;1025 }1026 }1027 }1028 }1029 } break;1031 case WM_COMMAND:1032 switch(LOWORD(wParam))1033 {1034 case RAMMENU_FILE_SAVE:1035 QuickSaveWatches();1036 break;1038 case RAMMENU_FILE_SAVEAS:1039 //case IDC_C_SAVE:1040 return Save_Watches();1041 case RAMMENU_FILE_OPEN:1042 return Load_Watches(true);1043 case RAMMENU_FILE_APPEND:1044 //case IDC_C_LOAD:1045 return Load_Watches(false);1046 case RAMMENU_FILE_NEW:1047 //case IDC_C_RESET:1048 ResetWatches();1049 return true;1050 case IDC_C_WATCH_REMOVE:1051 {1052 HWND watchListControl = GetDlgItem(hDlg, IDC_WATCHLIST);1053 watchIndex = ListView_GetNextItem(watchListControl, -1, LVNI_ALL | LVNI_SELECTED);1054 while (watchIndex >= 0)1055 {1056 RemoveWatch(watchIndex);1057 ListView_DeleteItem(watchListControl, watchIndex);1058 watchIndex = ListView_GetNextItem(watchListControl, -1, LVNI_ALL | LVNI_SELECTED);1059 }1060 RWfileChanged=true;1061 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));1062 return true;1063 }1064 case IDC_C_WATCH_EDIT:1065 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));1066 if(watchIndex != -1)1067 {1068 systemSoundClearBuffer();1069 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC) EditWatchProc,(LPARAM) watchIndex);1070 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));1071 }1072 return true;1073 case IDC_C_WATCH:1074 rswatches[WatchCount].Address = rswatches[WatchCount].WrongEndian = 0;1075 rswatches[WatchCount].Size = 'b';1076 rswatches[WatchCount].Type = 's';1077 systemSoundClearBuffer();1078 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC) EditWatchProc,(LPARAM) WatchCount);1079 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));1080 return true;1081 case IDC_C_WATCH_DUPLICATE:1082 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));1083 if(watchIndex != -1)1084 {1085 rswatches[WatchCount].Address = rswatches[watchIndex].Address;1086 rswatches[WatchCount].WrongEndian = rswatches[watchIndex].WrongEndian;1087 rswatches[WatchCount].Size = rswatches[watchIndex].Size;1088 rswatches[WatchCount].Type = rswatches[watchIndex].Type;1089 systemSoundClearBuffer();1090 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC) EditWatchProc,(LPARAM) WatchCount);1091 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));1092 }1093 return true;1095 case IDC_C_WATCH_SEPARATE:1096 AddressWatcher separator;1097 separator.Address = 0;1098 separator.WrongEndian = false;1099 separator.Size = 'S';1100 separator.Type = 'S';1101 InsertWatch(separator, "----------------------------");1102 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));1103 return true;1105 case IDC_C_WATCH_UP:1106 {1107 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));1108 if (watchIndex == 0 || watchIndex == -1)1109 return true;1110 void *tmp = malloc(sizeof(AddressWatcher));1111 memcpy(tmp,&(rswatches[watchIndex]),sizeof(AddressWatcher));1112 memcpy(&(rswatches[watchIndex]),&(rswatches[watchIndex - 1]),sizeof(AddressWatcher));1113 memcpy(&(rswatches[watchIndex - 1]),tmp,sizeof(AddressWatcher));1114 free(tmp);1115 ListView_SetItemState(GetDlgItem(hDlg,IDC_WATCHLIST),watchIndex,0,LVIS_FOCUSED|LVIS_SELECTED);1116 ListView_SetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST),watchIndex-1);1117 ListView_SetItemState(GetDlgItem(hDlg,IDC_WATCHLIST),watchIndex-1,LVIS_FOCUSED|LVIS_SELECTED,LVIS_FOCUSED|LVIS_SELECTED);1118 ListView_SetItemCount(GetDlgItem(hDlg,IDC_WATCHLIST),WatchCount);1119 RWfileChanged=true;1120 return true;1121 }1122 case IDC_C_WATCH_DOWN:1123 {1124 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));1125 if (watchIndex >= WatchCount - 1 || watchIndex == -1)1126 return true;1127 void *tmp = malloc(sizeof(AddressWatcher));1128 memcpy(tmp,&(rswatches[watchIndex]),sizeof(AddressWatcher));1129 memcpy(&(rswatches[watchIndex]),&(rswatches[watchIndex + 1]),sizeof(AddressWatcher));1130 memcpy(&(rswatches[watchIndex + 1]),tmp,sizeof(AddressWatcher));1131 free(tmp);1132 ListView_SetItemState(GetDlgItem(hDlg,IDC_WATCHLIST),watchIndex,0,LVIS_FOCUSED|LVIS_SELECTED);1133 ListView_SetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST),watchIndex+1);1134 ListView_SetItemState(GetDlgItem(hDlg,IDC_WATCHLIST),watchIndex+1,LVIS_FOCUSED|LVIS_SELECTED,LVIS_FOCUSED|LVIS_SELECTED);1135 ListView_SetItemCount(GetDlgItem(hDlg,IDC_WATCHLIST),WatchCount);1136 RWfileChanged=true;1137 return true;1138 }1139 case ID_WATCHES_UPDOWN:1140 {1141 int delta = ((LPNMUPDOWN)lParam)->iDelta;1142 SendMessage(hDlg, WM_COMMAND, delta<0 ? IDC_C_WATCH_UP : IDC_C_WATCH_DOWN,0);1143 break;1144 }1145 case RAMMENU_FILE_AUTOLOAD:1146 {1147 AutoRWLoad ^= 1;1148 CheckMenuItem(ramwatchmenu, RAMMENU_FILE_AUTOLOAD, AutoRWLoad ? MF_CHECKED : MF_UNCHECKED);1149 regSetDwordValue(AUTORWLOAD, AutoRWLoad);1150 break;1151 }1152 case RAMMENU_FILE_SAVEWINDOW:1153 {1154 RWSaveWindowPos ^=1;1155 CheckMenuItem(ramwatchmenu, RAMMENU_FILE_SAVEWINDOW, RWSaveWindowPos ? MF_CHECKED : MF_UNCHECKED);1156 regSetDwordValue(RWSAVEPOS, RWSaveWindowPos);1157 break;1158 }1159 case IDC_C_ADDCHEAT:1160 {1161 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));1162 if(watchIndex >= 0)1163 {1164 unsigned int address = rswatches[watchIndex].Address;1166 int sizeType = -1;1167 if(rswatches[watchIndex].Size == 'b')1168 sizeType = 0;1169 else if(rswatches[watchIndex].Size == 'w')1170 sizeType = 1;1171 else if(rswatches[watchIndex].Size == 'd')1172 sizeType = 2;1174 int numberType = -1;1175 if(rswatches[watchIndex].Type == 's')1176 numberType = 0;1177 else if(rswatches[watchIndex].Type == 'u')1178 numberType = 1;1179 else if(rswatches[watchIndex].Type == 'h')1180 numberType = 2;1182 if(systemCartridgeType == 0)1183 {1184 AddCheat dlg (address/*, hDlg*/);1185 if(sizeType != -1) dlg.sizeType = sizeType;1186 if(numberType != -1) dlg.numberType = numberType;1187 systemSoundClearBuffer();1188 dlg.DoModal();1189 }1190 else1191 {1192 AddGBCheat dlg (address/*, hDlg*/);1193 if(sizeType != -1) dlg.sizeType = sizeType;1194 if(numberType != -1) dlg.numberType = numberType;1195 systemSoundClearBuffer();1196 dlg.DoModal();1197 }1198 }1199 }1200 break;1201 case IDOK:1202 case IDCANCEL:1203 RamWatchHWnd = NULL;1204 DragAcceptFiles(hDlg, FALSE);1205 EndDialog(hDlg, true);1206 return true;1207 default:1208 if (LOWORD(wParam) >= RW_MENU_FIRST_RECENT_FILE && LOWORD(wParam) < RW_MENU_FIRST_RECENT_FILE+MAX_RECENT_WATCHES && LOWORD(wParam) <= RW_MENU_LAST_RECENT_FILE)1209 OpenRWRecentFile(LOWORD(wParam) - RW_MENU_FIRST_RECENT_FILE);1210 }1211 break;1213 #if 01214 // this message is never received1215 case WM_KEYDOWN: // handle accelerator keys1216 {1217 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));1218 MSG msg;1219 msg.hwnd = hDlg;1220 msg.message = uMsg;1221 msg.wParam = wParam;1222 msg.lParam = lParam;1223 if(RamWatchAccels && TranslateAccelerator(hDlg, RamWatchAccels, &msg))1224 return true;1225 } break;1226 #endif1228 case WM_CLOSE:1229 SendMessage(RamWatchHWnd, WM_DESTROY, 0, 0);1230 break;1232 case WM_DESTROY:1233 // this is the correct place1234 RamWatchHWnd = NULL;1235 DragAcceptFiles(hDlg, FALSE);1236 WriteRecentRWFiles(); // write recent menu to ini1237 break;1239 case WM_DROPFILES:1240 {1241 HDROP hDrop = (HDROP)wParam;1242 DragQueryFile(hDrop, 0, Str_Tmp, 1024);1243 DragFinish(hDrop);1244 return Load_Watches(true, Str_Tmp);1245 } break;1246 }1248 return false;1249 }