Cache some item drawing related data and objects to prevent calculate them repeatedly when drawing.
Changed the watch list to a map for future developments.
This commit is contained in:
parent
74853a83fb
commit
206cb06f47
|
@ -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
|
||||||
|
@ -114,8 +123,12 @@ bool InsertWatch(const AddressWatcher& Watch, char *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));
|
||||||
|
|
||||||
|
if (NewWatch.Type == 'S')
|
||||||
|
separatorCache[i] = SeparatorCache(RamWatchHWnd, Comment);
|
||||||
|
|
||||||
ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);
|
ListView_SetItemCount(GetDlgItem(RamWatchHWnd,IDC_WATCHLIST),WatchCount);
|
||||||
RWfileChanged=true;
|
RWfileChanged = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +203,7 @@ bool InsertWatch(const AddressWatcher& Watch, HWND parent)
|
||||||
|
|
||||||
rswatches[WatchCount] = Watch;
|
rswatches[WatchCount] = Watch;
|
||||||
rswatches[WatchCount].CurValue = GetCurrentValue(rswatches[WatchCount]);
|
rswatches[WatchCount].CurValue = GetCurrentValue(rswatches[WatchCount]);
|
||||||
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), parent, (DLGPROC) EditWatchProc, (LPARAM)WatchCount);
|
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), parent, (DLGPROC)EditWatchProc, (LPARAM)WatchCount);
|
||||||
|
|
||||||
return WatchCount > prevWatchCount;
|
return WatchCount > prevWatchCount;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +433,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
|
||||||
|
@ -606,7 +619,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)
|
||||||
|
@ -693,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)
|
||||||
{
|
{
|
||||||
|
@ -701,6 +715,8 @@ bool ResetWatches()
|
||||||
}
|
}
|
||||||
RWfileChanged = false;
|
RWfileChanged = false;
|
||||||
currentWatch[0] = NULL;
|
currentWatch[0] = NULL;
|
||||||
|
|
||||||
|
separatorCache.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,11 +724,22 @@ void RemoveWatch(int watchIndex)
|
||||||
{
|
{
|
||||||
free(rswatches[watchIndex].comment);
|
free(rswatches[watchIndex].comment);
|
||||||
rswatches[watchIndex].comment = NULL;
|
rswatches[watchIndex].comment = NULL;
|
||||||
|
if (rswatches[watchIndex].Type == 'S')
|
||||||
|
RemoveSeparatorBuf(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--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveSeparatorBuf(int watchIndex)
|
||||||
|
{
|
||||||
|
separatorCache.erase(watchIndex);
|
||||||
|
}
|
||||||
|
|
||||||
void RefreshWatchListSelectedItemControlStatus(HWND hDlg)
|
void RefreshWatchListSelectedItemControlStatus(HWND hDlg)
|
||||||
{
|
{
|
||||||
static int prevSelIndex=-1;
|
static int prevSelIndex=-1;
|
||||||
|
@ -776,7 +803,8 @@ LRESULT CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||||
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);
|
||||||
|
@ -806,6 +834,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);
|
||||||
|
@ -923,8 +953,7 @@ 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)
|
||||||
{
|
{
|
||||||
static int watchIndex = 0; // current watch index
|
static int watchIndex = 0; // current watch index
|
||||||
static HPEN sepPen, sepPenSel; // separator line colors
|
static bool listFocus;
|
||||||
static HFONT sepFon; // separator fonts
|
|
||||||
|
|
||||||
switch(uMsg)
|
switch(uMsg)
|
||||||
{
|
{
|
||||||
|
@ -990,8 +1019,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] = {68,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
|
||||||
|
@ -1011,13 +1043,6 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
||||||
|
|
||||||
RefreshWatchListSelectedCountControlStatus(hDlg);
|
RefreshWatchListSelectedCountControlStatus(hDlg);
|
||||||
|
|
||||||
sepPen = CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
|
|
||||||
sepPenSel = CreatePen(PS_SOLID, 1, RGB(224, 224, 224));
|
|
||||||
LOGFONT logFont;
|
|
||||||
GetObject((HANDLE)SendDlgItemMessage(hDlg, IDC_WATCHLIST, WM_GETFONT, NULL, NULL), sizeof(logFont), &logFont);
|
|
||||||
logFont.lfWeight = FW_SEMIBOLD;
|
|
||||||
sepFon = (HFONT)CreateFontIndirect(&logFont);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1030,7 +1055,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)
|
||||||
|
@ -1112,51 +1136,15 @@ 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; break;
|
||||||
|
case NM_KILLFOCUS: listFocus = false; break;
|
||||||
case NM_CUSTOMDRAW:
|
case NM_CUSTOMDRAW:
|
||||||
{
|
{
|
||||||
NMCUSTOMDRAW* nmcd = (NMCUSTOMDRAW*)lParam;
|
NMCUSTOMDRAW* nmcd = (NMCUSTOMDRAW*)lParam;
|
||||||
switch (nmcd->dwDrawStage)
|
switch (nmcd->dwDrawStage)
|
||||||
{
|
{
|
||||||
case CDDS_ITEMPOSTPAINT:
|
case CDDS_PREPAINT:
|
||||||
// Here is the separator actually drawn
|
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);
|
||||||
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 tohave a value for it.
|
|
||||||
// int selCount = SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETSELECTEDCOUNT, 0, 0);
|
|
||||||
int state = SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETITEMSTATE, nmcd->dwItemSpec, LVIS_SELECTED);
|
|
||||||
|
|
||||||
// draw the comment as the separator title
|
|
||||||
if (comment != NULL && strcmp(comment, ""))
|
|
||||||
{
|
|
||||||
SIZE size;
|
|
||||||
SelectObject(hdc, sepFon);
|
|
||||||
GetTextExtentPoint(hdc, comment, strlen(comment), &size);
|
|
||||||
int adjust = (rect.bottom - rect.top - size.cy) / 2;
|
|
||||||
rect.bottom -= adjust;
|
|
||||||
rect.top += adjust;
|
|
||||||
int right = rect.right;
|
|
||||||
rect.right = (rect.left += 6) + size.cx;
|
|
||||||
// draw it with a different color when hilighted for eyes easy
|
|
||||||
SetTextColor(hdc, state ? RGB(229, 224, 236) : RGB(43, 145, 175));
|
|
||||||
DrawText(hdc, comment, strlen(comment), &rect, DT_VCENTER);
|
|
||||||
rect.left = rect.right;
|
|
||||||
rect.right = right;
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw the separator
|
|
||||||
// draw it with a different color when hilighted for eyes easy
|
|
||||||
SelectObject(hdc, state ? sepPenSel : sepPen);
|
|
||||||
int posy = (rect.bottom - rect.top) / 2 + rect.top;
|
|
||||||
// Is there a way to find real ident of the highlight mark in the first cloumn?
|
|
||||||
MoveToEx(hdc, rect.left += 4, posy, NULL);
|
|
||||||
LineTo(hdc, rect.right, posy);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CDDS_ITEMPREPAINT:
|
case CDDS_ITEMPREPAINT:
|
||||||
if (rswatches[nmcd->dwItemSpec].Type == 'S')
|
if (rswatches[nmcd->dwItemSpec].Type == 'S')
|
||||||
|
@ -1184,8 +1172,41 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -1275,10 +1296,17 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
||||||
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);
|
||||||
|
@ -1291,11 +1319,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);
|
||||||
|
@ -1327,6 +1363,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;
|
||||||
|
|
||||||
|
@ -1349,24 +1386,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.", "Error", MB_ICONERROR | MB_OK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDOK:
|
case IDOK:
|
||||||
|
@ -1405,9 +1443,8 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
||||||
DragAcceptFiles(hDlg, FALSE);
|
DragAcceptFiles(hDlg, FALSE);
|
||||||
WriteRecentRWFiles(); // write recent menu to ini
|
WriteRecentRWFiles(); // write recent menu to ini
|
||||||
|
|
||||||
DeleteObject(sepFon);
|
// release the hdc related objects
|
||||||
DeleteObject(sepPen);
|
SeparatorCache::DeInit();
|
||||||
DeleteObject(sepPenSel); // delete drawing objects;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1429,4 +1466,51 @@ void UpdateWatchCheats() {
|
||||||
extern int FCEU_CalcCheatAffectedBytes(uint32, uint32);
|
extern int FCEU_CalcCheatAffectedBytes(uint32, uint32);
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
@ -39,6 +60,10 @@ extern HACCEL RamWatchAccels;
|
||||||
|
|
||||||
bool InsertWatch(const AddressWatcher& Watch, char *Comment);
|
bool InsertWatch(const AddressWatcher& Watch, char *Comment);
|
||||||
bool InsertWatch(const AddressWatcher& Watch, HWND parent=NULL); // asks user for comment
|
bool InsertWatch(const AddressWatcher& Watch, HWND parent=NULL); // asks user for comment
|
||||||
|
void EditWatch(int watchIndex, AddressWatcher& watcher);
|
||||||
|
void RemoveWatch(int watchIndex);
|
||||||
|
void RemoveSeparatorBuf(int index);
|
||||||
|
|
||||||
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 +71,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)
|
||||||
|
|
Loading…
Reference in New Issue