Mercurial > vba-clojure
comparison src/win32/ramwatch.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
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> | |
14 | |
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 */ | |
23 | |
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; | |
37 | |
38 HWND RamWatchHWnd; | |
39 #define gamefilename theApp.gameFilename | |
40 #define hWnd AfxGetMainWnd()->GetSafeHwnd() | |
41 #define hInst AfxGetInstanceHandle() | |
42 static char Str_Tmp [1024]; | |
43 | |
44 void init_list_box(HWND Box, const char* Strs[], int numColumns, int *columnWidths); //initializes the ram search and/or ram watch listbox | |
45 | |
46 #define MESSAGEBOXPARENT (RamWatchHWnd ? RamWatchHWnd : hWnd) | |
47 | |
48 bool QuickSaveWatches(); | |
49 bool ResetWatches(); | |
50 | |
51 void RefreshWatchListSelectedCountControlStatus(HWND hDlg); | |
52 | |
53 unsigned int GetCurrentValue(AddressWatcher& watch) | |
54 { | |
55 return ReadValueAtHardwareAddress(watch.Address, watch.Size == 'd' ? 4 : watch.Size == 'w' ? 2 : 1); | |
56 } | |
57 | |
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 } | |
63 | |
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 } | |
77 | |
78 | |
79 bool InsertWatch(const AddressWatcher& Watch, char *Comment) | |
80 { | |
81 if(WatchCount >= MAX_WATCH_COUNT) | |
82 return false; | |
83 | |
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; | |
93 | |
94 return true; | |
95 } | |
96 | |
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; | |
102 | |
103 switch(uMsg) | |
104 { | |
105 case WM_INITDIALOG: | |
106 //Clear_Sound_Buffer(); | |
107 | |
108 GetWindowRect(hWnd, &r); | |
109 dx1 = (r.right - r.left) / 2; | |
110 dy1 = (r.bottom - r.top) / 2; | |
111 | |
112 GetWindowRect(hDlg, &r2); | |
113 dx2 = (r2.right - r2.left) / 2; | |
114 dy2 = (r2.bottom - r2.top) / 2; | |
115 | |
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; | |
124 | |
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; | |
143 | |
144 case WM_CLOSE: | |
145 EndDialog(hDlg, false); | |
146 return false; | |
147 break; | |
148 } | |
149 | |
150 return false; | |
151 } | |
152 | |
153 bool InsertWatch(const AddressWatcher& Watch, HWND parent) | |
154 { | |
155 if(!VerifyWatchNotAlreadyAdded(Watch)) | |
156 return false; | |
157 | |
158 if(!parent) | |
159 parent = RamWatchHWnd; | |
160 if(!parent) | |
161 parent = hWnd; | |
162 | |
163 int prevWatchCount = WatchCount; | |
164 | |
165 rswatches[WatchCount] = Watch; | |
166 rswatches[WatchCount].CurValue = GetCurrentValue(rswatches[WatchCount]); | |
167 systemSoundClearBuffer(); | |
168 DialogBox(hInst, MAKEINTRESOURCE(IDD_PROMPT), parent, (DLGPROC) PromptWatchNameProc); | |
169 | |
170 return WatchCount > prevWatchCount; | |
171 } | |
172 | |
173 void Update_RAM_Watch() | |
174 { | |
175 BOOL watchChanged[MAX_WATCH_COUNT] = {0}; | |
176 | |
177 if(WatchCount) | |
178 { | |
179 // update cached values and detect changes to displayed listview items | |
180 | |
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 } | |
192 | |
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 } | |
220 | |
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 } | |
236 | |
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 } | |
246 | |
247 void UpdateRW_RMenu(HMENU menu, unsigned int mitem, unsigned int baseid) | |
248 { | |
249 MENUITEMINFO moo; | |
250 int x; | |
251 | |
252 moo.cbSize = sizeof(moo); | |
253 moo.fMask = MIIM_SUBMENU | MIIM_STATE; | |
254 | |
255 GetMenuItemInfo(GetSubMenu(ramwatchmenu, 0), mitem, FALSE, &moo); | |
256 moo.hSubMenu = menu; | |
257 moo.fState = strlen(rw_recent_files[0]) ? MFS_ENABLED : MFS_GRAYED; | |
258 | |
259 SetMenuItemInfo(GetSubMenu(ramwatchmenu, 0), mitem, FALSE, &moo); | |
260 | |
261 // Remove all recent files submenus | |
262 for(x = 0; x < MAX_RECENT_WATCHES; x++) | |
263 { | |
264 RemoveMenu(menu, baseid + x, MF_BYCOMMAND); | |
265 } | |
266 | |
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 } | |
275 | |
276 moo.cbSize = sizeof(moo); | |
277 moo.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE; | |
278 | |
279 #if 0 | |
280 const int TEMP_STRING_LENGTH = 128 + 5; | |
281 char tmp[TEMP_STRING_LENGTH]; // FIXME? | |
282 | |
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); | |
297 | |
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); | |
304 | |
305 // atltmp.ReleaseBuffer(); | |
306 } | |
307 | |
308 // I don't think one function shall do so many things in a row | |
309 // WriteRecentRWFiles(); // write recent menu to ini | |
310 } | |
311 | |
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 | |
315 | |
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. | |
325 | |
326 int y; | |
327 char tmp[len]; | |
328 | |
329 // Save pointer. | |
330 strncpy(tmp, rw_recent_files[x], len - 1); // assuming rw_recent_files[n] is 0-terminated | |
331 | |
332 for(y = x; y; y--) | |
333 { | |
334 // Move items down. | |
335 strncpy(rw_recent_files[y], rw_recent_files[y - 1], len); | |
336 } | |
337 | |
338 // Put item on top. | |
339 strncpy(rw_recent_files[0],tmp, len); | |
340 | |
341 // Update the recent files menu | |
342 UpdateRW_RMenu(menu, menuItem, baseId); | |
343 | |
344 return; | |
345 } | |
346 } | |
347 } | |
348 | |
349 // The filename wasn't found in the list. That means we need to add it. | |
350 | |
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 } | |
356 | |
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 | |
360 | |
361 // Update the recent files menu | |
362 UpdateRW_RMenu(menu, menuItem, baseId); | |
363 } | |
364 | |
365 void RWAddRecentFile(const char *filename) | |
366 { | |
367 UpdateRWRecentArray(filename, MAX_RECENT_WATCHES, rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE); | |
368 } | |
369 | |
370 void OpenRWRecentFile(int memwRFileNumber) | |
371 { | |
372 if(!ResetWatches()) | |
373 return; | |
374 | |
375 int rnum = memwRFileNumber; | |
376 if ((unsigned int)rnum >= MAX_RECENT_WATCHES) | |
377 return; //just in case | |
378 | |
379 char* x; | |
380 | |
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) | |
386 | |
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 } | |
397 | |
398 strcpy(currentWatch,x); | |
399 strcpy(Str_Tmp,currentWatch); | |
400 | |
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 } | |
446 | |
447 fclose(WatchFile); | |
448 if (RamWatchHWnd) { | |
449 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount); | |
450 RefreshWatchListSelectedCountControlStatus(RamWatchHWnd); | |
451 } | |
452 RWfileChanged=false; | |
453 return; | |
454 } | |
455 | |
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 } | |
463 | |
464 SetCurrentDirectory(winGetDestDir(IDS_WATCH_DIR)); | |
465 | |
466 OPENFILENAME ofn; | |
467 | |
468 memset(&ofn, 0, sizeof(OPENFILENAME)); | |
469 | |
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; | |
481 | |
482 systemSoundClearBuffer(); | |
483 | |
484 if (GetOpenFileName(&ofn)) return 1; | |
485 | |
486 return 0; | |
487 } | |
488 | |
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 } | |
496 | |
497 SetCurrentDirectory(winGetDestDir(IDS_WATCH_DIR)); | |
498 | |
499 OPENFILENAME ofn; | |
500 | |
501 memset(&ofn, 0, sizeof(OPENFILENAME)); | |
502 | |
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; | |
514 | |
515 if (GetSaveFileName(&ofn)) return 1; | |
516 | |
517 return 0; | |
518 } | |
519 | |
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 } | |
542 | |
543 fclose(WatchFile); | |
544 RWfileChanged=false; | |
545 //TODO: Add to recent list function call here | |
546 return true; | |
547 } | |
548 return false; | |
549 } | |
550 | |
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 } | |
558 | |
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 } | |
575 | |
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 } | |
617 | |
618 fclose(WatchFile); | |
619 if (RamWatchHWnd) | |
620 ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount); | |
621 RWfileChanged=false; | |
622 return true; | |
623 } | |
624 | |
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 } | |
638 | |
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 } | |
657 | |
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 } | |
666 | |
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; | |
674 | |
675 switch(uMsg) | |
676 { | |
677 case WM_INITDIALOG: | |
678 //Clear_Sound_Buffer(); | |
679 | |
680 | |
681 GetWindowRect(hWnd, &r); | |
682 dx1 = (r.right - r.left) / 2; | |
683 dy1 = (r.bottom - r.top) / 2; | |
684 | |
685 GetWindowRect(hDlg, &r2); | |
686 dx2 = (r2.right - r2.left) / 2; | |
687 dy2 = (r2.bottom - r2.top) / 2; | |
688 | |
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 } | |
728 | |
729 return true; | |
730 break; | |
731 | |
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)); | |
766 | |
767 if((Temp.Address & ~0xFFFFFF) == ~0xFFFFFF) | |
768 Temp.Address &= 0xFFFFFF; | |
769 | |
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; | |
806 | |
807 case WM_CLOSE: | |
808 EndDialog(hDlg, false); | |
809 return false; | |
810 break; | |
811 } | |
812 | |
813 return false; | |
814 } | |
815 | |
816 | |
817 | |
818 | |
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 } | |
831 | |
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 } | |
849 | |
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; | |
856 | |
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; | |
867 | |
868 case WM_INITDIALOG: { | |
869 GetWindowRect(hWnd, &r); //Ramwatch window | |
870 dx1 = (r.right - r.left) / 2; | |
871 dy1 = (r.bottom - r.top) / 2; | |
872 | |
873 GetWindowRect(hDlg, &r2); // TASer window | |
874 dx2 = (r2.right - r2.left) / 2; | |
875 dy2 = (r2.bottom - r2.top) / 2; | |
876 | |
877 | |
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 } | |
892 | |
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); | |
906 | |
907 ramwatchmenu=GetMenu(hDlg); | |
908 rwrecentmenu=CreateMenu(); | |
909 UpdateRW_RMenu(rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE); | |
910 | |
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); | |
921 | |
922 RamWatchAccels = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATOR1)); | |
923 | |
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); | |
926 | |
927 Update_RAM_Watch(); | |
928 | |
929 DragAcceptFiles(hDlg, TRUE); | |
930 | |
931 s_prevSelCount = -1; | |
932 RefreshWatchListSelectedCountControlStatus(hDlg); | |
933 return false; | |
934 } break; | |
935 | |
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; | |
940 | |
941 case WM_ENTERMENULOOP: | |
942 systemSoundClearBuffer(); | |
943 break; | |
944 | |
945 case WM_MENUSELECT: | |
946 case WM_ENTERSIZEMOVE: | |
947 //Clear_Sound_Buffer(); | |
948 break; | |
949 | |
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; | |
964 | |
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; | |
980 | |
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 } | |
1007 | |
1008 Item->item.pszText = num; | |
1009 } return true; | |
1010 case 2: | |
1011 Item->item.pszText = rswatches[iNum].comment ? rswatches[iNum].comment : ""; | |
1012 return true; | |
1013 | |
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 accelerators | |
1022 // and it isn't very useful here anyway | |
1023 SetWindowLong(hDlg, DWL_MSGRESULT, ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST))); | |
1024 return 1; | |
1025 } | |
1026 } | |
1027 } | |
1028 } | |
1029 } break; | |
1030 | |
1031 case WM_COMMAND: | |
1032 switch(LOWORD(wParam)) | |
1033 { | |
1034 case RAMMENU_FILE_SAVE: | |
1035 QuickSaveWatches(); | |
1036 break; | |
1037 | |
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; | |
1094 | |
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; | |
1104 | |
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; | |
1165 | |
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; | |
1173 | |
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; | |
1181 | |
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 else | |
1191 { | |
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; | |
1212 | |
1213 #if 0 | |
1214 // this message is never received | |
1215 case WM_KEYDOWN: // handle accelerator keys | |
1216 { | |
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 | |
1227 | |
1228 case WM_CLOSE: | |
1229 SendMessage(RamWatchHWnd, WM_DESTROY, 0, 0); | |
1230 break; | |
1231 | |
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; | |
1238 | |
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 } | |
1247 | |
1248 return false; | |
1249 } |