view src/win32/ramwatch.cpp @ 4:5f6f2134e8ce

apu appears to not be used
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:35:58 -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 changes
30 bool AutoRWLoad = false; //Keeps track of whether Auto-load is checked
31 bool RWSaveWindowPos = false; //Keeps track of whether Save Window position is checked
32 char currentWatch[1024];
33 int ramw_x, ramw_y; //Used to store ramwatch dialog window positions
34 AddressWatcher rswatches[MAX_WATCH_COUNT];
35 int WatchCount=0;
36 static int s_prevSelCount=-1;
38 HWND RamWatchHWnd;
39 #define gamefilename theApp.gameFilename
40 #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 listbox
46 #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 address
98 {
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 items
181 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 changed
194 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 item
197 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 else
211 {
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 changed
224 //returns false only if a save was attempted but failed or was cancelled
225 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 submenus
262 for(x = 0; x < MAX_RECENT_WATCHES; x++)
263 {
264 RemoveMenu(menu, baseid + x, MF_BYCOMMAND);
265 }
267 // Recreate the menus
268 for(x = MAX_RECENT_WATCHES - 1; x >= 0; x--)
269 {
270 // Skip empty strings
271 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 0
280 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 else
289 {
290 sprintf(tmp, "&%d. %s", ( x + 1 ) % 10, rw_recent_files[x] + strlen( rw_recent_files[x] ) - 127);
291 }
292 #endif
293 // the ATL way; it is really pain to work out a MBCS-compatible string replace function in the pure c way
294 CString atltmp(rw_recent_files[x]);
295 atltmp.Replace("&", "&&");
296 char *tmp = atltmp.GetBuffer(0);
298 // Insert the menu item
299 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 row
309 // WriteRecentRWFiles(); // write recent menu to ini
310 }
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 numbers
316 // 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-terminated
332 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 menu
342 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 that
361 // Update the recent files menu
362 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 case
379 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 recent
388 {
389 RWAddRecentFile(x);
390 rnum = 0;
391 }
392 else
393 {
394 break;
395 }
396 }
398 strcpy(currentWatch,x);
399 strcpy(Str_Tmp,currentWatch);
401 //loadwatches here
402 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 list
410 if (rnum) //Update the ramwatch list
411 RWAddRecentFile(rw_recent_files[0]);
412 else
413 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 here
546 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 changes
554 if (currentWatch[0] == NULL) //If there is no currently loaded file, run to Save as and then return
555 {
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 List
668 {
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 properly
761 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 else
782 {
783 MessageBox(hDlg,"Invalid Address","ERROR",MB_OK);
784 }
785 }
786 else
787 {
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 else
828 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 window
870 dx1 = (r.right - r.left) / 2;
871 dy1 = (r.bottom - r.top) / 2;
873 GetWindowRect(hDlg, &r2); // TASer window
874 dx2 = (r2.right - r2.left) / 2;
875 dy2 = (r2.bottom - r2.top) / 2;
878 // push it away from the main window if we can
879 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 positioning
895 if (RWSaveWindowPos)
896 {
897 //If ramwindow is for some reason completely off screen, use default instead
898 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 codes
900 //If ramwindow is for some reason completely off screen, use default instead
901 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 codes
903 }
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 else
917 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 here
925 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 event
971 {
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 for
977 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)
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;
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;
1018 case LVN_ODFINDITEM:
1020 // disable search by keyboard typing,
1021 // because it interferes with some of the accelerators
1022 // and it isn't very useful here anyway
1023 SetWindowLong(hDlg, DWL_MSGRESULT, ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST)));
1024 return 1;
1029 } break;
1031 case WM_COMMAND:
1032 switch(LOWORD(wParam))
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:
1052 HWND watchListControl = GetDlgItem(hDlg, IDC_WATCHLIST);
1053 watchIndex = ListView_GetNextItem(watchListControl, -1, LVNI_ALL | LVNI_SELECTED);
1054 while (watchIndex >= 0)
1056 RemoveWatch(watchIndex);
1057 ListView_DeleteItem(watchListControl, watchIndex);
1058 watchIndex = ListView_GetNextItem(watchListControl, -1, LVNI_ALL | LVNI_SELECTED);
1060 RWfileChanged=true;
1061 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));
1062 return true;
1064 case IDC_C_WATCH_EDIT:
1065 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));
1066 if(watchIndex != -1)
1068 systemSoundClearBuffer();
1069 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC) EditWatchProc,(LPARAM) watchIndex);
1070 SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));
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)
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));
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:
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;
1122 case IDC_C_WATCH_DOWN:
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;
1139 case ID_WATCHES_UPDOWN:
1141 int delta = ((LPNMUPDOWN)lParam)->iDelta;
1142 SendMessage(hDlg, WM_COMMAND, delta<0 ? IDC_C_WATCH_UP : IDC_C_WATCH_DOWN,0);
1143 break;
1145 case RAMMENU_FILE_AUTOLOAD:
1147 AutoRWLoad ^= 1;
1148 CheckMenuItem(ramwatchmenu, RAMMENU_FILE_AUTOLOAD, AutoRWLoad ? MF_CHECKED : MF_UNCHECKED);
1149 regSetDwordValue(AUTORWLOAD, AutoRWLoad);
1150 break;
1152 case RAMMENU_FILE_SAVEWINDOW:
1154 RWSaveWindowPos ^=1;
1155 CheckMenuItem(ramwatchmenu, RAMMENU_FILE_SAVEWINDOW, RWSaveWindowPos ? MF_CHECKED : MF_UNCHECKED);
1156 regSetDwordValue(RWSAVEPOS, RWSaveWindowPos);
1157 break;
1159 case IDC_C_ADDCHEAT:
1161 watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));
1162 if(watchIndex >= 0)
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)
1184 AddCheat dlg (address/*, hDlg*/);
1185 if(sizeType != -1) dlg.sizeType = sizeType;
1186 if(numberType != -1) dlg.numberType = numberType;
1187 systemSoundClearBuffer();
1188 dlg.DoModal();
1190 else
1192 AddGBCheat dlg (address/*, hDlg*/);
1193 if(sizeType != -1) dlg.sizeType = sizeType;
1194 if(numberType != -1) dlg.numberType = numberType;
1195 systemSoundClearBuffer();
1196 dlg.DoModal();
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);
1211 break;
1213 #if 0
1214 // this message is never received
1215 case WM_KEYDOWN: // handle accelerator keys
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 #endif
1228 case WM_CLOSE:
1229 SendMessage(RamWatchHWnd, WM_DESTROY, 0, 0);
1230 break;
1232 case WM_DESTROY:
1233 // this is the correct place
1234 RamWatchHWnd = NULL;
1235 DragAcceptFiles(hDlg, FALSE);
1236 WriteRecentRWFiles(); // write recent menu to ini
1237 break;
1239 case WM_DROPFILES:
1241 HDROP hDrop = (HDROP)wParam;
1242 DragQueryFile(hDrop, 0, Str_Tmp, 1024);
1243 DragFinish(hDrop);
1244 return Load_Watches(true, Str_Tmp);
1245 } break;
1248 return false;