Merge pull request #50 from owomomo/master

Use a better look for the separator in RAM watch.
This commit is contained in:
CaH4e3 2019-04-27 21:15:13 +03:00 committed by GitHub
commit 63ffafa0a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 455 additions and 218 deletions

View File

@ -1056,18 +1056,27 @@ void UpdateCheatWindowRelatedWindow()
// hex editor // hex editor
if (hMemView) if (hMemView)
UpdateColorTable(); //if the memory viewer is open then update any blue freeze locations in it as well UpdateColorTable(); //if the memory viewer is open then update any blue freeze locations in it as well
extern HWND RamSearchHWnd;
// ram search // ram search
extern HWND RamSearchHWnd;
if (RamSearchHWnd) if (RamSearchHWnd)
RedrawWindow(GetDlgItem(RamSearchHWnd, IDC_RAMLIST), NULL, NULL, RDW_INVALIDATE); // if ram search is open then update the ram list. {
// if ram search is open then update the ram list.
SendDlgItemMessage(RamSearchHWnd, IDC_RAMLIST, LVM_REDRAWITEMS,
SendDlgItemMessage(RamSearchHWnd, IDC_RAMLIST, LVM_GETTOPINDEX, 0, 0),
SendDlgItemMessage(RamSearchHWnd, IDC_RAMLIST, LVM_GETCOUNTPERPAGE, 0, 0) + 1);
}
// ram watch // ram watch
extern void UpdateWatchCheats(); extern void UpdateWatchCheats();
UpdateWatchCheats(); UpdateWatchCheats();
extern HWND RamWatchHWnd; extern HWND RamWatchHWnd;
if (RamWatchHWnd) if (RamWatchHWnd)
RedrawWindow(GetDlgItem(RamWatchHWnd, IDC_WATCHLIST), NULL, NULL, RDW_INVALIDATE); // update the data in watch list to the newest. {
// if ram watch is open then update the ram list.
SendDlgItemMessage(RamWatchHWnd, IDC_WATCHLIST, LVM_REDRAWITEMS,
SendDlgItemMessage(RamWatchHWnd, IDC_WATCHLIST, LVM_GETTOPINDEX, 0, 0),
SendDlgItemMessage(RamWatchHWnd, IDC_WATCHLIST, LVM_GETCOUNTPERPAGE, 0, 0) + 1);
}
} }

View File

@ -14,6 +14,18 @@ static int mapInputSortCol = -1;
// whether it's asc or desc sorting, when sortCol is -1, this value has no effect // whether it's asc or desc sorting, when sortCol is -1, this value has no effect
static bool mapInputSortAsc = true; static bool mapInputSortAsc = true;
// an ugly macro function
#define UpdateListViewSort(hwndListView, lpListView, filter) \
if (filter == EMUCMDTYPE_MAX + 3) \
lpListView->iSubItem = 2; \
else if (filter > EMUCMDTYPE_MISC && filter < EMUCMDTYPE_MAX || filter == EMUCMDTYPE_MAX + 2) \
lpListView->iSubItem = 1; \
else \
lpListView->iSubItem = mapInputSortCol; \
if (SendMessage(hwndListView, LVM_SORTITEMS, (WPARAM)lpListView, (LPARAM)MapInputItemSortFunc)) \
UpdateSortColumnIcon(hwndListView, mapInputSortCol, mapInputSortAsc);
void KeyboardUpdateState(void); //mbg merge 7/17/06 yech had to add this void KeyboardUpdateState(void); //mbg merge 7/17/06 yech had to add this
struct INPUTDLGTHREADARGS struct INPUTDLGTHREADARGS
@ -564,22 +576,12 @@ void PopulateMappingDisplay(HWND hwndDlg)
hdr.hwndFrom = hwndListView; hdr.hwndFrom = hwndListView;
hdr.code = LVN_COLUMNCLICK; hdr.code = LVN_COLUMNCLICK;
NMLISTVIEW listView; NMLISTVIEW* lpListView = new NMLISTVIEW;
listView.hdr = hdr; lpListView->hdr = hdr;
// when showing the conflict table, always sorted by "Input" column first, UpdateListViewSort(hwndListView, lpListView, filter);
// So the user can easily find out which are conflicting.
if (filter == EMUCMDTYPE_MAX + 3)
listView.iSubItem = 2;
// only one type is in the list, just sort with "Command" column
// "Unassigned" has no text in "Input", just sort with "Command" column
else if (filter > EMUCMDTYPE_MISC && filter < EMUCMDTYPE_MAX || filter == EMUCMDTYPE_MAX + 2)
listView.iSubItem = 1;
else
listView.iSubItem = mapInputSortCol;
int ret = SendMessage(hwndListView, LVM_SORTITEMS, (WPARAM)&listView, (LPARAM)MapInputItemSortFunc); delete lpListView;
UpdateSortColumnIcon(hwndListView, mapInputSortCol, mapInputSortAsc);
} }
} }
@ -799,20 +801,7 @@ BOOL CALLBACK MapInputDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
mapInputSortAsc = !mapInputSortAsc; mapInputSortAsc = !mapInputSortAsc;
int filter = (int)SendDlgItemMessage(hwndDlg, COMBO_FILTER, CB_GETCURSEL, 0, 0); int filter = (int)SendDlgItemMessage(hwndDlg, COMBO_FILTER, CB_GETCURSEL, 0, 0);
UpdateListViewSort(hwndListView, lpListView, filter);
// when showing the conflict table, always sorted by "Input" column first,
// So the user can easily find out which are conflicting.
if (filter == EMUCMDTYPE_MAX + 3)
lpListView->iSubItem = 2;
// only one type is in the list, just sort with "Command" column
// "Unassigned" has no text in "Input", just sort with "Command" column
else if (filter > EMUCMDTYPE_MISC && filter < EMUCMDTYPE_MAX || filter == EMUCMDTYPE_MAX + 2)
lpListView->iSubItem = 1;
else
lpListView->iSubItem = mapInputSortCol;
int ret = SendMessage(hwndListView, LVM_SORTITEMS, (WPARAM)lpListView, (LPARAM)MapInputItemSortFunc);
UpdateSortColumnIcon(hwndListView, mapInputSortCol, mapInputSortAsc);
} }
return TRUE; return TRUE;
} }

View File

