RAM Watch: Adding multiple watches in the dialog, when adding multiple watches from other window, the watches is also in the address edit control.
I realized that the watch operation need to be decoupled from the RAM Watch list, but things seem get too complicated, hoping this is not get even worse.
This commit is contained in:
parent
a9c4bc9592
commit
7a278b10a8
|
@ -1553,7 +1553,7 @@ void CreateCheatMap()
|
|||
void ReleaseCheatMap()
|
||||
{
|
||||
--CheatMapUsers;
|
||||
printf("CheatMapUsers: %d\n", CheatMapUsers);
|
||||
// printf("CheatMapUsers: %d\n", CheatMapUsers);
|
||||
if (!CheatMapUsers)
|
||||
FCEUI_ReleaseCheatMap();
|
||||
}
|
||||
|
|
|
@ -1982,32 +1982,30 @@ INT_PTR CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
|||
int selCount = SendMessage(ramListControl, LVM_GETSELECTEDCOUNT, 0, 0);
|
||||
if (selCount > 0)
|
||||
{
|
||||
AddressWatcher tempWatch;
|
||||
tempWatch.Size = rs_type_size;
|
||||
tempWatch.Type = rs_t;
|
||||
tempWatch.WrongEndian = 0; //Replace when I get little endian working
|
||||
tempWatch.comment = NULL;
|
||||
WatcherMsg msg;
|
||||
msg.Size = rs_type_size;
|
||||
msg.Type = rs_t;
|
||||
msg.WrongEndian = 0; //Replace when I get little endian working
|
||||
msg.comment = NULL;
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
AddressWatcher* watches = (AddressWatcher*)malloc(selCount * sizeof(AddressWatcher));
|
||||
msg.Addresses = (unsigned int*)malloc(selCount * sizeof(unsigned int));
|
||||
int i = 0;
|
||||
int watchItemIndex = -1;
|
||||
while ((watchItemIndex = SendMessage(ramListControl, LVM_GETNEXTITEM, watchItemIndex, LVNI_SELECTED)) >= 0)
|
||||
{
|
||||
tempWatch.Address = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_type_size, rs_t == 's', noMisalign, watchItemIndex);
|
||||
watches[i] = tempWatch;
|
||||
msg.Addresses[i] = CALL_WITH_T_SIZE_TYPES_1(GetHardwareAddressFromItemIndex, rs_type_size, rs_t == 's', noMisalign, watchItemIndex);
|
||||
++i;
|
||||
}
|
||||
|
||||
msg.count = i;
|
||||
// bring up the ram watch window if it's not already showing so the user knows where the watch went
|
||||
if ((selCount == 1 ?
|
||||
InsertWatch(watches[0], hDlg) : InsertWatches(watches, hDlg, selCount))
|
||||
if (InsertWatches(&msg, hDlg, selCount)
|
||||
&& !RamWatchHWnd)
|
||||
SendMessage(hWnd, WM_COMMAND, ID_RAM_WATCH, 0);
|
||||
SetForegroundWindow(RamSearchHWnd);
|
||||
|
||||
free(watches);
|
||||
if (msg.Addresses) free(msg.Addresses);
|
||||
if (msg.comment) free(msg.comment);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -143,45 +143,37 @@ bool InsertWatch(const AddressWatcher& Watch, HWND parent)
|
|||
|
||||
int prevWatchCount = WatchCount;
|
||||
|
||||
int tmpWatchIndex;
|
||||
if (parent == RamWatchHWnd)
|
||||
tmpWatchIndex = WatchCount;
|
||||
else if (parent == RamSearchHWnd)
|
||||
tmpWatchIndex = -2;
|
||||
else if (parent == hCheat)
|
||||
tmpWatchIndex = -3;
|
||||
else
|
||||
tmpWatchIndex = -4;
|
||||
|
||||
rswatches[tmpWatchIndex] = Watch;
|
||||
rswatches[tmpWatchIndex].CurValue = GetCurrentValue(rswatches[tmpWatchIndex]);
|
||||
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), parent, EditWatchProc, tmpWatchIndex);
|
||||
rswatches.erase(tmpWatchIndex);
|
||||
WatcherMsg msg = WatcherMsg::FromAddressWatches(&Watch);
|
||||
if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), parent, EditWatchProc, (LPARAM)&msg))
|
||||
{
|
||||
AddressWatcher* watcher = msg.ToAddressWatches();
|
||||
InsertWatch(*watcher);
|
||||
if (watcher->comment)
|
||||
free(watcher->comment);
|
||||
free(watcher);
|
||||
}
|
||||
if (msg.Addresses) free(msg.Addresses);
|
||||
if (msg.comment) free(msg.comment);
|
||||
|
||||
return WatchCount > prevWatchCount;
|
||||
}
|
||||
|
||||
bool InsertWatches(const AddressWatcher* watches, HWND parent, const int count)
|
||||
bool InsertWatches(WatcherMsg* msg, HWND parent, int count)
|
||||
{
|
||||
if (count == 1)
|
||||
return InsertWatch(watches[0], parent);
|
||||
else
|
||||
bool success = false;
|
||||
if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), parent, EditWatchProc, (LPARAM)msg))
|
||||
{
|
||||
bool success = false;
|
||||
char comment[256];
|
||||
rswatches[-1] = watches[0];
|
||||
rswatches[-1].comment = comment;
|
||||
if(DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), parent, EditWatchProc, (LPARAM)-1))
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
AddressWatcher watcher = watches[i];
|
||||
watcher.comment = rswatches[-1].comment;
|
||||
success |= InsertWatch(watcher);
|
||||
}
|
||||
rswatches.erase(-1);
|
||||
return success;
|
||||
AddressWatcher* watches = msg->ToAddressWatches();
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
success |= InsertWatch(watches[i]);
|
||||
if (watches[i].comment)
|
||||
free(watches[i].comment);
|
||||
}
|
||||
free(watches);
|
||||
}
|
||||
return false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void Update_RAM_Watch()
|
||||
|
@ -781,193 +773,253 @@ INT_PTR CALLBACK EditWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
|||
|
||||
// since there are 3 windows can pops up the add watch dialog, we should store them separately.
|
||||
// 0 for ram watch, 1 for ram search, 2 for cheat dialog.
|
||||
static int indexes[4];
|
||||
static WatcherMsg* msgs[4];
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
HWND parent = GetParent(hDlg);
|
||||
WatcherMsg* msg = (WatcherMsg*)lParam;
|
||||
msgs[GetDlgStoreIndex(parent)] = (WatcherMsg*)msg;
|
||||
|
||||
RECT r;
|
||||
GetWindowRect(hDlg, &r);
|
||||
SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
||||
|
||||
char title[128];
|
||||
UINT addrCtrlID;
|
||||
|
||||
switch (msg->msg)
|
||||
{
|
||||
|
||||
HWND parent = GetParent(hDlg);
|
||||
indexes[GetDlgStoreIndex(parent)] = lParam;
|
||||
|
||||
RECT r;
|
||||
GetWindowRect(hDlg, &r);
|
||||
SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
||||
|
||||
AddressWatcher& watcher = rswatches[lParam];
|
||||
if (watcher.Type != 'S') {
|
||||
char Str_Tmp[1024];
|
||||
// -1 means batch add
|
||||
if (lParam != -1)
|
||||
{
|
||||
sprintf(Str_Tmp, "%04X", watcher.Address);
|
||||
SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, Str_Tmp);
|
||||
} else
|
||||
// Add multiple watches
|
||||
SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, "(multiple)");
|
||||
|
||||
switch (watcher.Size)
|
||||
{
|
||||
case 'b':
|
||||
SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'w':
|
||||
SendDlgItemMessage(hDlg, IDC_2_BYTES, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'd':
|
||||
SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
}
|
||||
switch (watcher.Type)
|
||||
{
|
||||
case 's':
|
||||
SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'u':
|
||||
SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'h':
|
||||
SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'b':
|
||||
SendDlgItemMessage(hDlg, IDC_BINARY, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
SetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, "---------");
|
||||
|
||||
if (watcher.comment != NULL)
|
||||
SetDlgItemText(hDlg, IDC_PROMPT_EDIT, watcher.comment);
|
||||
|
||||
if (watcher.Type == 'S' || parent == RamSearchHWnd || parent == hCheat)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_SPECIFICADDRESS), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_DATATYPE_GROUPBOX), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_DATASIZE_GROUPBOX), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_EDIT_COMPAREADDRESS), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_SIGNED), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_UNSIGNED), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_HEX), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_BINARY), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_1_BYTE), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_2_BYTES), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_4_BYTES), FALSE);
|
||||
SetFocus(GetDlgItem(hDlg, IDC_PROMPT_EDIT));
|
||||
}
|
||||
else {
|
||||
SetFocus(GetDlgItem(hDlg, IDC_EDIT_COMPAREADDRESS));
|
||||
SendDlgItemMessage(hDlg, IDC_EDIT_COMPAREADDRESS, EM_SETLIMITTEXT, 4, 0);
|
||||
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg, IDC_EDIT_COMPAREADDRESS), GWL_WNDPROC, (LONG)FilterEditCtrlProc);
|
||||
}
|
||||
case WATCHER_MSG_EDIT:
|
||||
// Editing multiple watch is currently not supported
|
||||
addrCtrlID = IDC_EDIT_COMPAREADDRESS;
|
||||
// limit the length to 4 since currently doesn't support batch editing
|
||||
SendDlgItemMessage(hDlg, addrCtrlID, EM_SETLIMITTEXT, 4, 0);
|
||||
strcpy(title, "Edit ");
|
||||
break;
|
||||
case WATCHER_MSG_ADD:
|
||||
strcpy(title, "Add ");
|
||||
addrCtrlID = IDC_EDIT_COMPAREADDRESSES;
|
||||
break;
|
||||
case WATCHER_MSG_DUP:
|
||||
default:
|
||||
strcpy(title, "Duplicate ");
|
||||
addrCtrlID = IDC_EDIT_COMPAREADDRESSES;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
// The information is needed to fill to the UI, and separetor doesn't have them
|
||||
if (msg->Type != 'S')
|
||||
{
|
||||
strcat(title, "Watch");
|
||||
if (msg->Addresses != NULL)
|
||||
{
|
||||
// fill the information refers to the message provided
|
||||
char str_addr[7];
|
||||
char str_addrs[1024] = { 0 };
|
||||
|
||||
// In case more than one watches to be batch added
|
||||
if (msg->count > 0)
|
||||
{
|
||||
// Don't worry about editing a watch since currently doesn't support multiple watch editing, the msg->count would always be 1 in edit mode.
|
||||
for (int i = 0; i < msg->count; ++i)
|
||||
{
|
||||
sprintf(str_addr, "%04X, ", msg->Addresses[i]);
|
||||
strcat(str_addrs, str_addr);
|
||||
}
|
||||
str_addrs[strlen(str_addrs) - 2] = 0;
|
||||
}
|
||||
// Set address(es) to the edit control
|
||||
SetDlgItemText(hDlg, addrCtrlID, str_addrs);
|
||||
|
||||
switch (msg->Size)
|
||||
{
|
||||
case 'b':
|
||||
SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'w':
|
||||
SendDlgItemMessage(hDlg, IDC_2_BYTES, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'd':
|
||||
SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (msg->Type)
|
||||
{
|
||||
case 's':
|
||||
SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'u':
|
||||
SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'h':
|
||||
SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
case 'b':
|
||||
SendDlgItemMessage(hDlg, IDC_BINARY, BM_SETCHECK, BST_CHECKED, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
strcat(title, "Separator");
|
||||
|
||||
// Set the comment
|
||||
if (msg->comment != NULL)
|
||||
SetDlgItemText(hDlg, IDC_PROMPT_EDIT, msg->comment);
|
||||
|
||||
// show the proper edit control
|
||||
ShowWindow(GetDlgItem(hDlg, addrCtrlID), SW_SHOW);
|
||||
ShowWindow(GetDlgItem(hDlg, IDC_SPECIFICADDRESS), SW_SHOW);
|
||||
|
||||
// Adjust the dialog to proper state when editing/adding separator or adding watch from windows other than RAM Watch
|
||||
if (msg->Type == 'S' || parent != RamWatchHWnd)
|
||||
{
|
||||
// same part
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_DATATYPE_GROUPBOX), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_DATASIZE_GROUPBOX), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_SIGNED), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_UNSIGNED), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_HEX), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_BINARY), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_1_BYTE), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_2_BYTES), FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_4_BYTES), FALSE);
|
||||
|
||||
// When it is a separator, focus on the comment
|
||||
if (msg->Type == 'S')
|
||||
SetFocus(GetDlgItem(hDlg, IDC_PROMPT_EDIT));
|
||||
|
||||
// When it is from RAM Search or Cheat Window, all the information required was already given, make the addresses read-only
|
||||
if (parent != RamWatchHWnd)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg, addrCtrlID), TRUE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_SPECIFICADDRESS), TRUE);
|
||||
SetFocus(GetDlgItem(hDlg, IDC_PROMPT_EDIT));
|
||||
SendDlgItemMessage(hDlg, addrCtrlID, EM_SETREADONLY, TRUE, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg, addrCtrlID), TRUE);
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_SPECIFICADDRESS), TRUE);
|
||||
SetFocus(GetDlgItem(hDlg, addrCtrlID));
|
||||
}
|
||||
|
||||
// limit the text
|
||||
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg, addrCtrlID), GWL_WNDPROC, (LONG)FilterEditCtrlProc);
|
||||
|
||||
SetWindowText(hDlg, title);
|
||||
}
|
||||
return false;
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
char Str_Tmp[256];
|
||||
|
||||
HWND parent = GetParent(hDlg);
|
||||
int index = indexes[GetDlgStoreIndex(parent)];
|
||||
WatcherMsg* msg = msgs[GetDlgStoreIndex(parent)];
|
||||
UINT addrCtrlID;
|
||||
|
||||
// not a single watch editing operation
|
||||
if (index != -1)
|
||||
switch (msg->msg)
|
||||
{
|
||||
// a normal watch, copy it to a temporary one
|
||||
AddressWatcher watcher = rswatches[index];
|
||||
// if (watcher.comment != NULL)
|
||||
// watcher.comment = strcpy((char*)malloc(strlen(watcher.comment) + 2), watcher.comment);
|
||||
case WATCHER_MSG_EDIT:
|
||||
addrCtrlID = IDC_EDIT_COMPAREADDRESS;
|
||||
break;
|
||||
case WATCHER_MSG_ADD:
|
||||
case WATCHER_MSG_DUP:
|
||||
addrCtrlID = IDC_EDIT_COMPAREADDRESSES;
|
||||
break;
|
||||
}
|
||||
|
||||
// It's from ram watch window, not a separator
|
||||
// When it's from ram search or cheat window, all the information required is already set,
|
||||
// so this is also unecessary
|
||||
if (RamWatchHWnd && RamWatchHWnd == GetParent(hDlg) && watcher.Type != 'S')
|
||||
{
|
||||
GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 256);
|
||||
// The information is needed to parse from the UI, and separetor doesn't need them
|
||||
if (parent == RamWatchHWnd && msg->Type != 'S')
|
||||
{
|
||||
// Don't worry about editing mode because it always has only 1 address in the edit control
|
||||
|
||||
// type
|
||||
if (SendDlgItemMessage(hDlg, IDC_SIGNED, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Type = 's';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Type = 'u';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_HEX, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Type = 'h';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_BINARY, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Type = 'b';
|
||||
else {
|
||||
MessageBox(hDlg, "Type must be specified.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
// Do the always same part first.
|
||||
|
||||
// size
|
||||
if (SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Size = 'b';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_2_BYTES, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Size = 'w';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
watcher.Size = 'd';
|
||||
else {
|
||||
MessageBox(hDlg, "Size must be specified.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (watcher.Type == 'b' && (watcher.Size == 'd' || watcher.Size == 'w'))
|
||||
{
|
||||
MessageBox(hDlg, "Only 1 byte is supported on binary format.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// address
|
||||
GetDlgItemText(hDlg, IDC_EDIT_COMPAREADDRESS, Str_Tmp, 1024);
|
||||
char *addrstr = Str_Tmp;
|
||||
if (strlen(Str_Tmp) > 8)
|
||||
addrstr = &Str_Tmp[strlen(Str_Tmp) - 9];
|
||||
for (int i = 0; addrstr[i]; ++i)
|
||||
if (toupper(addrstr[i]) == 'O')
|
||||
addrstr[i] = '0';
|
||||
sscanf(addrstr, "%04X", &watcher.Address);
|
||||
|
||||
if ((watcher.Address & ~0xFFFFFF) == ~0xFFFFFF)
|
||||
watcher.Address &= 0xFFFFFF;
|
||||
|
||||
if (!IsHardwareAddressValid(watcher.Address))
|
||||
{
|
||||
MessageBox(hDlg, "Invalid Address.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
// get the type
|
||||
if (SendDlgItemMessage(hDlg, IDC_SIGNED, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Type = 's';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Type = 'u';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_HEX, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Type = 'h';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_BINARY, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Type = 'b';
|
||||
else {
|
||||
MessageBox(hDlg, "Type must be specified.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// comment
|
||||
GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 80);
|
||||
watcher.comment = Str_Tmp;
|
||||
// get the size
|
||||
if (SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Size = 'b';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_2_BYTES, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Size = 'w';
|
||||
else if (SendDlgItemMessage(hDlg, IDC_4_BYTES, BM_GETCHECK, 0, 0) == BST_CHECKED)
|
||||
msg->Size = 'd';
|
||||
else {
|
||||
MessageBox(hDlg, "Size must be specified.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// finallly update the watch list
|
||||
if (index >= 0 && index < WatchCount)
|
||||
// it's a watch editing operation.
|
||||
// Only ram watch window can edit a watch, the ram search window and cheat window only add watch.
|
||||
EditWatch(index, watcher);
|
||||
if (msg->Type == 'b' && (msg->Size == 'd' || msg->Size == 'w'))
|
||||
{
|
||||
MessageBox(hDlg, "Only 1 byte is supported on binary format.", "Error", MB_OK | MB_ICONERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the address(es)
|
||||
char str_addrs[1024];
|
||||
GetDlgItemText(hDlg, addrCtrlID, str_addrs, 1024);
|
||||
char* next = strtok(str_addrs, ",");
|
||||
int i = 0;
|
||||
unsigned int addrSize = 4;
|
||||
|
||||
if (msg->Addresses)
|
||||
msg->Addresses = (unsigned int*)malloc(sizeof(int) * addrSize);
|
||||
else
|
||||
InsertWatch(watcher);
|
||||
if (RamWatchHWnd)
|
||||
ListView_SetItemCount(GetDlgItem(RamWatchHWnd, IDC_WATCHLIST), WatchCount);
|
||||
}
|
||||
else {
|
||||
// a multiple watches insert operation, just asking for a comment
|
||||
AddressWatcher& watcher = rswatches[index];
|
||||
// comment
|
||||
GetDlgItemText(hDlg, IDC_PROMPT_EDIT, Str_Tmp, 80);
|
||||
strcpy(watcher.comment, Str_Tmp);
|
||||
}
|
||||
EndDialog(hDlg, true);
|
||||
msg->Addresses = (unsigned int*)realloc(msg->Addresses, sizeof(int) * addrSize);
|
||||
|
||||
RWfileChanged = true;
|
||||
return true;
|
||||
break;
|
||||
do {
|
||||
sscanf(next, "%04X", &msg->Addresses[i]);
|
||||
// When an invalid address is in it
|
||||
if (!IsHardwareAddressValid(msg->Addresses[i]))
|
||||
{
|
||||
MessageBox(hDlg, "You have entered an invalid address.", "Error", MB_ICONERROR | MB_OK);
|
||||
// Comment out, leave it unfreed until next ID_OK event or close the dialog
|
||||
// free(msg->Addresses);
|
||||
// msg->Addresses = NULL;
|
||||
|
||||
char* start = next + strspn(next, ", ");
|
||||
char* end = start + strcspn(start, ", ");
|
||||
SendDlgItemMessage(hDlg, addrCtrlID, EM_SETSEL, start - str_addrs, end - str_addrs);
|
||||
SetFocus(GetDlgItem(hDlg, addrCtrlID));
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
if (i == addrSize)
|
||||
msg->Addresses = (unsigned int*)realloc(msg->Addresses, sizeof(unsigned int) * (addrSize += 4));
|
||||
} while (next = strtok(NULL, ","));
|
||||
|
||||
msg->count = i;
|
||||
}
|
||||
|
||||
// get the new comment, every AddressWatcher would have a comment, no matter what type it is
|
||||
if (msg->comment)
|
||||
msg->comment = (char*)realloc(msg->comment, 1024 * sizeof(char));
|
||||
else
|
||||
msg->comment = (char*)malloc(1024 * sizeof(char));
|
||||
GetDlgItemText(hDlg, IDC_PROMPT_EDIT, msg->comment, 1024);
|
||||
|
||||
EndDialog(hDlg, true);
|
||||
return false;
|
||||
}
|
||||
case IDCANCEL:
|
||||
EndDialog(hDlg, false);
|
||||
|
@ -1308,19 +1360,43 @@ INT_PTR CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg,IDC_WATCHLIST));
|
||||
if(watchIndex != -1)
|
||||
{
|
||||
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, watchIndex);
|
||||
SetFocus(GetDlgItem(hDlg,IDC_WATCHLIST));
|
||||
WatcherMsg msg = WatcherMsg::FromAddressWatches(&rswatches[watchIndex]);
|
||||
msg.msg = WATCHER_MSG_EDIT;
|
||||
if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, (LPARAM)&msg))
|
||||
{
|
||||
AddressWatcher watcher = msg.ToAddressWatches()[0];
|
||||
EditWatch(watchIndex, watcher);
|
||||
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
if (watcher.comment)
|
||||
free(watcher.comment);
|
||||
}
|
||||
if (msg.Addresses)
|
||||
free(msg.Addresses);
|
||||
if (msg.comment)
|
||||
free(msg.comment);
|
||||
}
|
||||
return true;
|
||||
case IDC_C_WATCH:
|
||||
{
|
||||
AddressWatcher& target = rswatches[WatchCount];
|
||||
target.Address = 0;
|
||||
target.WrongEndian = 0;
|
||||
target.Size = 'b';
|
||||
target.Type = 's';
|
||||
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, WatchCount);
|
||||
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
WatcherMsg msg;
|
||||
msg.Addresses = (unsigned int*)calloc(1, sizeof(unsigned int));
|
||||
msg.WrongEndian = 0;
|
||||
msg.Size = 'b';
|
||||
msg.Type = 's';
|
||||
if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, (LPARAM)&msg))
|
||||
{
|
||||
AddressWatcher* target = msg.ToAddressWatches();
|
||||
for (int i = 0; i < msg.count; ++i)
|
||||
InsertWatch(target[i]);
|
||||
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
if (target->comment)
|
||||
free(target->comment);
|
||||
free(target);
|
||||
}
|
||||
if (msg.Addresses)
|
||||
free(msg.Addresses);
|
||||
if (msg.comment)
|
||||
free(msg.comment);
|
||||
return true;
|
||||
}
|
||||
case IDC_C_WATCH_DUPLICATE:
|
||||
|
@ -1328,27 +1404,46 @@ INT_PTR CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
watchIndex = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
if (watchIndex != -1)
|
||||
{
|
||||
char str_tmp[1024];
|
||||
AddressWatcher* target = &rswatches[WatchCount];
|
||||
AddressWatcher* source = &rswatches[watchIndex];
|
||||
memcpy(target, source, sizeof(AddressWatcher));
|
||||
target->comment = strcpy(str_tmp, source->comment);
|
||||
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, WatchCount);
|
||||
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
WatcherMsg msg = WatcherMsg::FromAddressWatches(&rswatches[watchIndex]);
|
||||
msg.msg = WATCHER_MSG_DUP;
|
||||
if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, (LPARAM)&msg))
|
||||
{
|
||||
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
int count;
|
||||
AddressWatcher* target = msg.ToAddressWatches(&count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
InsertWatch(target[i]);
|
||||
if (target[i].comment)
|
||||
free(target[i].comment);
|
||||
}
|
||||
}
|
||||
if(msg.Addresses)
|
||||
free(msg.Addresses);
|
||||
if(msg.comment)
|
||||
free(msg.comment);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case IDC_C_WATCH_SEPARATE:
|
||||
{
|
||||
AddressWatcher* target = &rswatches[WatchCount];
|
||||
target->Address = 0;
|
||||
target->WrongEndian = false;
|
||||
target->Size = 'S';
|
||||
target->Type = 'S';
|
||||
WatcherMsg msg;
|
||||
msg.WrongEndian = 0;
|
||||
msg.Size = 'S';
|
||||
msg.Type = 'S';
|
||||
msg.msg = WATCHER_MSG_ADD;
|
||||
msg.count = 1;
|
||||
|
||||
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, (LPARAM)WatchCount);
|
||||
if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_EDITWATCH), hDlg, EditWatchProc, (LPARAM)&msg))
|
||||
{
|
||||
AddressWatcher* sep = msg.ToAddressWatches();
|
||||
InsertWatch(*sep);
|
||||
if (sep->comment)
|
||||
free(sep->comment);
|
||||
}
|
||||
if (msg.comment)
|
||||
free(msg.comment);
|
||||
|
||||
// InsertWatch(separator, "----------------------------");
|
||||
SetFocus(GetDlgItem(hDlg, IDC_WATCHLIST));
|
||||
return true;
|
||||
}
|
||||
|
@ -1593,3 +1688,59 @@ SeparatorCache::SeparatorCache(HWND hwnd, char* text) {
|
|||
labelOffY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AddressWatcher* WatcherMsg::ToAddressWatches(int* _count)
|
||||
{
|
||||
AddressWatcher* watches = (AddressWatcher*)malloc(count * sizeof(AddressWatcher));
|
||||
int i = 0;
|
||||
while(i < count)
|
||||
{
|
||||
AddressWatcher watcher;
|
||||
watcher.Size = Size;
|
||||
if (Type != 'S')
|
||||
watcher.Address = Addresses[i];
|
||||
watcher.Type = Type;
|
||||
watcher.WrongEndian = 0;
|
||||
if (comment)
|
||||
{
|
||||
watcher.comment = (char*)malloc(strlen(comment) * sizeof(char) + 1);
|
||||
strcpy(watcher.comment, comment);
|
||||
}
|
||||
else
|
||||
watcher.comment = NULL;
|
||||
watches[i] = watcher;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (_count)
|
||||
*_count = i;
|
||||
|
||||
return watches;
|
||||
}
|
||||
|
||||
WatcherMsg WatcherMsg::FromAddressWatches(const AddressWatcher* watches, int count)
|
||||
{
|
||||
WatcherMsg msg;
|
||||
if (watches[0].comment)
|
||||
{
|
||||
msg.comment = (char*)malloc(strlen(watches[0].comment) + 1);
|
||||
strcpy(msg.comment, watches[0].comment);
|
||||
}
|
||||
|
||||
msg.count = count;
|
||||
msg.Size = watches->Size;
|
||||
msg.Type = watches->Type;
|
||||
msg.WrongEndian = watches->WrongEndian;
|
||||
|
||||
// Because currently doesn't support adding multiple separators at once,
|
||||
// and a separator doesn't have address values,
|
||||
// so when add separator, there's only 1 item in the list
|
||||
if (watches->Type != 'S')
|
||||
{
|
||||
msg.Addresses = (unsigned int*)malloc(count * sizeof(unsigned int));
|
||||
for (int i = 0; i < count; ++i)
|
||||
msg.Addresses[i] = watches[i].Address;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ struct SeparatorCache
|
|||
};
|
||||
|
||||
#define MAX_WATCH_COUNT 256
|
||||
|
||||
extern int WatchCount; // number of valid items in rswatches
|
||||
|
||||
extern char Watch_Dir[1024];
|
||||
|
@ -58,9 +59,28 @@ struct AddressWatcher
|
|||
short Cheats; // how many bytes are affected by cheat
|
||||
};
|
||||
|
||||
// the struct for communicating with add watch window
|
||||
#define WATCHER_MSG_ADD 0
|
||||
#define WATCHER_MSG_EDIT 1
|
||||
#define WATCHER_MSG_DUP 2
|
||||
struct WatcherMsg {
|
||||
int msg = WATCHER_MSG_ADD;
|
||||
int count = 0; // how many addresses are there
|
||||
unsigned int* Addresses = NULL; // Address list
|
||||
char* comment = NULL;
|
||||
bool WrongEndian;
|
||||
char Size;
|
||||
char Type;
|
||||
|
||||
AddressWatcher* ToAddressWatches(int* _count = NULL);
|
||||
static WatcherMsg FromAddressWatches(const AddressWatcher* watches, int count = 1);
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool InsertWatch(const AddressWatcher& Watch);
|
||||
bool InsertWatch(const AddressWatcher& Watch, HWND parent); // asks user for comment
|
||||
bool InsertWatches(const AddressWatcher* watches, HWND parent, const int count);
|
||||
bool InsertWatches(WatcherMsg* msg, HWND parent, int count);
|
||||
bool InsertWatch(int watchIndex, const AddressWatcher& watcher);
|
||||
bool EditWatch(int watchIndex, const AddressWatcher& watcher);
|
||||
bool RemoveWatch(int watchIndex);
|
||||
|
|
|
@ -2205,8 +2205,9 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM
|
|||
CAPTION " Edit Watch"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CTEXT "&Address:",IDC_SPECIFICADDRESS,15,12,30,8
|
||||
EDITTEXT IDC_EDIT_COMPAREADDRESS,48,10,65,12,ES_UPPERCASE | ES_AUTOHSCROLL
|
||||
CTEXT "&Address:",IDC_SPECIFICADDRESS,15,12,30,8,NOT WS_VISIBLE | WS_DISABLED
|
||||
EDITTEXT IDC_EDIT_COMPAREADDRESS,48,10,65,12,ES_UPPERCASE | ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_DISABLED
|
||||
EDITTEXT IDC_EDIT_COMPAREADDRESSES,48,10,65,12,ES_UPPERCASE | ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_DISABLED
|
||||
CTEXT "&Notes:",IDC_PROMPT_TEXT,23,24,22,8
|
||||
EDITTEXT IDC_PROMPT_EDIT,48,22,119,12,ES_AUTOHSCROLL
|
||||
GROUPBOX "Data Type",IDC_DATATYPE_GROUPBOX,14,37,75,53,0,WS_EX_TRANSPARENT
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file
|
||||
// for res.rc
|
||||
// Microsoft Visual C++ 生成的包含文件。
|
||||
// 供 res.rc 使用
|
||||
//
|
||||
#define CLOSE_BUTTON 1
|
||||
#define BUTTON_CLOSE 1
|
||||
#define BTN_CLOSE 1
|
||||
#define MENU_OPEN_FILE 100
|
||||
#define EDIT_ROM 100
|
||||
#define EDIT_ROM 100
|
||||
#define LBL_LOG_TEXT 100
|
||||
#define LBL_KEY_COMBO 100
|
||||
#define LBL_CDLOGGER_CODECOUNT 100
|
||||
|
@ -216,7 +216,7 @@
|
|||
#define IDD_TASEDITOR_FINDNOTE 198
|
||||
#define IDD_TASEDITOR_ABOUT 199
|
||||
#define MENU_RESET 200
|
||||
#define BUTTON_ROM 200
|
||||
#define BUTTON_ROM 200
|
||||
#define TXT_PAD1 200
|
||||
#define BTN_RESTORE_DEFAULTS 200
|
||||
#define BTN_CLEAR 200
|
||||
|
@ -765,6 +765,7 @@
|
|||
#define IDC_EDIT_COMPAREVALUE 1225
|
||||
#define IDC_EDIT_COMPAREADDRESS 1226
|
||||
#define IDC_EDIT_COMPARECHANGES 1227
|
||||
#define IDC_EDIT_COMPAREADDRESSES 1227
|
||||
#define IDC_SIGNED 1228
|
||||
#define IDC_UNSIGNED 1229
|
||||
#define IDC_HEX 1230
|
||||
|
|
|
@ -3293,7 +3293,7 @@ LRESULT APIENTRY FilterEditCtrlProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP)
|
|||
{
|
||||
through = false;
|
||||
// Show Edit control tip, just like the control with ES_NUMBER do
|
||||
ShowLetterIllegalError(hwnd, IsLetterLegal);
|
||||
ShowLetterIllegalBalloonTip(hwnd, IsLetterLegal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3309,7 +3309,7 @@ LRESULT APIENTRY FilterEditCtrlProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP)
|
|||
bool(*IsLetterLegal)(char) = GetIsLetterLegal(GetDlgCtrlID(hwnd));
|
||||
through = IsInputLegal(IsLetterLegal, wP);
|
||||
if (!through)
|
||||
ShowLetterIllegalError(hwnd, IsLetterLegal);
|
||||
ShowLetterIllegalBalloonTip(hwnd, IsLetterLegal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3353,11 +3353,14 @@ bool inline (*GetIsLetterLegal(UINT id))(char letter)
|
|||
case MW_ADDR12: case MW_ADDR13: case MW_ADDR14: case MW_ADDR15:
|
||||
case MW_ADDR16: case MW_ADDR17: case MW_ADDR18: case MW_ADDR19:
|
||||
case MW_ADDR20: case MW_ADDR21: case MW_ADDR22: case MW_ADDR23:
|
||||
case IDC_EDIT_COMPAREADDRESS:
|
||||
|
||||
return IsLetterLegalHex;
|
||||
|
||||
// Specific Address in RAM Search
|
||||
// RAM Watch / RAM Search / Cheat -> Add watch
|
||||
case IDC_EDIT_COMPAREADDRESS:
|
||||
return IsLetterLegalHex;
|
||||
// RAM Watch / RAM Search / Cheat -> Add watch (current only in adding watch operation)
|
||||
case IDC_EDIT_COMPAREADDRESSES:
|
||||
return IsLetterLegalHexList;
|
||||
|
||||
// Size multiplier and TV Aspect in Video Config
|
||||
case IDC_WINSIZE_MUL_X: case IDC_WINSIZE_MUL_Y:
|
||||
|
@ -3390,63 +3393,45 @@ bool inline (*GetIsLetterLegal(UINT id))(char letter)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
inline void ShowLetterIllegalError(HWND hwnd, bool(*IsLetterLegal)(char letter), bool balloon)
|
||||
{
|
||||
(balloon ? ShowLetterIllegalBalloonTip : ShowLetterIllegalMessageBox)(hwnd, IsLetterLegal);
|
||||
}
|
||||
|
||||
void ShowLetterIllegalBalloonTip(HWND hwnd, bool(*IsLetterLegal)(char letter))
|
||||
{
|
||||
char* title = "Unacceptable Character";
|
||||
int uLen = MultiByteToWideChar(CP_ACP, NULL, title, -1, NULL, 0);
|
||||
wchar_t* titleW = (wchar_t*)malloc(sizeof(wchar_t) * uLen);
|
||||
MultiByteToWideChar(CP_ACP, 0, title, -1, (LPWSTR)titleW, uLen);
|
||||
|
||||
char* msg = GetLetterIllegalErrMsg(IsLetterLegal);
|
||||
uLen = MultiByteToWideChar(CP_ACP, NULL, msg, -1, NULL, 0);
|
||||
wchar_t* msgW = (wchar_t*)malloc(sizeof(wchar_t) * uLen);
|
||||
MultiByteToWideChar(CP_ACP, 0, msg, -1, (LPWSTR)msgW, uLen);
|
||||
wchar_t* title = L"Unacceptable Character";
|
||||
wchar_t* msg = GetLetterIllegalErrMsg(IsLetterLegal);
|
||||
|
||||
EDITBALLOONTIP tip;
|
||||
tip.cbStruct = sizeof(EDITBALLOONTIP);
|
||||
tip.pszText = msgW;
|
||||
tip.pszTitle = titleW;
|
||||
tip.pszText = msg;
|
||||
tip.pszTitle = title;
|
||||
tip.ttiIcon = TTI_ERROR;
|
||||
SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&tip);
|
||||
|
||||
// make a sound
|
||||
MessageBeep(0xFFFFFFFF);
|
||||
|
||||
free(titleW);
|
||||
free(msgW);
|
||||
}
|
||||
|
||||
inline void ShowLetterIllegalMessageBox(HWND hwnd, bool(*IsLetterLegal)(char letter))
|
||||
{
|
||||
MessageBox(hwnd, GetLetterIllegalErrMsg(IsLetterLegal), _T("Unacceptable Character"), MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
inline TCHAR* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
|
||||
inline wchar_t* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
|
||||
{
|
||||
if (IsLetterLegal == IsLetterLegalGG)
|
||||
return "You can only type Game Genie characters:\nA P Z L G I T Y E O X U K S V N";
|
||||
return L"You can only type Game Genie characters:\nA P Z L G I T Y E O X U K S V N";
|
||||
if (IsLetterLegal == IsLetterLegalHex)
|
||||
return "You can only type characters for hexadecimal number (0-9,A-F).";
|
||||
return L"You can only type characters for hexadecimal number (0-9,A-F).";
|
||||
if (IsLetterLegal == IsLetterLegalHexList)
|
||||
return L"You can only type characters for hexademical number (0-9,A-F), each number is separated by a comma (,)";
|
||||
if (IsLetterLegal == IsLetterLegalCheat)
|
||||
return
|
||||
"The cheat code comes into the following 2 formats:\n"
|
||||
L"The cheat code comes into the following 2 formats:\n"
|
||||
"AAAA:VV freezes the value in Address $AAAA to $VV.\n"
|
||||
"AAAA?CC:VV changes the value in Address $AAAA to $VV only when it's $CC.\n"
|
||||
"All the characters are hexadecimal number (0-9,A-F).\n";
|
||||
if (IsLetterLegal == IsLetterLegalFloat)
|
||||
return "You can only type decimal number (decimal point is acceptable).";
|
||||
return L"You can only type decimal number (decimal point is acceptable).";
|
||||
if (IsLetterLegal == IsLetterLegalSize)
|
||||
return "You can only type decimal number followed with B, KB or MB.";
|
||||
return L"You can only type decimal number followed with B, KB or MB.";
|
||||
if (IsLetterLegal == IsLetterLegalDec)
|
||||
return "You can only type decimal number (sign character is acceptable).";
|
||||
return L"You can only type decimal number (sign character is acceptable).";
|
||||
if (IsLetterLegal == IsLetterLegalDecHexMixed)
|
||||
return
|
||||
"You can only type decimal or hexademical number\n"
|
||||
L"You can only type decimal or hexademical number\n"
|
||||
"(sign character is acceptable).\n\n"
|
||||
"When your number contains letter A-F,\n"
|
||||
"it is regarded as hexademical number,\n"
|
||||
|
@ -3457,7 +3442,7 @@ inline TCHAR* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
|
|||
"$10 means a hexademical number that is 16 in decimal.";
|
||||
if (IsLetterLegal == IsLetterLegalUnsignedDecHexMixed)
|
||||
return
|
||||
"You can only type decimal or hexademical number.\n\n"
|
||||
L"You can only type decimal or hexademical number.\n\n"
|
||||
"When your number contains letter A-F,\n"
|
||||
"it is regarded as hexademical number,\n"
|
||||
"however, if you want to express a heademical number\n"
|
||||
|
@ -3466,7 +3451,7 @@ inline TCHAR* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter))
|
|||
"eg. 10 is a decimal number,\n"
|
||||
"$10 means a hexademical number that is 16 in decimal.";
|
||||
|
||||
return "Your input contains invalid characters.";
|
||||
return L"Your input contains invalid characters.";
|
||||
}
|
||||
|
||||
inline bool IsInputLegal(bool (*IsLetterLegal)(char letter), char letter)
|
||||
|
@ -3488,6 +3473,11 @@ inline bool IsLetterLegalHex(char letter)
|
|||
return letter >= '0' && letter <= '9' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f';
|
||||
}
|
||||
|
||||
inline bool IsLetterLegalHexList(char letter)
|
||||
{
|
||||
return IsLetterLegalHex(letter) || letter == ',' || letter == ' ';
|
||||
}
|
||||
|
||||
inline bool IsLetterLegalCheat(char letter)
|
||||
{
|
||||
return letter >= '0' && letter <= ':' || letter >= 'A' && letter <= 'F' || letter >= 'a' && letter <= 'f' || letter == '?';
|
||||
|
|
|
@ -129,13 +129,12 @@ void UpdateMenuHotkeys(FCEUMENU_INDEX index);
|
|||
int GetCurrentContextIndex();
|
||||
|
||||
inline bool (*GetIsLetterLegal(UINT id))(char letter);
|
||||
inline char* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter));
|
||||
inline void ShowLetterIllegalError(HWND hwnd, bool(*IsLetterLegal)(char letter), bool balloon = true);
|
||||
inline wchar_t* GetLetterIllegalErrMsg(bool(*IsLetterLegal)(char letter));
|
||||
void ShowLetterIllegalBalloonTip(HWND hwnd, bool(*IsLetterLegal)(char letter));
|
||||
inline void ShowLetterIllegalMessageBox(HWND hwnd, bool(*IsLetterLegal)(char letter));
|
||||
inline bool IsInputLegal(bool(*IsLetterLegal)(char letter), char letter);
|
||||
inline bool IsLetterLegalGG(char letter);
|
||||
inline bool IsLetterLegalHex(char letter);
|
||||
inline bool IsLetterLegalHexList(char letter);
|
||||
inline bool IsLetterLegalCheat(char letter);
|
||||
inline bool IsLetterLegalDec(char letter);
|
||||
inline bool IsLetterLegalSize(char letter);
|
||||
|
|
Loading…
Reference in New Issue