annotate src/win32/ramwatch.cpp @ 2:3549bbe597ed

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