@ -1975,7 +1975,7 @@ invalid_field:
if (selCount == 1) if (selCount == 1)
inserted |= InsertWatch(tempWatch, hDlg); inserted |= InsertWatch(tempWatch, hDlg);
else else
inserted |= InsertWatch(tempWatch, ""); inserted |= InsertWatch(tempWatch);
watchItemIndex = ListView_GetNextItem(ramListControl, watchItemIndex, LVNI_SELECTED); watchItemIndex = ListView_GetNextItem(ramListControl, watchItemIndex, LVNI_SELECTED);
} }

View File

@ -12,6 +12,7 @@ using namespace std;
#include <windows.h> #include <windows.h>
#include <commctrl.h> #include <commctrl.h>
#include <string> #include <string>
#include <map>
/* /*
#include <commctrl.h> #include <commctrl.h>
@ -32,7 +33,7 @@ bool AutoRWLoad = false; //Keeps track of whether Auto-load is checked
bool RWSaveWindowPos = false; //Keeps track of whether Save Window position is checked bool RWSaveWindowPos = false; //Keeps track of whether Save Window position is checked
char currentWatch[1024]; char currentWatch[1024];
int ramw_x, ramw_y; //Used to store ramwatch dialog window positions int ramw_x, ramw_y; //Used to store ramwatch dialog window positions
AddressWatcher rswatches[MAX_WATCH_COUNT]; std::map<int, AddressWatcher> rswatches;
int WatchCount=0; int WatchCount=0;
char applicationPath[2048]; char applicationPath[2048];
@ -44,6 +45,14 @@ struct InitRamWatch
} }
} initRamWatch; } initRamWatch;
HPEN SeparatorCache::sepPen = NULL;
HPEN SeparatorCache::sepPenSel = NULL;
HFONT SeparatorCache::sepFon = NULL;
int SeparatorCache::iHeight = 0;
int SeparatorCache::sepOffY = 0;
std::map<int, SeparatorCache> separatorCache;
HWND RamWatchHWnd; HWND RamWatchHWnd;
#define gamefilename GetRomName() #define gamefilename GetRomName()
#define hWnd hAppWnd #define hWnd hAppWnd
@ -57,7 +66,7 @@ void init_list_box(HWND Box, const char* Strs[], int numColumns, int *columnWidt
bool QuickSaveWatches(); bool QuickSaveWatches();
bool ResetWatches(); bool ResetWatches();
void RefreshWatchListSelectedCountControlStatus(HWND hDlg); void RefreshWatchListSelectedCountControlStatus(HWND hDlg, int newComer = -1);
unsigned int GetCurrentValue(AddressWatcher& watch) unsigned int GetCurrentValue(AddressWatcher& watch)
{ {
@ -93,7 +102,7 @@ bool VerifyWatchNotAlreadyAdded(const AddressWatcher& watch)
} }
bool InsertWatch(const AddressWatcher& Watch, char *Comment) bool InsertWatch(const AddressWatcher& Watch)
{ {
if(!VerifyWatchNotAlreadyAdded(Watch)) if(!VerifyWatchNotAlreadyAdded(Watch))
return false; return false;
@ -104,22 +113,23 @@ bool InsertWatch(const AddressWatcher& Watch, char *Comment)
int i = WatchCount++; int i = WatchCount++;
AddressWatcher& NewWatch = rswatches[i]; AddressWatcher& NewWatch = rswatches[i];
NewWatch = Watch; NewWatch = Watch;
//if (NewWatch.comment) free(NewWatch.comment);
if (NewWatch.comment == NULL)
NewWatch.comment = (char *)malloc(strlen(Comment) + 2);
else
NewWatch.comment = (char *)realloc(NewWatch.comment, strlen(Comment) + 2);
strcpy(NewWatch.comment, Comment);
NewWatch.CurValue = GetCurrentValue(NewWatch); NewWatch.CurValue = GetCurrentValue(NewWatch);
extern int FCEU_CalcCheatAffectedBytes(uint32, uint32); extern int FCEU_CalcCheatAffectedBytes(uint32, uint32);
NewWatch.Cheats = FCEU_CalcCheatAffectedBytes(NewWatch.Address, WatchSizeConv(NewWatch)); NewWatch.Cheats = FCEU_CalcCheatAffectedBytes(NewWatch.Address, WatchSizeConv(NewWatch));
NewWatch.comment = strcpy((char*)malloc(strlen(Watch.comment) + 2), Watch.comment);
if (NewWatch.Type == 'S')
separatorCache[i] = SeparatorCache(RamWatchHWnd, NewWatch.comment);
ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount); ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);
RWfileChanged = true; RWfileChanged = true;
return true; return true;
} }
/* /*
LRESULT CALLBACK PromptWatchNameProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) //Gets the description of a watched address LRESULT CALLBACK PromptWatchNameProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) //Gets the description of a watched address
{ {
@ -204,6 +214,8 @@ void Update_RAM_Watch()
// update cached values and detect changes to displayed listview items // update cached values and detect changes to displayed listview items
for(int i = 0; i < WatchCount; i++) for(int i = 0; i < WatchCount; i++)
{
if (rswatches[i].Type != 'S')
{ {
unsigned int prevCurValue = rswatches[i].CurValue; unsigned int prevCurValue = rswatches[i].CurValue;
unsigned int newCurValue = GetCurrentValue(rswatches[i]); unsigned int newCurValue = GetCurrentValue(rswatches[i]);
@ -214,6 +226,7 @@ void Update_RAM_Watch()
} }
} }
} }
}
// refresh any visible parts of the listview box that changed // refresh any visible parts of the listview box that changed
HWND lv = GetDlgItem(RamWatchHWnd,IDC_WATCHLIST); HWND lv = GetDlgItem(RamWatchHWnd,IDC_WATCHLIST);
@ -417,7 +430,7 @@ void OpenRWRecentFile(int memwRFileNumber)
FILE *WatchFile = fopen(Str_Tmp,"rb"); FILE *WatchFile = fopen(Str_Tmp,"rb");
if (!WatchFile) if (!WatchFile)
{ {
int answer = MessageBox(MESSAGEBOXPARENT,"Error opening file.","ERROR",MB_OKCANCEL | MB_ICONERROR); int answer = MessageBox(MESSAGEBOXPARENT,"Error opening file.","Ram Watch",MB_OKCANCEL | MB_ICONERROR);
if (answer == IDOK) if (answer == IDOK)
{ {
rw_recent_files[rnum][0] = '\0'; //Clear file from list rw_recent_files[rnum][0] = '\0'; //Clear file from list
@ -459,11 +472,13 @@ void OpenRWRecentFile(int memwRFileNumber)
if (CommentEnd) if (CommentEnd)
{ {
*CommentEnd = '\0'; *CommentEnd = '\0';
InsertWatch(Temp, Comment); Temp.comment = Comment;
InsertWatch(Temp);
} else } else
{ {
// the wch file is probably corrupted // the wch file is probably corrupted
InsertWatch(Temp, Comment); Temp.comment = Comment;
InsertWatch(Temp);
break; break;
} }
} else } else
@ -603,7 +618,7 @@ bool Load_Watches(bool clear, const char* filename)
FILE* WatchFile = fopen(filename,"rb"); FILE* WatchFile = fopen(filename,"rb");
if (!WatchFile) if (!WatchFile)
{ {
MessageBox(MESSAGEBOXPARENT,"Error opening file.","ERROR",MB_OK | MB_ICONERROR); MessageBox(MESSAGEBOXPARENT,"Error opening file.","Ram Watch",MB_OK | MB_ICONERROR);
return false; return false;
} }
if(clear) if(clear)
@ -646,11 +661,13 @@ bool Load_Watches(bool clear, const char* filename)
if (CommentEnd) if (CommentEnd)
{ {
*CommentEnd = '\0'; *CommentEnd = '\0';
InsertWatch(Temp, Comment); Temp.comment = Comment;
InsertWatch(Temp);
} else } else
{ {
// the wch file is probably corrupted // the wch file is probably corrupted
InsertWatch(Temp, Comment); Temp.comment = Comment;
InsertWatch(Temp);
break; break;
} }
} else } else
@ -689,6 +706,7 @@ bool ResetWatches()
free(rswatches[WatchCount].comment); free(rswatches[WatchCount].comment);
rswatches[WatchCount].comment = NULL; rswatches[WatchCount].comment = NULL;
} }
rswatches.clear();
WatchCount = 0; WatchCount = 0;
if (RamWatchHWnd) if (RamWatchHWnd)
{ {
@ -697,16 +715,72 @@ bool ResetWatches()
} }
RWfileChanged = false; RWfileChanged = false;
currentWatch[0] = NULL; currentWatch[0] = NULL;
separatorCache.clear();
return true; return true;
} }
void RemoveWatch(int watchIndex) bool RemoveWatch(int watchIndex)
{ {
free(rswatches[watchIndex].comment); AddressWatcher& target = rswatches[watchIndex];
rswatches[watchIndex].comment = NULL; if (watchIndex >= WatchCount)
return false;
if (target.comment)
{
free(target.comment);
target.comment = NULL;
}
if (target.Type == 'S')
separatorCache.erase(watchIndex);
rswatches.erase(watchIndex);
for (int i = watchIndex; i <= WatchCount; i++) for (int i = watchIndex; i <= WatchCount; i++)
{
rswatches[i] = rswatches[i + 1]; rswatches[i] = rswatches[i + 1];
separatorCache[i] = separatorCache[i + 1];
}
WatchCount--; WatchCount--;
return true;
}
bool EditWatch(int watchIndex, AddressWatcher& watcher)
{
if (watchIndex >= WatchCount)
return InsertWatch(watcher);
AddressWatcher& original = rswatches[watchIndex];
if (watcher.Type != 'S' && VerifyWatchNotAlreadyAdded(watcher))
{
if (original.Address != watcher.Address || original.Size != watcher.Size)
{
extern int FCEU_CalcCheatAffectedBytes(uint32, uint32);
original.Cheats = FCEU_CalcCheatAffectedBytes(watcher.Address, WatchSizeConv(watcher));
original.CurValue = GetCurrentValue(watcher);
}
original.Address = watcher.Address;
original.Type = watcher.Type;
original.Size = watcher.Size;
original.WrongEndian = watcher.WrongEndian;
RWfileChanged = true;
}
if (strcmp(original.comment, watcher.comment))
{
if (original.comment)
original.comment = strcpy((char*)realloc(original.comment, strlen(watcher.comment) + 2), watcher.comment);
else
original.comment = strcpy((char*)malloc(strlen(watcher.comment) + 2), watcher.comment);
if (original.Type == 'S')
separatorCache[watchIndex] = SeparatorCache(RamWatchHWnd, watcher.comment);
return true;
}
return false;
} }
void RefreshWatchListSelectedItemControlStatus(HWND hDlg) void RefreshWatchListSelectedItemControlStatus(HWND hDlg)
@ -737,12 +811,12 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
index = (int)lParam; index = (int)lParam;
AddressWatcher* watcher = &rswatches[index]; AddressWatcher& watcher = rswatches[index];
if (watcher->Type != 'S') { if (watcher.Type != 'S') {
char Str_Tmp[1024]; char Str_Tmp[1024];
sprintf(Str_Tmp, "%04X", watcher->Address); sprintf(Str_Tmp, "%04X", watcher.Address);
SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, Str_Tmp); SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, Str_Tmp);
switch (watcher->Size) switch (watcher.Size)
{ {
case 'b': case 'b':
SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0); SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0);
@ -754,7 +828,7 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_SETCHECK, BST_CHECKED, 0); SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_SETCHECK, BST_CHECKED, 0);
break; break;
} }
switch (watcher->Type) switch (watcher.Type)
{ {
case 's': case 's':
SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0); SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0);
@ -769,10 +843,11 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
} else } else
SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, "---------"); SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, "---------");
if (watcher->comment != NULL) if (watcher.comment != NULL)
SetDlgItemText(hDlg, IDC_PROMPT_EDIT, watcher->comment); SetDlgItemText(hDlg, IDC_PROMPT_EDIT, watcher.comment);
if (watcher->Type == 'S' || GetParent(hDlg) == RamSearchHWnd) HWND parent = GetParent(hDlg);
if (watcher.Type == 'S' || parent == RamSearchHWnd)
{ {
EnableWindow(GetDlgItem(hDlg, IDC_SPECIFICADDRESS), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_SPECIFICADDRESS), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_DATATYPE_GROUPBOX), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_DATATYPE_GROUPBOX), FALSE);
@ -787,6 +862,7 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
SetFocus(GetDlgItem(hDlg, IDC_PROMPT_EDIT)); SetFocus(GetDlgItem(hDlg, IDC_PROMPT_EDIT));
} }
} }
return true; return true;
break; break;
@ -802,6 +878,8 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
watcher.comment = strcpy((char*)malloc(strlen(watcher.comment) + 2), watcher.comment); watcher.comment = strcpy((char*)malloc(strlen(watcher.comment) + 2), watcher.comment);
// It's from ram watch window, not a separator // It's from ram watch window, not a separator
// When it's from ram search window, all the information required is already set,
// so this is also unecessary
if (RamWatchHWnd && RamWatchHWnd == GetParent(hDlg) && watcher.Type != 'S') if (RamWatchHWnd && RamWatchHWnd == GetParent(hDlg) && watcher.Type != 'S')
{ {
GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 1024); GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 1024);
@ -852,12 +930,15 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
// comment // comment
GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 80); GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 80);
watcher.comment = Str_Tmp;
// finallly update the watch list // finallly update the watch list
if (index < WatchCount) if (index < WatchCount)
// it's a watch editing operation, and the dialog is from Ram Watch Window, remove then insert; // it's a watch editing operation.
RemoveWatch(index); // Only ram watch window can edit a watch, the ram search window only add watch.
InsertWatch(watcher, Str_Tmp); EditWatch(index, watcher);
else
InsertWatch(watcher);
if (RamWatchHWnd) if (RamWatchHWnd)
ListView_SetItemCount(GetDlgItem(RamWatchHWnd, IDC_WATCHLIST), WatchCount); ListView_SetItemCount(GetDlgItem(RamWatchHWnd, IDC_WATCHLIST), WatchCount);
EndDialog(hDlg, true); EndDialog(hDlg, true);
@ -887,21 +968,23 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
void RamWatchEnableCommand(HWND hDlg, HMENU hMenu, UINT uIDEnableItem, bool enable) void RamWatchEnableCommand(HWND hDlg, HMENU hMenu, UINT uIDEnableItem, bool enable)
{ {
EnableWindow(GetDlgItem(hDlg, uIDEnableItem), (enable?TRUE:FALSE)); EnableWindow(GetDlgItem(hDlg, uIDEnableItem), enable ? TRUE : FALSE);
if (hMenu != NULL) { if (hMenu != NULL) {
if (uIDEnableItem == ID_WATCHES_UPDOWN) { if (uIDEnableItem == ID_WATCHES_UPDOWN) {
EnableMenuItem(hMenu, IDC_C_WATCH_UP, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED)); EnableMenuItem(hMenu, IDC_C_WATCH_UP, MF_BYCOMMAND | enable ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
EnableMenuItem(hMenu, IDC_C_WATCH_DOWN, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED)); EnableMenuItem(hMenu, IDC_C_WATCH_DOWN, MF_BYCOMMAND | enable ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
} }
else else
EnableMenuItem(hMenu, uIDEnableItem, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED)); EnableMenuItem(hMenu, uIDEnableItem, MF_BYCOMMAND | enable ? MF_ENABLED : MF_GRAYED | MF_DISABLED);
} }
} }
void RefreshWatchListSelectedCountControlStatus(HWND hDlg) void RefreshWatchListSelectedCountControlStatus(HWND hDlg, int newComer)
{ {
static int prevSelCount=-1; static int prevSelCount=-1;
int selCount = ListView_GetSelectedCount(GetDlgItem(hDlg,IDC_WATCHLIST)); int selCount = ListView_GetSelectedCount(GetDlgItem(hDlg,IDC_WATCHLIST));
// int sel = SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETSELECTIONMARK, 0, 0);
if(selCount != prevSelCount) if(selCount != prevSelCount)
{ {
if(selCount < 2 || prevSelCount < 2) if(selCount < 2 || prevSelCount < 2)
@ -909,8 +992,8 @@ void RefreshWatchListSelectedCountControlStatus(HWND hDlg)
RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_EDIT, selCount == 1); RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_EDIT, selCount == 1);
RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_REMOVE, selCount >= 1); RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_REMOVE, selCount >= 1);
RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_DUPLICATE, selCount == 1); RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_WATCH_DUPLICATE, selCount == 1);
RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_ADDCHEAT, selCount == 1);
RamWatchEnableCommand(hDlg, ramwatchmenu, ID_WATCHES_UPDOWN, selCount == 1); RamWatchEnableCommand(hDlg, ramwatchmenu, ID_WATCHES_UPDOWN, selCount == 1);
RamWatchEnableCommand(hDlg, ramwatchmenu, IDC_C_ADDCHEAT, selCount == 1 && newComer != -1 && rswatches[newComer].Type != 'S');
} }
prevSelCount = selCount; prevSelCount = selCount;
} }
@ -918,10 +1001,8 @@ void RefreshWatchListSelectedCountControlStatus(HWND hDlg)
LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
RECT r; static int watchIndex = 0; // current watch index
RECT r2; static bool listFocus;
int dx1, dy1, dx2, dy2;
static int watchIndex=0;
switch(uMsg) switch(uMsg)
{ {
@ -941,6 +1022,9 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
} break; } break;
case WM_INITDIALOG: { case WM_INITDIALOG: {
RECT r, r2;
int dx1, dy1, dx2, dy2;
GetWindowRect(hWnd, &r); //Ramwatch window GetWindowRect(hWnd, &r); //Ramwatch window
dx1 = (r.right - r.left) / 2; dx1 = (r.right - r.left) / 2;
dy1 = (r.bottom - r.top) / 2; dy1 = (r.bottom - r.top) / 2;
@ -984,8 +1068,11 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
UpdateRW_RMenu(rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE); UpdateRW_RMenu(rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE);
const char* names[3] = {"Address","Value","Notes"}; const char* names[3] = {"Address","Value","Notes"};
int widths[3] = {62,64,64+51+53}; int widths[3] = {78,64,160};
init_list_box(GetDlgItem(hDlg,IDC_WATCHLIST),names,3,widths); init_list_box(GetDlgItem(hDlg,IDC_WATCHLIST),names,3,widths);
SeparatorCache::Init(GetDlgItem(hDlg, IDC_WATCHLIST));
if (!ResultCount) if (!ResultCount)
reset_address_info(); reset_address_info();
else else
@ -1004,6 +1091,7 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
DragAcceptFiles(hDlg, TRUE); DragAcceptFiles(hDlg, TRUE);
RefreshWatchListSelectedCountControlStatus(hDlg); RefreshWatchListSelectedCountControlStatus(hDlg);
return false; return false;
} break; } break;
@ -1016,7 +1104,6 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
case WM_ENTERSIZEMOVE: case WM_ENTERSIZEMOVE:
//Clear_Sound_Buffer(); //Clear_Sound_Buffer();
break; break;
case WM_NOTIFY: case WM_NOTIFY:
{ {
switch(wParam) switch(wParam)
@ -1032,7 +1119,7 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
} }
} break; } break;
default: case IDC_WATCHLIST:
{ {
LPNMHDR lP = (LPNMHDR) lParam; LPNMHDR lP = (LPNMHDR) lParam;
switch (lP->code) switch (lP->code)
@ -1040,31 +1127,32 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
case LVN_ITEMCHANGED: // selection changed event case LVN_ITEMCHANGED: // selection changed event
{ {
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lP; NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)lP;
if(pNMListView->uNewState & LVIS_FOCUSED || if(pNMListView->uNewState & LVIS_FOCUSED ||
(pNMListView->uNewState ^ pNMListView->uOldState) & LVIS_SELECTED) (pNMListView->uNewState ^ pNMListView->uOldState) & LVIS_SELECTED)
{ {
// disable buttons that we don't have the right number of selected items for // disable buttons that we don't have the right number of selected items for
RefreshWatchListSelectedCountControlStatus(hDlg); RefreshWatchListSelectedCountControlStatus(hDlg, pNMListView->iItem);
} }
} break; } break;
case LVN_GETDISPINFO: case LVN_GETDISPINFO:
{ {
LV_DISPINFO *Item = (LV_DISPINFO *)lParam; LV_DISPINFO *Item = (LV_DISPINFO *)lParam;
Item->item.mask = LVIF_TEXT;
Item->item.state = 0;
Item->item.iImage = 0;
const unsigned int iNum = Item->item.iItem; const unsigned int iNum = Item->item.iItem;
if (rswatches[iNum].Type != 'S')
{
Item->item.mask = LVIF_TEXT;
static char num[11]; static char num[11];
switch (Item->item.iSubItem) switch (Item->item.iSubItem)
{ {
case 0: case 0: {
{
int size = WatchSizeConv(rswatches[iNum]); int size = WatchSizeConv(rswatches[iNum]);
int addr = rswatches[iNum].Address; int addr = rswatches[iNum].Address;
sprintf(num, rswatches[iNum].Type == 'S' ? "------" : size > 1 ? "%04X-%04X" : "%04X", addr, addr + size - 1); sprintf(num, size > 1 ? "%04X-%04X" : "%04X", addr, addr + size - 1);
Item->item.pszText = num; Item->item.pszText = num;
return true; break;
} }
case 1: { case 1: {
int i = rswatches[iNum].CurValue; int i = rswatches[iNum].CurValue;
@ -1077,19 +1165,20 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
default: sprintf(num, formatString, t == 's' ? (char)(i & 0xff) : (unsigned char)(i & 0xff)); break; default: sprintf(num, formatString, t == 's' ? (char)(i & 0xff) : (unsigned char)(i & 0xff)); break;
case 'w': sprintf(num, formatString, t == 's' ? (short)(i & 0xffff) : (unsigned short)(i & 0xffff)); break; case 'w': sprintf(num, formatString, t == 's' ? (short)(i & 0xffff) : (unsigned short)(i & 0xffff)); break;
case 'd': sprintf(num, formatString, t == 's' ? (long)(i & 0xffffffff) : (unsigned long)(i & 0xffffffff)); break; case 'd': sprintf(num, formatString, t == 's' ? (long)(i & 0xffffffff) : (unsigned long)(i & 0xffffffff)); break;
case 'S': sprintf(num, "---------"); break;
} }
Item->item.pszText = num; Item->item.pszText = num;
} return true; }
break;
case 2: case 2:
Item->item.pszText = rswatches[iNum].comment ? rswatches[iNum].comment : (char*)""; Item->item.pszText = rswatches[iNum].comment ? rswatches[iNum].comment : (char*)"";
return true; break;
default: default:
return false; break;
} }
} }
return true;
}
case LVN_ODFINDITEM: case LVN_ODFINDITEM:
{ {
// disable search by keyboard typing, // disable search by keyboard typing,
@ -1098,17 +1187,29 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
SetWindowLong(hDlg, DWL_MSGRESULT, ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST))); SetWindowLong(hDlg, DWL_MSGRESULT, ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST)));
return 1; return 1;
} }
case NM_SETFOCUS:
listFocus = true;
InvalidateRect(GetDlgItem(hDlg, IDC_WATCHLIST), 0, 0);
break;
case NM_KILLFOCUS:
listFocus = false;
InvalidateRect(GetDlgItem(hDlg, IDC_WATCHLIST), 0, 0);
break;
case NM_CUSTOMDRAW: case NM_CUSTOMDRAW:
{ {
LPNMCUSTOMDRAW nmcd = (LPNMCUSTOMDRAW)lParam; NMCUSTOMDRAW* nmcd = (NMCUSTOMDRAW*)lParam;
switch (nmcd->dwDrawStage) switch (nmcd->dwDrawStage)
{ {
case CDDS_PREPAINT:
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);
break;
case CDDS_ITEMPREPAINT: case CDDS_ITEMPREPAINT:
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
if (rswatches[nmcd->dwItemSpec].Type == 'S') if (rswatches[nmcd->dwItemSpec].Type == 'S')
lplvcd->clrTextBk = RGB(247, 187, 67); // A separator looks very different from normal watches, it should be drawn in another space while I want to use the highlight bar and the focus frame from the system.
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYPOSTPAINT);
else else
{
NMLVCUSTOMDRAW* lplvcd = (NMLVCUSTOMDRAW*)lParam;
switch (rswatches[nmcd->dwItemSpec].Cheats) switch (rswatches[nmcd->dwItemSpec].Cheats)
{ {
default: default:
@ -1128,17 +1229,49 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NEWFONT); SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NEWFONT);
} }
break; break;
case CDDS_PREPAINT: case CDDS_ITEMPOSTPAINT:
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW); // Here is the separator actually drawn
if (rswatches[nmcd->dwItemSpec].Type == 'S')
{
char* comment = rswatches[nmcd->dwItemSpec].comment;
RECT rect;
rect.left = LVIR_BOUNDS;
SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETITEMRECT, nmcd->dwItemSpec, (LPARAM)&rect);
HDC hdc = nmcd->hdc;
// This value is required, when you click outside any items in the list there's nothing selected, but the frame is still on the separator, it would draw with the wrong color. I don't know if there's a better way to check this state, since nmcd->uItemState doesn't seem to have a value for it.
bool state = SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETITEMSTATE, nmcd->dwItemSpec, LVIS_SELECTED) && listFocus;
SeparatorCache& sepCache = separatorCache[nmcd->dwItemSpec];
// draw the separator
// draw it with a different color when hilighted for eyes easy
SelectObject(hdc, state ? SeparatorCache::sepPenSel : SeparatorCache::sepPen);
MoveToEx(hdc, rect.left + sepCache.sepOffX, rect.top + SeparatorCache::sepOffY, NULL);
LineTo(hdc, rect.right, rect.top + SeparatorCache::sepOffY);
// draw the comment as the separator title
if (comment && comment[0])
{
rect.top += sepCache.labelOffY;
rect.left += 6;
// draw it with a different color when hilighted for eyes easy
SetTextColor(hdc, state ? RGB(229, 224, 236) : RGB(43, 145, 175));
SelectObject(hdc, SeparatorCache::sepFon);
DrawText(hdc, comment, strlen(comment), &rect, DT_LEFT);
}
}
break;
} }
return TRUE; return TRUE;
} }
} }
} }
} }
} break; }
break;
case WM_COMMAND: case WM_COMMAND:
switch(LOWORD(wParam)) switch(LOWORD(wParam))
{ {
@ -1181,49 +1314,62 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
} }
return true; return true;
case IDC_C_WATCH: case IDC_C_WATCH:
rswatches[WatchCount].Address = 0; {
rswatches[WatchCount].WrongEndian = 0; AddressWatcher& target = rswatches[WatchCount];
rswatches[WatchCount].Size = 'b'; target.Address = 0;
rswatches[WatchCount].Type = 's'; target.WrongEndian = 0;
target.Size = 'b';
target.Type = 's';
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC)EditWatchProc, (LPARAM)WatchCount); DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC)EditWatchProc, (LPARAM)WatchCount);
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST)); SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
return true; return true;
}
case IDC_C_WATCH_DUPLICATE: case IDC_C_WATCH_DUPLICATE:
{
watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST)); watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST));
if (watchIndex != -1) if (watchIndex != -1)
{ {
rswatches[WatchCount].Address = rswatches[watchIndex].Address; char str_tmp[1024];
rswatches[WatchCount].WrongEndian = rswatches[watchIndex].WrongEndian; AddressWatcher* target = &rswatches[WatchCount];
rswatches[WatchCount].Size = rswatches[watchIndex].Size; AddressWatcher* source = &rswatches[watchIndex];
rswatches[WatchCount].Type = rswatches[watchIndex].Type; memcpy(target, source, sizeof(AddressWatcher));
rswatches[WatchCount].comment = strcpy((char*)malloc(strlen(rswatches[watchIndex].comment) + 2), rswatches[watchIndex].comment); target->comment = strcpy(str_tmp, source->comment);
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC)EditWatchProc, WatchCount); DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC)EditWatchProc, WatchCount);
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST)); SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
} }
return true; return true;
}
case IDC_C_WATCH_SEPARATE: case IDC_C_WATCH_SEPARATE:
rswatches[WatchCount].Address = 0; {
rswatches[WatchCount].WrongEndian = false; AddressWatcher* target = &rswatches[WatchCount];
rswatches[WatchCount].Size = 'S'; target->Address = 0;
rswatches[WatchCount].Type = 'S'; target->WrongEndian = false;
target->Size = 'S';
target->Type = 'S';
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC)EditWatchProc, (LPARAM)WatchCount); DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, (DLGPROC)EditWatchProc, (LPARAM)WatchCount);
// InsertWatch(separator, "----------------------------"); // InsertWatch(separator, "----------------------------");
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST)); SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
return true; return true;
}
case IDC_C_WATCH_UP: case IDC_C_WATCH_UP:
{ {
watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST)); watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));
if (watchIndex == 0 || watchIndex == -1) if (watchIndex == 0 || watchIndex == -1)
return true; return true;
void *tmp = malloc(sizeof(AddressWatcher)); void *tmp = malloc(sizeof(AddressWatcher));
memcpy(tmp,&(rswatches[watchIndex]),sizeof(AddressWatcher)); memcpy(tmp, &rswatches[watchIndex], sizeof(AddressWatcher));
memcpy(&(rswatches[watchIndex]),&(rswatches[watchIndex - 1]),sizeof(AddressWatcher)); memcpy(&rswatches[watchIndex], &rswatches[watchIndex - 1], sizeof(AddressWatcher));
memcpy(&(rswatches[watchIndex - 1]),tmp,sizeof(AddressWatcher)); memcpy(&rswatches[watchIndex - 1], tmp, sizeof(AddressWatcher));
free(tmp); free(tmp);
tmp = malloc(sizeof(SeparatorCache));
memcpy(tmp, &separatorCache[watchIndex], sizeof(SeparatorCache));
memcpy(&separatorCache[watchIndex], &separatorCache[watchIndex - 1], sizeof(SeparatorCache));
memcpy(&separatorCache[watchIndex - 1], tmp, sizeof(SeparatorCache));
free(tmp);
ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex, 0, LVIS_FOCUSED | LVIS_SELECTED); ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex, 0, LVIS_FOCUSED | LVIS_SELECTED);
ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex - 1); ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex - 1);
ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex - 1, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex - 1, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
@ -1236,11 +1382,19 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST)); watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST));
if (watchIndex >= WatchCount - 1 || watchIndex == -1) if (watchIndex >= WatchCount - 1 || watchIndex == -1)
return true; return true;
void *tmp = malloc(sizeof(AddressWatcher));
memcpy(tmp,&(rswatches[watchIndex]),sizeof(AddressWatcher)); void *tmp = calloc(1, sizeof(AddressWatcher));
memcpy(&(rswatches[watchIndex]),&(rswatches[watchIndex + 1]),sizeof(AddressWatcher)); memcpy(tmp, &rswatches[watchIndex], sizeof(AddressWatcher));
memcpy(&(rswatches[watchIndex + 1]),tmp,sizeof(AddressWatcher)); memcpy(&rswatches[watchIndex], &rswatches[watchIndex + 1], sizeof(AddressWatcher));
memcpy(&rswatches[watchIndex + 1], tmp, sizeof(AddressWatcher));
free(tmp); free(tmp);
tmp = calloc(1, sizeof(SeparatorCache));
memcpy(tmp, &separatorCache[watchIndex], sizeof(SeparatorCache));
memcpy(&separatorCache[watchIndex], &separatorCache[watchIndex + 1], sizeof(SeparatorCache));
memcpy(&separatorCache[watchIndex + 1], tmp, sizeof(SeparatorCache));
free(tmp);
ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex, 0, LVIS_FOCUSED | LVIS_SELECTED); ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex, 0, LVIS_FOCUSED | LVIS_SELECTED);
ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST),watchIndex + 1); ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST),watchIndex + 1);
ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex + 1, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); ListView_SetItemState(GetDlgItem(hDlg, IDC_WATCHLIST), watchIndex + 1, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
@ -1250,8 +1404,7 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
} }
case ID_WATCHES_UPDOWN: case ID_WATCHES_UPDOWN:
{ {
int delta = ((LPNMUPDOWN)lParam)->iDelta; SendMessage(hDlg, WM_COMMAND, ((LPNMUPDOWN)lParam)->iDelta < 0 ? IDC_C_WATCH_UP : IDC_C_WATCH_DOWN,0);
SendMessage(hDlg, WM_COMMAND, delta<0 ? IDC_C_WATCH_UP : IDC_C_WATCH_DOWN,0);
break; break;
} }
case RAMMENU_FILE_AUTOLOAD: case RAMMENU_FILE_AUTOLOAD:
@ -1272,6 +1425,7 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
{ {
watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST)); watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));
if(watchIndex >= 0) if(watchIndex >= 0)
if (rswatches[watchIndex].Type != 'S')
{ {
unsigned int address = rswatches[watchIndex].Address; unsigned int address = rswatches[watchIndex].Address;
@ -1294,24 +1448,25 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
// Don't open cheat dialog // Don't open cheat dialog
switch (sizeType) { switch (sizeType) {
case 0: { case 0:
FCEUI_AddCheat("", address, rswatches[watchIndex].CurValue, -1, 1); FCEUI_AddCheat("", address, rswatches[watchIndex].CurValue, -1, 1);
break; } break;
case 1: { case 1:
FCEUI_AddCheat("", address, rswatches[watchIndex].CurValue & 0xFF, -1, 1); FCEUI_AddCheat("", address, rswatches[watchIndex].CurValue & 0xFF, -1, 1);
FCEUI_AddCheat("", address + 1, (rswatches[watchIndex].CurValue & 0xFF00) / 0x100, -1, 1); FCEUI_AddCheat("", address + 1, (rswatches[watchIndex].CurValue & 0xFF00) / 0x100, -1, 1);
break; } break;
case 2: { case 2:
FCEUI_AddCheat("", address, rswatches[watchIndex].CurValue & 0xFF, -1, 1); FCEUI_AddCheat("", address, rswatches[watchIndex].CurValue & 0xFF, -1, 1);
FCEUI_AddCheat("", address + 1, (rswatches[watchIndex].CurValue & 0xFF00) / 0x100, -1, 1); FCEUI_AddCheat("", address + 1, (rswatches[watchIndex].CurValue & 0xFF00) / 0x100, -1, 1);
FCEUI_AddCheat("", address + 2, (rswatches[watchIndex].CurValue & 0xFF0000) / 0x10000, -1, 1); FCEUI_AddCheat("", address + 2, (rswatches[watchIndex].CurValue & 0xFF0000) / 0x10000, -1, 1);
FCEUI_AddCheat("", address + 3, (rswatches[watchIndex].CurValue & 0xFF000000) / 0x1000000, -1, 1); FCEUI_AddCheat("", address + 3, (rswatches[watchIndex].CurValue & 0xFF000000) / 0x1000000, -1, 1);
break; } break;
} }
UpdateCheatsAdded(); UpdateCheatsAdded();
UpdateCheatWindowRelatedWindow(); UpdateCheatWindowRelatedWindow();
} }
else
MessageBox(hDlg, "Sorry, you can't add cheat to a separator.", "Ram Watch", MB_ICONERROR | MB_OK);
} }
break; break;
case IDOK: case IDOK:
@ -1349,6 +1504,10 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
RamWatchHWnd = NULL; RamWatchHWnd = NULL;
DragAcceptFiles(hDlg, FALSE); DragAcceptFiles(hDlg, FALSE);
WriteRecentRWFiles(); // write recent menu to ini WriteRecentRWFiles(); // write recent menu to ini
// release the hdc related objects
SeparatorCache::DeInit();
break; break;
case WM_DROPFILES: case WM_DROPFILES:
@ -1370,3 +1529,51 @@ void UpdateWatchCheats() {
for (int i = 0; i < WatchCount; ++i) for (int i = 0; i < WatchCount; ++i)
rswatches[i].Cheats = FCEU_CalcCheatAffectedBytes(rswatches[i].Address, WatchSizeConv(rswatches[i])); rswatches[i].Cheats = FCEU_CalcCheatAffectedBytes(rswatches[i].Address, WatchSizeConv(rswatches[i]));
} }
void SeparatorCache::Init(HWND hBox)
{
RECT ir;
ir.left = LVIR_BOUNDS;
int count = SendMessage(hBox, LVM_GETITEMCOUNT, 0, 0);
SendMessage(hBox, LVM_SETITEMCOUNT, 1, 0);
SendMessage(hBox, LVM_GETITEMRECT, 0, (LPARAM)&ir);
SendMessage(hBox, LVM_SETITEMCOUNT, count, 0);
sepOffY = (iHeight = ir.bottom - ir.top) / 2;
sepPen = CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
sepPenSel = CreatePen(PS_SOLID, 1, RGB(224, 224, 224));
LOGFONT logFont;
GetObject((HANDLE)SendMessage(hBox, WM_GETFONT, NULL, NULL), sizeof(logFont), &logFont);
sepFon = (HFONT)CreateFontIndirect((logFont.lfWeight = FW_SEMIBOLD, &logFont));
}
void SeparatorCache::DeInit()
{
DeleteObject(sepPen);
DeleteObject(sepPenSel);
DeleteObject(sepFon);
}
SeparatorCache::SeparatorCache(HWND hwnd, char* text) {
if (text && text[0])
{
SIZE size;
HDC hdc = GetDC(hwnd);
SelectFont(hdc, sepFon);
GetTextExtentPoint(hdc, text, strlen(text), &size);
ReleaseDC(hwnd, hdc);
sepOffX = size.cx + 8;
labelOffY = (iHeight - size.cy) / 2;
}
else {
// Is there a way to find real ident of the highlight mark in the first cloumn?
sepOffX = 4;
labelOffY = 0;
}
}

View File

@ -22,14 +22,35 @@ struct AddressWatcher
{ {
unsigned int Address; // hardware address unsigned int Address; // hardware address
unsigned int CurValue; unsigned int CurValue;
char* comment; // NULL means no comment, non-NULL means allocated comment char* comment = NULL; // NULL means no comment, non-NULL means allocated comment
bool WrongEndian; bool WrongEndian;
char Size; //'d' = 4 bytes, 'w' = 2 bytes, 'b' = 1 byte, and 'S' means it's a separator. char Size; //'d' = 4 bytes, 'w' = 2 bytes, 'b' = 1 byte, and 'S' means it's a separator.
char Type;//'s' = signed integer, 'u' = unsigned, 'h' = hex, 'S' = separator char Type;//'s' = signed integer, 'u' = unsigned, 'h' = hex, 'S' = separator
short Cheats; // how many bytes are affected by cheat short Cheats; // how many bytes are affected by cheat
}; };
// Cache all the things required for drawing separator
// to prevent creating and destroying them repeatedly when painting
struct SeparatorCache
{
// these things are static, every items are currently all the same.
static HPEN sepPen; // color for separator in normal state
static HPEN sepPenSel; // color for separator in selected state
static HFONT sepFon; // caption font
static int iHeight; // item height
static int sepOffY; // y coordinate offset of the separator
static void Init(HWND hBox); // prepare all the static stuff
static void DeInit(); // destroy all the static stuff
// there are only 2 thing that identical
int labelOffY; // y coordinate offset of the label
int sepOffX; // x coordinate offset of the separator
SeparatorCache() {};
SeparatorCache(HWND hWnd, char* text);
};
#define MAX_WATCH_COUNT 256 #define MAX_WATCH_COUNT 256
extern AddressWatcher rswatches[MAX_WATCH_COUNT];
extern int WatchCount; // number of valid items in rswatches extern int WatchCount; // number of valid items in rswatches
extern char Watch_Dir[1024]; extern char Watch_Dir[1024];
@ -37,8 +58,11 @@ extern char Watch_Dir[1024];
extern HWND RamWatchHWnd; extern HWND RamWatchHWnd;
extern HACCEL RamWatchAccels; extern HACCEL RamWatchAccels;
bool InsertWatch(const AddressWatcher& Watch, char *Comment); bool InsertWatch(const AddressWatcher& Watch);
bool InsertWatch(const AddressWatcher& Watch, HWND parent=NULL); // asks user for comment bool InsertWatch(const AddressWatcher& Watch, HWND parent); // asks user for comment)
bool EditWatch(int watchIndex, AddressWatcher& watcher);
bool RemoveWatch(int watchIndex);
void Update_RAM_Watch(); void Update_RAM_Watch();
bool Load_Watches(bool clear, const char* filename); bool Load_Watches(bool clear, const char* filename);
void RWAddRecentFile(const char *filename); void RWAddRecentFile(const char *filename);
@ -46,6 +70,7 @@ void UpdateWatchCheats();
LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern HWND RamWatchHWnd; extern HWND RamWatchHWnd;
#define WatchSizeConv(watch) (watch.Type == 'S' ? 0 : watch.Size == 'd' ? 4 : watch.Size == 'w' ? 2 : watch.Size == 'b' ? 1 : 0) #define WatchSizeConv(watch) (watch.Type == 'S' ? 0 : watch.Size == 'd' ? 4 : watch.Size == 'w' ? 2 : watch.Size == 'b' ? 1 : 0)

View File

@ -8,7 +8,6 @@
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#include "afxres.h" #include "afxres.h"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
@ -2147,7 +2146,7 @@ CAPTION " RAM Watch"
MENU RAMWATCH_MENU MENU RAMWATCH_MENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
CONTROL "",IDC_WATCHLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP | LVS_NOSORTHEADER,9,9,210,279,WS_EX_CLIENTEDGE CONTROL "",IDC_WATCHLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,9,9,210,279,WS_EX_CLIENTEDGE
PUSHBUTTON "Edit",IDC_C_WATCH_EDIT,226,66,34,14 PUSHBUTTON "Edit",IDC_C_WATCH_EDIT,226,66,34,14
PUSHBUTTON "Remove",IDC_C_WATCH_REMOVE,226,83,34,14 PUSHBUTTON "Remove",IDC_C_WATCH_REMOVE,226,83,34,14
PUSHBUTTON "New",IDC_C_WATCH,226,100,34,14 PUSHBUTTON "New",IDC_C_WATCH,226,100,34,14
@ -2350,6 +2349,10 @@ BEGIN
BEGIN BEGIN
END END
"GGCONV", DIALOG
BEGIN
END
"MONITOR", DIALOG "MONITOR", DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
@ -2491,6 +2494,11 @@ BEGIN
0 0
END END
GGCONV AFX_DIALOG_LAYOUT
BEGIN
0
END
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
@ -2707,7 +2715,6 @@ END
// Generated from the TEXTINCLUDE 3 resource. // Generated from the TEXTINCLUDE 3 resource.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED #endif // not APSTUDIO_INVOKED