Merge pull request #172 from owomomo/master

Hex Editor bookmark Bugfixes and Feature Updates
This commit is contained in:
CaH4e3 2020-10-06 14:28:48 +03:00 committed by GitHub
commit fb86ac871c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1851 additions and 1201 deletions

View File

@ -63,6 +63,7 @@ CHEATF_SUBFAST SubCheats[256] = { 0 };
uint32 numsubcheats = 0;
int globalCheatDisabled = 0;
int disableAutoLSCheats = 0;
bool disableShowGG = 0;
static _8BYTECHEATMAP* cheatMap = NULL;
struct CHEATF *cheats = 0, *cheatsl = 0;

View File

@ -37,6 +37,7 @@ HMENU hCheatcontext = 0; //Handle to cheat context menu
bool pauseWhileActive = false; //For checkbox "Pause while active"
extern int globalCheatDisabled;
extern int disableAutoLSCheats;
extern bool disableShowGG;
extern bool wasPausedByCheats;
int CheatWindow;
@ -281,7 +282,7 @@ HWND InitializeCheatList(HWND hwnd)
SendMessage(hwndChtList, LVM_INSERTCOLUMN, 0, (LPARAM)&lv);
lv.pszText = "Name";
lv.cx = 132;
lv.cx = 152;
SendMessage(hwndChtList, LVM_INSERTCOLUMN, 1, (LPARAM)&lv);
// Add a checkbox to indicate if the cheat is activated
@ -316,6 +317,7 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
CheckDlgButton(hwndDlg, IDC_CHEAT_PAUSEWHENACTIVE, pauseWhileActive ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg, IDC_CHEAT_GLOBAL_SWITCH, globalCheatDisabled ? BST_UNCHECKED : BST_CHECKED);
CheckDlgButton(hwndDlg, IDC_CHEAT_AUTOLOADSAVE, disableAutoLSCheats == 2 ? BST_UNCHECKED : disableAutoLSCheats == 1 ? BST_INDETERMINATE : BST_CHECKED);
CheckDlgButton(hwndDlg, IDC_CHEAT_SHOWGG, disableShowGG ? BST_UNCHECKED : BST_CHECKED);
//setup font
SetupCheatFont(hwndDlg);
@ -761,6 +763,31 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
}
SetCheatToolTip(hwndDlg, IDC_CHEAT_AUTOLOADSAVE);
}
break;
case IDC_CHEAT_SHOWGG:
{
disableShowGG ^= 1;
void(*CreateCheatStr)(char* buf, int a, int v, int c) = disableShowGG ? GetCheatCodeStr : EncodeGG;
int i = 0;
char buf[32];
LVITEM lvi;
lvi.iSubItem = 0;
struct CHEATF* cheat = cheats;
while (cheat != NULL)
{
if (cheat->addr > 0x7FFF)
{
CreateCheatStr(buf, cheat->addr, cheat->val, cheat->compare);
lvi.pszText = buf;
SendDlgItemMessage(hwndDlg, IDC_LIST_CHEATS, LVM_SETITEMTEXT, i, (LPARAM)&lvi);
}
cheat = cheat->next;
++i;
}
}
}
break;
case EN_SETFOCUS:
@ -1311,11 +1338,10 @@ void DoGGConv()
inline void GetCheatStr(char* buf, int a, int v, int c)
{
if (a > 0x7FFF)
EncodeGG(buf, a, v, c);
else {
if (a < 0x8000 || disableShowGG)
GetCheatCodeStr(buf, a, v, c);
}
else
EncodeGG(buf, a, v, c);
}
inline void GetCheatCodeStr(char* buf, int a, int v, int c)

View File

@ -58,6 +58,7 @@ extern int CurrentState;
extern bool pauseWhileActive; //adelikat: Cheats dialog
extern int globalCheatDisabled;
extern int disableAutoLSCheats;
extern bool disableShowGG;
extern bool enableHUDrecording;
extern bool disableMovieMessages;
extern bool replaceP2StartWithMicrophone;
@ -131,6 +132,7 @@ extern int RomFreezeColorB;
extern int HexBoundColorR;
extern int HexBoundColorG;
extern int HexBoundColorB;
extern int importBookmarkProps;
//adelikat: Hacky fix for Ram Watch recent menu
char* ramWatchRecent[] = {0, 0, 0, 0, 0};
@ -458,6 +460,7 @@ static CFGSTRUCT fceuconfig[] =
AC(HexBoundColorR),
AC(HexBoundColorG),
AC(HexBoundColorB),
AC(importBookmarkProps),
//ACS(memwLastfile[2048]),
AC(AutoRWLoad),
@ -469,6 +472,7 @@ static CFGSTRUCT fceuconfig[] =
AC(compressSavestates),
AC(pauseWhileActive),
AC(disableAutoLSCheats),
AC(disableShowGG),
AC(globalCheatDisabled),
AC(enableHUDrecording),
AC(disableMovieMessages),

View File

@ -2359,7 +2359,7 @@ INT_PTR CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
}
case IDC_DEBUGGER_BOOKMARK_ADD: AddDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_BOOKMARK_DEL: DeleteDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_BOOKMARK_NAME: NameDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_BOOKMARK_EDIT: EditDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_ENABLE_SYMBOLIC:
{
symbDebugEnabled ^= 1;

View File

@ -62,7 +62,9 @@ int debuggerWasActive = 0;
char temp_chr[40] = {0};
char delimiterChar[2] = "#";
extern INT_PTR CALLBACK nameBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK nameDebuggerBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern WNDPROC DefaultEditCtrlProc;
extern LRESULT APIENTRY FilterEditCtrlProc(HWND hDlg, UINT uMsg, WPARAM wP, LPARAM lP);
MemoryMappedRegister RegNames[] = {
{"$2000", "PPU_CTRL"},
@ -768,28 +770,6 @@ unsigned int getBookmarkAddress(unsigned int index)
return 0;
}
/**
* Adds a debugger bookmark to the list on the debugger window.
*
* @param hwnd HWMD of the debugger window
* @param buffer Text of the debugger bookmark
**/
void AddDebuggerBookmark2(HWND hwnd, unsigned int addr)
{
int index = bookmarks.size();
// try to find Symbolic name for this address
Name* node = findNode(getNamesPointerForAddress(addr), addr);
std::pair<unsigned int, std::string> bookmark(addr, node && node->name ? node->name : "");
bookmarks.push_back(bookmark);
// add new item to ListBox
char buffer[256];
sprintf(buffer, "%04X %s", bookmark.first, bookmark.second.c_str());
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_ADDSTRING, 0, (LPARAM)buffer);
// select this item
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_SETCURSEL, index, 0);
}
/**
* Takes the offset from the debugger bookmark edit field and adds a debugger
* bookmark with that offset to the bookmark list if the offset is valid.
@ -798,18 +778,44 @@ void AddDebuggerBookmark2(HWND hwnd, unsigned int addr)
**/
void AddDebuggerBookmark(HWND hwnd)
{
int n;
char buffer[5] = {0};
GetDlgItemText(hwnd, IDC_DEBUGGER_BOOKMARK, buffer, 5);
n = offsetStringToInt(BT_C, buffer);
int address = offsetStringToInt(BT_C, buffer);
// Make sure the offset is valid
if (n == -1 || n > 0xFFFF)
if (address == -1 || address > 0xFFFF)
{
MessageBox(hwnd, "Invalid offset", "Error", MB_OK | MB_ICONERROR);
return;
}
AddDebuggerBookmark2(hwnd, n);
/*
int index = 0;
for (std::vector<std::pair<unsigned int, std::string>>::iterator it = bookmarks.begin(); it != bookmarks.end(); ++it)
{
if (it->first == address)
{
// select this bookmark to notify it already have a bookmark
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_SETCURSEL, index, 0);
return;
}
++index;
}
*/
int index = bookmarks.size();
// try to find Symbolic name for this address
Name* node = findNode(getNamesPointerForAddress(address), address);
std::pair<unsigned int, std::string> bookmark(address, node && node->name ? node->name : "");
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLGDEBUGGER", hwnd, nameDebuggerBookmarkCallB, (LPARAM)&bookmark))
{
bookmarks.push_back(bookmark);
// add new item to ListBox
char buffer[256];
sprintf(buffer, "%04X %s", bookmark.first, bookmark.second.c_str());
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_ADDSTRING, 0, (LPARAM)buffer);
// select this item
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_SETCURSEL, index, 0);
}
}
/**
@ -841,7 +847,7 @@ void DeleteDebuggerBookmark(HWND hwnd)
}
}
void NameDebuggerBookmark(HWND hwnd)
void EditDebuggerBookmark(HWND hwnd)
{
// Get the selected bookmark
int selectedItem = SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_GETCURSEL, 0, 0);
@ -865,7 +871,7 @@ void NameDebuggerBookmark(HWND hwnd)
}
}
// Show the bookmark name dialog
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLG", hwnd, nameBookmarkCallB, (LPARAM)&bookmark))
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLGDEBUGGER", hwnd, nameDebuggerBookmarkCallB, (LPARAM)&bookmark))
{
// Rename the selected bookmark
bookmarks[selectedItem] = bookmark;
@ -1159,4 +1165,88 @@ void WriteNameFileToDisk(const char* filename, Name* node)
}
}
INT_PTR CALLBACK nameDebuggerBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static std::pair<unsigned int, std::string>* debuggerBookmark;
switch (uMsg)
{
case WM_INITDIALOG:
{
// Limit bookmark descriptions to 50 characters
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_DESCRIPTION, EM_SETLIMITTEXT, 50, 0);
// Limit the address text
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_ADDRESS, EM_SETLIMITTEXT, 4, 0);
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
debuggerBookmark = (std::pair<unsigned int, std::string>*)lParam;
char addr[8];
sprintf(addr, "%04X", debuggerBookmark->first);
// Set address and description
sprintf(addr, "%04X", debuggerBookmark->first);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_ADDRESS, addr);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, debuggerBookmark->second.c_str());
// Set focus to the edit field.
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_DESCRIPTION));
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_DESCRIPTION, EM_SETSEL, 0, 52);
break;
}
case WM_QUIT:
case WM_CLOSE:
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
switch (LOWORD(wParam))
{
case IDOK:
{
char addr_str[8];
GetDlgItemText(hwndDlg, IDC_BOOKMARK_ADDRESS, addr_str, 8);
sscanf(addr_str, "%X", &debuggerBookmark->first);
if (debuggerBookmark->first > 0xFFFE)
{
// if the address is out of range
char errmsg[64];
sprintf(errmsg, "The address must be in range of 0-%X", 0xFFFE);
MessageBox(hwndDlg, errmsg, "Address out of range", MB_OK | MB_ICONERROR);
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS));
return FALSE;
}
/*
extern std::vector<std::pair<unsigned int, std::string>> bookmarks;
for (std::vector<std::pair<unsigned int, std::string>>::iterator it = bookmarks.begin(); it != bookmarks.end(); ++it)
{
if (it->first == debuggerBookmark->first && it->second == debuggerBookmark->second)
{
// if the address already have a bookmark
MessageBox(hwndDlg, "This address already have a bookmark", "Bookmark duplicated", MB_OK | MB_ICONASTERISK);
return FALSE;
}
}
*/
// Update the description
char description[51];
GetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, description, 50);
debuggerBookmark->second = description;
EndDialog(hwndDlg, 1);
break;
}
case IDCANCEL:
EndDialog(hwndDlg, 0);
}
}
}
return FALSE;
}

View File

@ -55,9 +55,8 @@ void setNamesPointerForAddress(uint16 address, Name* newNode);
void loadNameFiles();
void replaceNames(Name* list, char* str, std::vector<uint16>* addressesLog = 0);
void AddDebuggerBookmark(HWND hwnd);
void AddDebuggerBookmark2(HWND hwnd, unsigned int addr);
void DeleteDebuggerBookmark(HWND hwnd);
void NameDebuggerBookmark(HWND hwnd);
void EditDebuggerBookmark(HWND hwnd);
void DeleteAllDebuggerBookmarks();
void FillDebuggerBookmarkListbox(HWND hwnd);

View File

@ -114,8 +114,7 @@ static INT_PTR CALLBACK DirConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
case WM_CLOSE:
case WM_QUIT:
CloseDirectoriesDialog(hwndDlg);
CloseDirectoriesDialog(hwndDlg); //adelikat: Hacky but this fixes the directory overides bug (or at least some instances of it). This of course really just puts a band-aid on the real problem.
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
@ -126,9 +125,7 @@ static INT_PTR CALLBACK DirConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
{
case CLOSE_BUTTON:
CloseDirectoriesDialog(hwndDlg);
break;
case BTN_CANCEL:
EndDialog(hwndDlg, 0);
CloseDirectoriesDialog(hwndDlg); //adelikat: Hacky but this fixes the directory overides bug (or at least some instances of it). This of course really just puts a band-aid on the real problem.
break;
default:
static char *helpert[14] = {

View File

@ -628,7 +628,7 @@ void SetHeaderData(HWND hwnd, iNES_HEADER* header) {
// Mapper#
int mapper = header->ROM_type >> 4 | header->ROM_type2 & 0xF0;
if (ines20)
mapper |= (header->ROM_type3 & 0x0F) << 8;
mapper |= (header->ROM_type3 & 0xF0) << 4;
sprintf(buf, "%d ", mapper);
if (SendDlgItemMessage(hwnd, IDC_MAPPER_COMBO, CB_SELECTSTRING, 0, (LPARAM)buf) == CB_ERR)
SetDlgItemText(hwnd, IDC_MAPPER_COMBO, buf);

View File

@ -171,7 +171,7 @@ unsigned int skippy = 0; //Frame skip
int frameSkipCounter = 0; //Counter for managing frame skip
// Contains the names of the overridden standard directories
// in the order roms, nonvol, states, fdsrom, snaps, cheats, movies, memwatch, basic bot, macro, input presets, lua scripts, avi, base
char *directory_names[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char *directory_names[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int edit_id[14] = { EDIT_ROM, EDIT_BATTERY, EDIT_STATE, EDIT_FDSBIOS, EDIT_SCREENSHOT, EDIT_CHEAT, EDIT_MOVIE, EDIT_MEMWATCH, EDIT_BOT, EDIT_MACRO, EDIT_PRESET, EDIT_LUA, EDIT_AVI, EDIT_ROOT };
int browse_btn_id[14] = {BUTTON_ROM, BUTTON_BATTERY, BUTTON_STATE, BUTTON_FDSBIOS, BUTTON_SCREENSHOT, BUTTON_CHEAT, BUTTON_MOVIE, BUTTON_MEMWATCH, BUTTON_BOT, BUTTON_MACRO, BUTTON_PRESET, BUTTON_LUA, BUTTON_AVI, BUTTON_ROOT };
std::string cfgFile = "fceux.cfg";
@ -286,7 +286,7 @@ void DefaultDirectoryWalker(void (*callback)(const char*))
sprintf(
TempArray,
"%s\\%s",
directory_names[NUMBER_OF_DEFAULT_DIRECTORIES] ? directory_names[NUMBER_OF_DEFAULT_DIRECTORIES] : BaseDirectory.c_str(),
directory_names[NUMBER_OF_DEFAULT_DIRECTORIES - 1] ? directory_names[NUMBER_OF_DEFAULT_DIRECTORIES - 1] : BaseDirectory.c_str(),
default_directory_names[curr_dir]
);

View File

@ -71,20 +71,21 @@ char *GetRomName(bool force = false); //Checks if rom is loaded, if so, outputs
char *GetRomPath(bool force = false); //Checks if rom is loaded, if so, outputs the Rom path only
///Contains the names of the default directories.
static const char *default_directory_names[13] = {
static const char *default_directory_names[14] = {
"", // roms
"sav", // nonvol
"sav", // novol
"fcs", // states
"", // fdsrom
"snaps", // snaps
"cheats", // cheats
"movies", // movies
"tools", // memwatch
"tools", // bot
"tools", // macro
"tools", // input presets
"tools", // lua scripts
"luascripts", // lua scripts
"", // avi output
"" // adelikat - adding a dummy one here ( [13] but only 12 entries)
"" // adelikat - adding a dummy one here ( [14] but only 13 entries)
};
#define NUMBER_OF_DIRECTORIES sizeof(directory_names) / sizeof(*directory_names)

View File

@ -141,6 +141,7 @@ int GetAddyFromCoord(int x,int y);
void AutoScrollFromCoord(int x,int y);
LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK importBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void FindNext();
void OpenFindDialog();
static int GetFileData(uint32 offset);
@ -615,7 +616,7 @@ void UpdateMemoryView(int draw_all)
return;
}
char EditString[4][20] = {"RAM","PPU","OAM","ROM"};
char* EditString[4] = {"RAM","PPU","OAM","ROM"};
void UpdateCaption()
{
@ -713,7 +714,7 @@ void UpdateColorTable()
TextColorList[i] = RGB(HexForeColorR,HexForeColorG,HexForeColorB); //Regular color text - 2 columns
}
for (j=0;j<nextBookmark;j++)
for (j=0;j<hexBookmarks.bookmarkCount;j++)
{
if(hexBookmarks[j].editmode != EditingMode) continue;
if(((int)hexBookmarks[j].address >= CurOffset) && ((int)hexBookmarks[j].address < CurOffset+DataAmount))
@ -912,73 +913,7 @@ void UnfreezeAllRam() {
return;
}
/*
int saveBookmarks(HWND hwnd)
{
char name[513] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Save bookmarks as...";
ofn.lpstrFilter = "Bookmark list (*.bld)\0*.lst\0All Files (*.*)\0*.*\0\0";
strcpy(name, mass_replace(GetRomName(), "|", ".").c_str());
ofn.lpstrFile = name;
ofn.lpstrDefExt = "bld";
ofn.nMaxFile = 256;
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
ofn.hwndOwner = hwnd;
bool success = false;
if (GetSaveFileName(&ofn))
{
FILE* bld = fopen(name, "wb");
if (bld)
{
fwrite("BOOKMARKLIST", strlen("BOOKMARKLIST"), 1, bld);
extern int storeHexPreferences(FILE*);
success = storeHexPreferences(bld);
fclose(bld);
}
}
return success;
}
int loadBookmarks(HWND hwnd)
{
char nameo[2048] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Load bookmarks...";
ofn.lpstrFilter = "Bookmark list (*.bld)\0*.lst\0All Files (*.*)\0*.*\0\0";
ofn.lpstrFile = nameo;
ofn.nMaxFile = 256;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.hwndOwner = hwnd;
int success = 0;
if (GetOpenFileName(&ofn))
{
char buffer[13] = { 0 };
FILE* bld = fopen(nameo, "r");
if (bld)
{
fread(bld, strlen("BOOKMARKLIST"), 1, bld);
if (!strcpy(buffer, "BOOKMARKLIST"))
{
extern int loadHexPreferences(FILE*);
success = loadHexPreferences(bld);
}
fclose(bld);
}
}
return success;
}
*/
void FreezeRam(int address, int mode, int final){
// mode: -1 == Unfreeze; 0 == Toggle; 1 == Freeze
if(FrozenAddressCount <= 256 && (address < 0x2000) || ((address >= 0x6000) && (address <= 0x7FFF))){
@ -1245,16 +1180,31 @@ void AutoScrollFromCoord(int x,int y)
void KillMemView()
{
ReleaseDC(hMemView,mDC);
if (hMemView)
{
ReleaseDC(hMemView, mDC);
DestroyWindow(hMemView);
UnregisterClass("MEMVIEW",fceu_hInstance);
hMemView = 0;
hMemFind = 0;
UnregisterClass("MEMVIEW", fceu_hInstance);
hMemView = NULL;
hMemFind = NULL;
if (EditingMode == MODE_NES_MEMORY)
ReleaseCheatMap();
return;
}
}
int GetMaxSize(int EditingMode)
{
switch (EditingMode)
{
case MODE_NES_MEMORY: return 0x10000;
case MODE_NES_PPU: return (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000);
case MODE_NES_OAM: return 0x100;
case MODE_NES_FILE: return 16 + CHRsize[0] + PRGsize[0]; //todo: add trainer size
}
return 0;
}
LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
@ -1414,12 +1364,12 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
int key_num;
sscanf(buf, "%d", &key_num);
key_num = (key_num + 9) % 10;
if (hexBookmarkShortcut[key_num] != -1)
if (hexBookmarks.shortcuts[key_num] != -1)
{
int address = hexBookmarks[hexBookmarkShortcut[key_num]].address;
int address = hexBookmarks[hexBookmarks.shortcuts[key_num]].address;
if (address != -1)
{
ChangeMemViewFocus(hexBookmarks[hexBookmarkShortcut[key_num]].editmode, address, -1);
ChangeMemViewFocus(hexBookmarks[hexBookmarks.shortcuts[key_num]].editmode, address, -1);
UpdateColorTable();
}
}
@ -1844,7 +1794,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
{
if (foundBookmark == -1)
{
if (nextBookmark >= 64)
if (hexBookmarks.bookmarkCount >= 64)
MessageBox(hwnd, "Can't set more than 64 bookmarks.", "Error", MB_OK | MB_ICONERROR);
else
{
@ -2162,17 +2112,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
break;
}
switch (EditingMode)
{
case MODE_NES_MEMORY:
MaxSize = 0x10000; break;
case MODE_NES_PPU:
MaxSize = (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000); break;
case MODE_NES_OAM:
MaxSize = 0x100; break;
case MODE_NES_FILE: //todo: add trainer size
MaxSize = 16 + CHRsize[0] + PRGsize[0]; break;
}
MaxSize = GetMaxSize(EditingMode);
if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount;
if (CurOffset < 0) CurOffset = 0;
@ -2229,7 +2169,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
}
case MENU_MV_BOOKMARKS_RM_ALL:
if (nextBookmark)
if (hexBookmarks.bookmarkCount)
{
if (MessageBox(hwnd, "Remove All Bookmarks?", "Bookmarks", MB_YESNO | MB_ICONINFORMATION) == IDYES)
{
@ -2238,15 +2178,294 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
}
}
return 0;
/*
case MENU_MV_BOOKMARKS_EXPORT:
if (!saveBookmarks(hwnd))
MessageBox(hwnd, "Error saving bookmarks.", "Error", MB_OK | MB_ICONERROR);
case ID_BOOKMARKS_EXPORT:
{
char name[2048] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Save bookmarks as...";
ofn.lpstrFilter = "Hex Editor Bookmark list (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0";
strcpy(name, mass_replace(GetRomName(), "|", ".").c_str());
ofn.lpstrFile = name;
ofn.lpstrDefExt = "hbm";
ofn.nMaxFile = 2048;
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
ofn.hwndOwner = hwnd;
int success = false;
if (GetSaveFileName(&ofn))
{
FILE* bld = fopen(name, "wb");
if (bld)
{
// write the header
fwrite("HexBookmarkList", strlen("HexBookmarkList"), 1, bld);
// it shares the same logic of creating the hexpreference part of .deb file
extern int storeHexPreferences(FILE*, HexBookmarkList& = hexBookmarks);
if (!storeHexPreferences(bld))
success = true;
fclose(bld);
}
if (!success)
MessageBox(hwnd, "Error saving bookmarks.", "Error saving bookmarks", MB_OK | MB_ICONERROR);
}
return 0;
case MENU_MV_BOOKMARKS_IMPORT:
loadBookmarks(hwnd);
}
case ID_BOOKMARKS_IMPORT:
{
char nameo[2048] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Load bookmarks...";
ofn.lpstrFilter = "Hex Editor Bookmarks (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0";
ofn.lpstrFile = nameo;
ofn.lpstrDefExt = "hbm";
ofn.nMaxFile = 2048;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.hwndOwner = hwnd;
bool success = false;
if (GetOpenFileName(&ofn))
{
char buffer[256] = { 0 };
FILE* bld = fopen(nameo, "r");
if (bld)
{
// Read the header to know it's hex bookmark list
fread(buffer, strlen("HexBookmarkList"), 1, bld);
if (!strcmp(buffer, "HexBookmarkList"))
{
HexBookmarkList import;
// it shares the same logic of creating the hexpreference part of .deb file
extern int loadHexPreferences(FILE*, HexBookmarkList& = hexBookmarks);
if (!loadHexPreferences(bld, import) && import.bookmarkCount > 0)
{
if (importBookmarkProps & IMPORT_DISCARD_ORIGINAL)
{
discard_original:
if (importBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT || hexBookmarks.bookmarkCount == 0 || MessageBox(hwnd, "All your existing bookmarks will be discarded after importing the new bookmarks! Do you want to continue?", "Bookmark Import", MB_YESNO | MB_ICONWARNING) == IDYES)
{
removeAllBookmarks(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS));
for (i = 0; i < import.bookmarkCount; ++i)
{
hexBookmarks[i].address = import[i].address;
hexBookmarks[i].editmode = import[i].editmode;
strcpy(hexBookmarks[i].description, import[i].description);
memcpy(hexBookmarks.shortcuts, import.shortcuts, sizeof(hexBookmarks.shortcuts));
hexBookmarks.bookmarkCount = import.bookmarkCount;
hexBookmarks.shortcutCount = import.shortcutCount;
}
updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS));
UpdateColorTable();
}
}
else
{
// conflict bookmark count
int conflictBookmarkCount = 0;
// the conflict bookmark indexes of the main list
int conflictBookmarkIndex[64];
// conflict shortcut count
int conflictShortcutCount = 0;
// discarded bookmark count
int discardBookmarkCount = 0;
// bookmark that is out of scope
int outOfRangeBookmarkCount = 0;
// store the count of bookmarks after importing finished
int finalBookmarkCount = hexBookmarks.bookmarkCount;
// the reference index number in main bookmark list
// -1 means this bookmark is not be indexed
int indexRef[64];
memset(indexRef, -1, sizeof(indexRef));
for (i = 0; i < import.bookmarkCount; ++i)
{
bool conflict = false;
for (j = 0; j < hexBookmarks.bookmarkCount; ++j)
{
// to find if there are any conflict bookmarks
// currently, one address can have only one bookmark
// if the address and editmode are the same, then they are considered conflict
if (import[i].address == hexBookmarks[j].address && import[j].editmode == hexBookmarks[j].editmode)
{
conflictBookmarkIndex[conflictBookmarkCount] = i;
indexRef[i] = j;
++conflictBookmarkCount;
conflict = true;
break;
}
}
// after a loop, this bookmark doesn't have conflict with the original one
if (!conflict)
if (finalBookmarkCount >= 64)
// the total bookmark count has reached the limit of bookmarks (64),
// discard it
++discardBookmarkCount;
else if (import[j].address > GetMaxSize(import[j].editmode))
// the bookmark is out of valid range for current game,
// discard it.
++outOfRangeBookmarkCount;
else
{
// if the bookmark is still not discarded,
// then it's not a conflict one, append it to the last of the main list
indexRef[i] = finalBookmarkCount;
hexBookmarks[finalBookmarkCount].address = import[i].address;
hexBookmarks[finalBookmarkCount].editmode = import[i].editmode;
strcpy(hexBookmarks[finalBookmarkCount].description, import[i].description);
++finalBookmarkCount;
}
}
// the result of overwriting the shortcuts
int shortcutListOverwrite[10];
memcpy(shortcutListOverwrite, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts));
int shortcutListOverwriteCount = hexBookmarks.shortcutCount;
// the result of keep the shortcut as original
int shortcutListKeep[10];
memcpy(shortcutListKeep, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts));
int shortcutListKeepCount = hexBookmarks.shortcutCount;
for (i = 0; i < 10; ++i)
if (import.shortcuts[i] != -1)
{
bool repeat = false;
for (j = 0; j < 10; ++j)
if (indexRef[import.shortcuts[i]] == hexBookmarks.shortcuts[j] && i != j)
{
// the slot in the original list had this bookmark but different
// slot, remove the bookmark in the original slot
shortcutListOverwrite[j] = -1;
--shortcutListOverwriteCount;
++conflictShortcutCount;
repeat = true;
break;
}
if (shortcutListOverwrite[i] == -1)
++shortcutListOverwriteCount;
shortcutListOverwrite[i] = indexRef[import.shortcuts[i]];
// after a loop, the original list doesn't have a slot with same
// bookmark but different slot, and the slot in original list
// is empty, then the bookmark can occupy it.
if (!repeat && hexBookmarks.shortcuts[i] == -1)
{
shortcutListKeep[i] = indexRef[import.shortcuts[i]];
++shortcutListKeepCount;
}
}
int tmpImportBookmarkProps = importBookmarkProps;
bool continue_ = true;
// show the prompt message if there are conflicts
if (!(tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT) && (conflictBookmarkCount || conflictShortcutCount))
{
char units[32];
strcpy(buffer, "The importing bookmark list has ");
sprintf(units, "%d duplicate bookmark", conflictBookmarkCount);
if (conflictBookmarkCount != 1)
strcat(units, "s");
strcat(buffer, units);
if (conflictShortcutCount)
{
if (conflictBookmarkCount) strcat(buffer, " and ");
sprintf(units, "%d conflict shortcut", conflictShortcutCount);
if (conflictShortcutCount != 1)
strcat(units, "s");
strcat(buffer, units);
}
strcat(buffer, " with yours.\r\nYou must choose which side would be reserved. Do you want to continue?");
continue_ = MessageBox(hwnd, buffer, "Bookmark conflict", MB_YESNO | MB_ICONEXCLAMATION) == IDYES && DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, importBookmarkCallB, (LPARAM)&tmpImportBookmarkProps);
if (tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT)
importBookmarkProps = tmpImportBookmarkProps;
// in case user's mind changes on the fly
if (tmpImportBookmarkProps & IMPORT_DISCARD_ORIGINAL)
goto discard_original;
}
if (continue_)
{
if (tmpImportBookmarkProps & IMPORT_OVERWRITE_BOOKMARK)
// when it is set to overwrite conflicted bookmark, otherwise do nothing
for (i = 0; i < conflictBookmarkCount; ++i)
// the conflict bookmarks are all before the bookmark count in main list
strcpy(hexBookmarks[indexRef[conflictBookmarkIndex[i]]].description, import[conflictBookmarkIndex[i]].description);
// update the bookmark shortcut mapping
if (tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT)
{
memcpy(hexBookmarks.shortcuts, shortcutListOverwrite, sizeof(hexBookmarks.shortcuts));
hexBookmarks.shortcutCount = shortcutListOverwriteCount;
}
else
{
memcpy(hexBookmarks.shortcuts, shortcutListKeep, sizeof(hexBookmarks.shortcuts));
hexBookmarks.shortcutCount = shortcutListKeepCount;
}
// set the count of the main list to the imported count
hexBookmarks.bookmarkCount = finalBookmarkCount;
updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS));
UpdateColorTable();
}
// tell user there are bookmarks that imported failed.
if (discardBookmarkCount || outOfRangeBookmarkCount)
{
char reason[64];
sprintf(buffer, "Import complete, but %d bookmark%s %s are not imported:\n", discardBookmarkCount + outOfRangeBookmarkCount, discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "" : "s", discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "is" : "are");
if (outOfRangeBookmarkCount)
{
sprintf(reason, "%d %s outside the valid address range of the game.", outOfRangeBookmarkCount, outOfRangeBookmarkCount == 1 ? "is" : "are");
strcat(buffer, reason);
}
if (discardBookmarkCount)
{
if (outOfRangeBookmarkCount)
strcat(buffer, "\n");
sprintf(reason, "%d %s discaded due to the list has reached its max limit (64).", discardBookmarkCount, discardBookmarkCount == 1 ? "is" : "are");
strcat(buffer, reason);
}
MessageBox(hwnd, buffer, "Loading Hex Editor bookmarks", MB_OK | MB_ICONEXCLAMATION);
}
}
}
else
MessageBox(hwnd, "An error occurred while loading bookmarks.", "Error loading bookmarks", MB_OK | MB_ICONERROR);
}
else
MessageBox(hwnd, "This file is not a Hex Editor bookmark list.", "Error loading bookmarks", MB_OK | MB_ICONERROR);
fclose(bld);
}
else
MessageBox(hwnd, "Error opening bookmark file", "Error loading bookmarks", MB_OK | MB_ICONERROR);
}
}
return 0;
case ID_BOOKMARKS_OPTION:
{
int tmpImportBookmarkProps = importBookmarkProps;
if (DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, importBookmarkCallB, (LPARAM)&tmpImportBookmarkProps))
importBookmarkProps = tmpImportBookmarkProps;
}
return 0;
*/
case MENU_MV_HELP:
OpenHelpWindow(memviewhelp);
return 0;
@ -2282,10 +2501,6 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
case WM_CLOSE:
KillMemView();
//ReleaseDC (hwnd, mDC) ;
//DestroyWindow(hMemView);
//UnregisterClass("MEMVIEW",fceu_hInstance);
//hMemView = 0;
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
@ -2551,3 +2766,182 @@ void PalettePoke(uint32 addr, uint8 data)
PALRAM[addr] = data;
}
}
INT_PTR CALLBACK importBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int* tmpImportBookmarkProps;
static HWND hTipMerge;
static HWND hTipIgnore;
static HWND hTipOverwrite;
static HWND hTipKeep;
static HWND hTipReassign;
static HWND hTipDiscard;
static HWND hTipConfirm;
switch (uMsg)
{
case WM_INITDIALOG:
CenterWindow(hwndDlg);
tmpImportBookmarkProps = (int*)lParam;
if (!(*tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT))
CheckDlgButton(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT, BST_CHECKED);
if (*tmpImportBookmarkProps & IMPORT_DISCARD_ORIGINAL)
{
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD, BST_CHECKED);
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), FALSE);
}
else
{
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE, BST_CHECKED);
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), TRUE);
}
if (*tmpImportBookmarkProps & IMPORT_OVERWRITE_BOOKMARK)
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE, BST_CHECKED);
else
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE, BST_CHECKED);
if (*tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT)
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN, BST_CHECKED);
else
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP, BST_CHECKED);
TOOLINFO info;
memset(&info, 0, sizeof(TOOLINFO));
info.cbSize = sizeof(TOOLINFO);
info.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
info.hwnd = hwndDlg;
hTipMerge = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "Merge the importing bookmarks into my list. \nThe non-conflict bookmarks will be append to the last. \nIf bookmarks or shortcuts have conflicts, \nsolve them according to the import settings.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE);
SendMessage(hTipMerge, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipMerge, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipMerge, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipIgnore = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If the importing bookmark has the same address \nand edit mode with one of the original bookmarks,\nkeep the exsiting one unchanged.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE);
SendMessage(hTipIgnore, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipIgnore, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipIgnore, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipOverwrite = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If the importing bookmark has the same address \nand edit mode with one of the existing bookmarks,\noverwrite the information of the existing one with the importing one.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE);
SendMessage(hTipOverwrite, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipOverwrite, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipOverwrite, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipKeep = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If two different bookmarks from importing and existing \nuse the same shortcut,\nthe shortcut is remained using by the existing one.\nthe importing one will not use the shortcut.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP);
SendMessage(hTipKeep, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipKeep, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipKeep, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipReassign = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If two different bookmarks from importing and existing \nuse the same shortcut,\nthe shortcut is assigned to the importing one.\nthe existing one will not use the shortcut.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN);
SendMessage(hTipReassign, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipReassign, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipReassign, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipDiscard = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "Discard all existing bookmarks and then import.\nThis is not recommended.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD);
SendMessage(hTipDiscard, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipDiscard, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipDiscard, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipConfirm = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "Ask what to do every time when conflict occurs between existing and importing bookmarks.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT);
SendMessage(hTipConfirm, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipConfirm, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipConfirm, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
break;
case WM_CLOSE:
case WM_QUIT:
DestroyWindow(hTipMerge);
DestroyWindow(hTipIgnore);
DestroyWindow(hTipOverwrite);
DestroyWindow(hTipKeep);
DestroyWindow(hTipReassign);
DestroyWindow(hTipDiscard);
DestroyWindow(hTipConfirm);
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
switch (LOWORD(wParam))
{
case IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD:
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), FALSE);
break;
case IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE:
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), TRUE);
break;
case IDOK:
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT) == BST_UNCHECKED)
*tmpImportBookmarkProps |= IMPORT_OVERWRITE_NO_PROMPT;
else
*tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_NO_PROMPT;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD))
*tmpImportBookmarkProps |= IMPORT_DISCARD_ORIGINAL;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE))
*tmpImportBookmarkProps &= ~IMPORT_DISCARD_ORIGINAL;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE))
*tmpImportBookmarkProps |= IMPORT_OVERWRITE_BOOKMARK;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE))
*tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_BOOKMARK;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN))
*tmpImportBookmarkProps |= IMPORT_OVERWRITE_SHORTCUT;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP))
*tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_SHORTCUT;
EndDialog(hwndDlg, 1);
break;
case IDCANCEL:
case IDCLOSE:
EndDialog(hwndDlg, 0);
break;
}
}
}
return FALSE;
}

View File

@ -1,19 +1,23 @@
#ifndef MEMVIEW_H
#define MEMVIEW_H
void DoMemView();
void KillMemView();
void UpdateMemoryView(int draw_all);
void UpdateColorTable();
void ChangeMemViewFocus(int newEditingMode, int StartOffset,int EndOffset);
void UpdateCaption();
/*
int saveBookmarks(HWND hwnd);
int loadBookmarks(HWND hwnd);
*/
void ApplyPatch(int addr,int size, uint8* data);
void UndoLastPatch();
void SetHexEditorAddress(int gotoaddress);
int GetMaxSize(int editingMode);
extern HWND hMemView, hMemFind;
extern int EditingMode;
extern char EditString[4][20];
extern char* EditString[4];
#endif

View File

@ -22,14 +22,18 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <uxtheme.h>
#include "memviewsp.h"
#include "memview.h"
#include "debugger.h"
#include "common.h"
HexBookmark hexBookmarks[64];
int hexBookmarkShortcut[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
int numHexBookmarkShortcut = 0;
int nextBookmark = 0;
#pragma comment(lib, "uxtheme.lib")
int importBookmarkProps = IMPORT_OVERWRITE_NONE;
HexBookmarkList hexBookmarks;
static HFONT hFont, hNewFont;
/// Finds the bookmark for a given address
/// @param address The address to find.
@ -39,13 +43,13 @@ int findBookmark(unsigned int address, int editmode)
{
int i;
if (address > 0xFFFF)
if (address > GetMaxSize(editmode))
{
MessageBox(0, "Error: Invalid address was specified as parameter to findBookmark", "Error", MB_OK | MB_ICONERROR);
return -1;
}
for (i=0;i<nextBookmark;i++)
for (i=0; i < hexBookmarks.bookmarkCount; i++)
{
if (hexBookmarks[i].address == address && hexBookmarks[i].editmode == editmode)
return i;
@ -54,23 +58,12 @@ int findBookmark(unsigned int address, int editmode)
return -1;
}
BOOL CenterWindow(HWND hwndDlg);
/// Callback function for the name bookmark dialog
/*
TODO: The bookmarks of Debugger and Hex Editor uses the same dialog box,
but different bookmark systems, either decouple their callback into separate
functions or unify them to use the same bookmark system.
*/
INT_PTR CALLBACK nameBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
INT_PTR CALLBACK nameHexBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// For Hex Editor
static HexBookmarkMsg* hexBookmarkMsg;
static int dlgShortcutRadioCheck[10] = { IDC_RADIO_SHORTCUT0, IDC_RADIO_SHORTCUT1, IDC_RADIO_SHORTCUT2, IDC_RADIO_SHORTCUT3, IDC_RADIO_SHORTCUT4, IDC_RADIO_SHORTCUT5, IDC_RADIO_SHORTCUT6, IDC_RADIO_SHORTCUT7, IDC_RADIO_SHORTCUT8, IDC_RADIO_SHORTCUT9 };
// For Debugger
extern HWND hDebug;
static std::pair<unsigned int, std::string>* debuggerBookmark;
static int dlgShortcutRadio[10] = { IDC_RADIO_SHORTCUT0, IDC_RADIO_SHORTCUT1, IDC_RADIO_SHORTCUT2, IDC_RADIO_SHORTCUT3, IDC_RADIO_SHORTCUT4, IDC_RADIO_SHORTCUT5, IDC_RADIO_SHORTCUT6, IDC_RADIO_SHORTCUT7, IDC_RADIO_SHORTCUT8, IDC_RADIO_SHORTCUT9 };
static int dlgShortcutCaption[10] = { IDC_EDIT_SHORTCUT0, IDC_EDIT_SHORTCUT1, IDC_EDIT_SHORTCUT2, IDC_EDIT_SHORTCUT3, IDC_EDIT_SHORTCUT4, IDC_EDIT_SHORTCUT5, IDC_EDIT_SHORTCUT6, IDC_EDIT_SHORTCUT7, IDC_EDIT_SHORTCUT8, IDC_EDIT_SHORTCUT9 };
switch (uMsg)
{
@ -79,64 +72,83 @@ INT_PTR CALLBACK nameBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
// Limit bookmark descriptions to 50 characters
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_DESCRIPTION, EM_SETLIMITTEXT, 50, 0);
// Put the current bookmark description into the edit field
HWND parent = GetParent(hwndDlg);
// Limit the address text
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_ADDRESS, EM_SETLIMITTEXT, 6, 0);
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
// Add View list box
for (int i = 0; i < 4; ++i)
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_COMBO_VIEW, CB_INSERTSTRING, -1, (LPARAM)EditString[i]);
char addr[5];
const char* description;
// Called from Hex Editor
if (parent == hMemView)
{
hexBookmarkMsg = (HexBookmarkMsg*)lParam;
HexBookmark* hexBookmark = hexBookmarkMsg->bookmark;
sprintf(addr, "%04X", hexBookmark->address);
description = hexBookmark->description;
bool shortcut_assigned = hexBookmarkMsg->shortcut_index != -1;
if (shortcut_assigned)
if (hexBookmarkMsg->shortcut_index != -1)
{
CheckDlgButton(hwndDlg, IDC_CHECK_SHORTCUT, BST_CHECKED);
CheckDlgButton(hwndDlg, dlgShortcutRadioCheck[hexBookmarkMsg->shortcut_index], BST_CHECKED);
CheckDlgButton(hwndDlg, dlgShortcutRadio[hexBookmarkMsg->shortcut_index], BST_CHECKED);
}
else
EnableWindow(GetDlgItem(hwndDlg, IDC_BOOKMARK_SHORTCUT_PREFIX_TEXT), FALSE);
for (int i = 0; i < 10; ++i)
if (!shortcut_assigned || hexBookmarkShortcut[i] != -1 && hexBookmarkShortcut[i] != hexBookmarkMsg->bookmark_index)
// the shortcut number is occupied but it doesn't belongs to this bookmark, or the bookmark doesn't have a shortcut
EnableWindow(GetDlgItem(hwndDlg, dlgShortcutRadioCheck[i]), FALSE);
hFont = (HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0);
LOGFONT lf;
GetObject(hFont, sizeof(LOGFONT), &lf);
strcpy(lf.lfFaceName, "Courier New");
hNewFont = CreateFontIndirect(&lf);
if (!shortcut_assigned && numHexBookmarkShortcut >= 10)
for (int i = 0; i < 10; ++i)
{
SetWindowTheme(GetDlgItem(hwndDlg, dlgShortcutRadio[i]), L"", L"");
// The slot is not occupied, or it is the same slot of the bookmark
EnableWindow(GetDlgItem(hwndDlg, dlgShortcutRadio[i]), hexBookmarkMsg->shortcut_index != -1 && (hexBookmarks.shortcuts[i] == -1 || hexBookmarks.shortcuts[i] == hexBookmarkMsg->bookmark_index));
if (hexBookmarks.shortcuts[i] != -1) {
// Fill the caption block with the address information
char buf[16];
sprintf(buf, "%s: $%04X", EditString[hexBookmarks[hexBookmarks.shortcuts[i]].editmode], hexBookmarks[hexBookmarks.shortcuts[i]].address);
SetDlgItemText(hwndDlg, dlgShortcutCaption[i], buf);
SendDlgItemMessage(hwndDlg, dlgShortcutCaption[i], WM_SETFONT, (WPARAM)hNewFont, FALSE);
}
else
EnableWindow(GetDlgItem(hwndDlg, dlgShortcutCaption[i]), FALSE);
}
if (hexBookmarkMsg->shortcut_index == -1 && hexBookmarks.shortcutCount >= 10)
{
// all the shortcuts are occupied and this one doesn't have a shortcut, it's impossible to assign a new shortcut
EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_SHORTCUT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_BOOKMARK_SHORTCUT_PREFIX_TEXT), FALSE);
}
}
// Called from Debugger
else if (parent == hDebug)
{
debuggerBookmark = (std::pair<unsigned int, std::string>*)lParam;
sprintf(addr, "%04X", debuggerBookmark->first);
description = debuggerBookmark->second.c_str();
// Hide the shortcut panel since it doesn't support jump to address shortcut keys.
ShowWindow(GetDlgItem(hwndDlg, IDC_CHECK_SHORTCUT), SW_HIDE);
ShowWindow(GetDlgItem(hwndDlg, IDC_BOOKMARK_SHORTCUT_PREFIX_TEXT), SW_HIDE);
for (int i = 0; i < 10; ++i)
ShowWindow(GetDlgItem(hwndDlg, dlgShortcutRadioCheck[i]), SW_HIDE);
}
// Set address and description
char addr[8];
sprintf(addr, "%04X", hexBookmark->address);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_ADDRESS, addr);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, description);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, hexBookmark->description);
// Set the view of the bookmark
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_COMBO_VIEW, CB_SETCURSEL, hexBookmarkMsg->bookmark->editmode, 0);
// and set focus to that edit field.
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_DESCRIPTION));
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_DESCRIPTION, EM_SETSEL, 0, 52);
break;
}
case WM_CTLCOLORSTATIC:
if (hexBookmarkMsg->shortcut_index != -1 && hexBookmarks.shortcuts[hexBookmarkMsg->shortcut_index] == hexBookmarkMsg->bookmark_index && ((HWND)lParam == GetDlgItem(hwndDlg, dlgShortcutCaption[hexBookmarkMsg->shortcut_index]) || (HWND)lParam == GetDlgItem(hwndDlg, dlgShortcutRadio[hexBookmarkMsg->shortcut_index])))
{
SetBkMode((HDC)wParam, TRANSPARENT);
SetTextColor((HDC)wParam, RGB(0, 128, 0));
return (INT_PTR)GetSysColorBrush(COLOR_BTNFACE);
}
break;
case WM_CLOSE:
case WM_QUIT:
DeleteObject(hNewFont);
DeleteObject(hFont);
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
@ -148,50 +160,76 @@ INT_PTR CALLBACK nameBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
case IDC_CHECK_SHORTCUT:
{
UINT shortcut_assigned = IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHORTCUT);
EnableWindow(GetDlgItem(hwndDlg, IDC_BOOKMARK_SHORTCUT_PREFIX_TEXT), shortcut_assigned);
EnableWindow(GetDlgItem(hwndDlg, IDC_BOOKMARK_SHORTCUT_PREFIX_TEXT), shortcut_assigned == BST_CHECKED);
for (int i = 0; i < 10; ++i)
EnableWindow(GetDlgItem(hwndDlg, dlgShortcutRadioCheck[i]), shortcut_assigned && (hexBookmarkShortcut[i] == -1 || hexBookmarkShortcut[i] == hexBookmarkMsg->bookmark_index));
EnableWindow(GetDlgItem(hwndDlg, dlgShortcutRadio[i]), shortcut_assigned && (hexBookmarks.shortcuts[i] == -1 || hexBookmarks.shortcuts[i] == hexBookmarkMsg->bookmark_index));
}
break;
case IDOK:
{
HWND parent = GetParent(hwndDlg);
// Called from Hex Editor
if (parent == hMemView)
int address, editmode;
// Get the address;
char addr_str[8];
GetDlgItemText(hwndDlg, IDC_BOOKMARK_ADDRESS, addr_str, 8);
sscanf(addr_str, "%X", &address);
// Get the view which the address in
editmode = SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_COMBO_VIEW, CB_GETCURSEL, 0, 0);
int MaxSize = GetMaxSize(editmode);
// Update the address
if (address > MaxSize - 1)
{
// if the address is out of range
char errmsg[64];
sprintf(errmsg, "The address in %s must be in range of 0-%X", EditString[editmode], MaxSize - 1);
MessageBox(hwndDlg, errmsg, "Address out of range", MB_OK | MB_ICONERROR);
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS));
return FALSE;
}
int found = findBookmark(address, editmode);
if (found != -1 && found != hexBookmarkMsg->bookmark_index)
{
// if the address already have a bookmark and the bookmark is not the one we currently editing
MessageBox(hwndDlg, "This address already have a bookmark", "Bookmark duplicated", MB_OK | MB_ICONASTERISK);
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS));
return FALSE;
}
hexBookmarkMsg->bookmark->address = address;
hexBookmarkMsg->bookmark->editmode = editmode;
// Update the bookmark description
GetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, hexBookmarkMsg->bookmark->description, 50);
// Update the shortcut key
if (hexBookmarkMsg->shortcut_index != -1 && hexBookmarkShortcut[hexBookmarkMsg->shortcut_index] != -1)
if (hexBookmarkMsg->shortcut_index != -1 && hexBookmarks.shortcuts[hexBookmarkMsg->shortcut_index] == hexBookmarkMsg->bookmark_index)
{
hexBookmarkShortcut[hexBookmarkMsg->shortcut_index] = -1;
--numHexBookmarkShortcut;
hexBookmarks.shortcuts[hexBookmarkMsg->shortcut_index] = -1;
--hexBookmarks.shortcutCount;
}
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHORTCUT))
for (int i = 0; i < 10; ++i)
if(IsDlgButtonChecked(hwndDlg, dlgShortcutRadioCheck[i]))
if (IsDlgButtonChecked(hwndDlg, dlgShortcutRadio[i]))
{
// Update the shortcut index
hexBookmarkShortcut[i] = hexBookmarkMsg->bookmark_index;
++numHexBookmarkShortcut;
hexBookmarks.shortcuts[i] = hexBookmarkMsg->bookmark_index;
++hexBookmarks.shortcutCount;
break;
}
}
else if (parent == hDebug)
{
char description[51];
GetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, description, 50);
debuggerBookmark->second = description;
}
EndDialog(hwndDlg, 1);
break;
}
}
}
break;
case IDCANCEL:
EndDialog(hwndDlg, 0);
}
}
}
return FALSE;
@ -205,38 +243,38 @@ INT_PTR CALLBACK nameBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
int addBookmark(HWND hwnd, unsigned int address, int editmode)
{
// Enforce a maximum of 64 bookmarks
if (nextBookmark < 64)
if (hexBookmarks.bookmarkCount < 64)
{
hexBookmarks[nextBookmark].address = address;
hexBookmarks[nextBookmark].editmode = editmode;
sprintf(hexBookmarks[nextBookmark].description, "%s %04X", EditString[editmode], address);
hexBookmarks[hexBookmarks.bookmarkCount].address = address;
hexBookmarks[hexBookmarks.bookmarkCount].editmode = editmode;
sprintf(hexBookmarks[hexBookmarks.bookmarkCount].description, "%s %04X", EditString[editmode], address);
HexBookmarkMsg msg;
// Pre-define a shortcut if possible
for (int i = 0; i < 10; ++i)
if (hexBookmarkShortcut[i] == -1)
if (hexBookmarks.shortcuts[i] == -1)
{
msg.shortcut_index = i;
break;
}
msg.bookmark = &hexBookmarks[nextBookmark];
msg.bookmark_index = nextBookmark;
msg.bookmark = &hexBookmarks[hexBookmarks.bookmarkCount];
msg.bookmark_index = hexBookmarks.bookmarkCount;
// Show the bookmark name dialog
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLG", hwnd, nameBookmarkCallB, (LPARAM)&msg))
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLGMEMVIEW", hwnd, nameHexBookmarkCallB, (LPARAM)&msg))
{
nextBookmark++;
hexBookmarks.bookmarkCount++;
return 0;
}
else
{
if (msg.shortcut_index != -1)
{
if (hexBookmarkShortcut[msg.shortcut_index] != -1)
--numHexBookmarkShortcut;
hexBookmarkShortcut[msg.shortcut_index] = -1;
if (hexBookmarks.shortcuts[msg.shortcut_index] != -1)
--hexBookmarks.shortcutCount;
hexBookmarks.shortcuts[msg.shortcut_index] = -1;
}
return 1;
}
@ -259,14 +297,14 @@ int editBookmark(HWND hwnd, unsigned int index)
// find its shortcut index
for (int i = 0; i < 10; ++i)
if (index == hexBookmarkShortcut[i])
if (index == hexBookmarks.shortcuts[i])
{
msg.shortcut_index = i;
break;
}
// Show the bookmark name dialog
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLG", hwnd, nameBookmarkCallB, (LPARAM)&msg))
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLGMEMVIEW", hwnd, nameHexBookmarkCallB, (LPARAM)&msg))
return 0;
else
return 1;
@ -285,23 +323,23 @@ int removeBookmark(unsigned int index)
for (int i = 0; i < 10; ++i)
{
// all the indexes after the deleted one sould decrease by 1
if (hexBookmarkShortcut[i] != -1 && hexBookmarkShortcut[i] > index)
--hexBookmarkShortcut[i];
else if (hexBookmarkShortcut[i] == index)
if (hexBookmarks.shortcuts[i] != -1 && hexBookmarks.shortcuts[i] > index)
--hexBookmarks.shortcuts[i];
else if (hexBookmarks.shortcuts[i] == index)
{
// delete the shortcut index itself
hexBookmarkShortcut[i] = -1;
--numHexBookmarkShortcut;
hexBookmarks.shortcuts[i] = -1;
--hexBookmarks.shortcutCount;
}
}
// At this point it's necessary to move the content of the bookmark list
for (int i=index;i<nextBookmark - 1;i++)
for (int i=index;i<hexBookmarks.bookmarkCount - 1;i++)
{
hexBookmarks[i] = hexBookmarks[i+1];
}
--nextBookmark;
--hexBookmarks.bookmarkCount;
return 0;
}
@ -331,34 +369,40 @@ int toggleBookmark(HWND hwnd, uint32 address, int editmode)
void updateBookmarkMenus(HMENU menu)
{
// Remove all bookmark menus
for (int i = 0; i<nextBookmark + 1; i++)
for (int i = 0; i < hexBookmarks.bookmarkCount + 1; i++)
RemoveMenu(menu, ID_FIRST_BOOKMARK + i, MF_BYCOMMAND);
RemoveMenu(menu, ID_BOOKMARKLIST_SEP, MF_BYCOMMAND);
if (nextBookmark != 0)
if (hexBookmarks.bookmarkCount != 0)
{
// Add the menus again
AppendMenu(menu, MF_SEPARATOR, ID_BOOKMARKLIST_SEP, NULL);
for (int i = 0;i<nextBookmark;i++)
InsertMenu(menu, ID_BOOKMARKS_IMPORT, MF_SEPARATOR | MF_BYCOMMAND, ID_BOOKMARKLIST_SEP, NULL);
for (int i = 0; i < hexBookmarks.bookmarkCount; i++)
{
// Get the text of the menu
char buffer[0x100];
sprintf(buffer, i < 10 ? "&%d. $%04X - %s" : "%d. $%04X - %s",i, hexBookmarks[i].address, hexBookmarks[i].description);
if (i < 9)
sprintf(buffer, "&%d. %s:$%04X - %s", i + 1, EditString[hexBookmarks[i].editmode], hexBookmarks[i].address, hexBookmarks[i].description);
else if (i == 9)
sprintf(buffer, "1&0. %s:$%04X - %s", EditString[hexBookmarks[i].editmode], hexBookmarks[i].address, hexBookmarks[i].description);
else
sprintf(buffer, "%d. %s:$%04X - %s", i + 1, EditString[hexBookmarks[i].editmode], hexBookmarks[i].address, hexBookmarks[i].description);
AppendMenu(menu, MF_STRING, ID_FIRST_BOOKMARK + i, buffer);
InsertMenu(menu, ID_BOOKMARKLIST_SEP, MF_STRING | MF_BYCOMMAND, ID_FIRST_BOOKMARK + i, buffer);
}
for (int i = 0; i < 10; ++i)
{
if (hexBookmarkShortcut[i] != -1)
if (hexBookmarks.shortcuts[i] != -1)
{
char buffer[0x100];
GetMenuString(menu, ID_FIRST_BOOKMARK + hexBookmarkShortcut[i], buffer, 50, MF_BYCOMMAND);
sprintf(&buffer[strlen(buffer)], "\tCtrl+%d\0", (i + 1) % 10);
ModifyMenu(menu, ID_FIRST_BOOKMARK + hexBookmarkShortcut[i], MF_BYCOMMAND, ID_FIRST_BOOKMARK + hexBookmarkShortcut[i], buffer);
char shortcut[16];
GetMenuString(menu, ID_FIRST_BOOKMARK + hexBookmarks.shortcuts[i], buffer, 50, MF_BYCOMMAND);
sprintf(shortcut, "\tCtrl+%d\0", (i + 1) % 10);
strcat(buffer, shortcut);
ModifyMenu(menu, ID_FIRST_BOOKMARK + hexBookmarks.shortcuts[i], MF_BYCOMMAND, ID_FIRST_BOOKMARK + hexBookmarks.shortcuts[i], buffer);
}
}
}
}
@ -367,7 +411,7 @@ void updateBookmarkMenus(HMENU menu)
/// @return The address to scroll to or -1 if the bookmark index is invalid.
int handleBookmarkMenu(int bookmark)
{
if (bookmark < nextBookmark)
if (bookmark < hexBookmarks.bookmarkCount)
{
return hexBookmarks[bookmark].address;
}
@ -379,14 +423,19 @@ int handleBookmarkMenu(int bookmark)
/// @param menu Handle of the bookmark menu
void removeAllBookmarks(HMENU menu)
{
for (int i = 0;i<nextBookmark;i++)
for (int i = 0;i<hexBookmarks.bookmarkCount;i++)
{
RemoveMenu(menu, ID_FIRST_BOOKMARK + i, MF_BYCOMMAND);
}
RemoveMenu(menu, ID_BOOKMARKLIST_SEP, MF_BYCOMMAND);
nextBookmark = 0;
numHexBookmarkShortcut = 0;
hexBookmarks.bookmarkCount = 0;
hexBookmarks.shortcutCount = 0;
for (int i = 0; i < 10; ++i)
hexBookmarkShortcut[i] = -1;
hexBookmarks.shortcuts[i] = -1;
}
HexBookmark& HexBookmarkList::operator[](int index)
{
return bookmarks[index];
}

View File

@ -18,6 +18,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MEMVIEWSP_H
#define MEMVIEWSP_H
#include "types.h"
#define ID_FIRST_BOOKMARK 30
@ -37,10 +40,24 @@ typedef struct
int shortcut_index = -1;
} HexBookmarkMsg;
extern HexBookmark hexBookmarks[64];
extern int hexBookmarkShortcut[10];
extern int numHexBookmarkShortcut;
extern int nextBookmark;
extern struct HexBookmarkList
{
HexBookmark bookmarks[64];
int shortcuts[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
int bookmarkCount = 0;
int shortcutCount = 0;
HexBookmark& operator[](int index);
} hexBookmarks;
#define IMPORT_OVERWRITE_NONE 0 // Overwrite nothing
#define IMPORT_OVERWRITE_BOOKMARK 1 // Overwrite duplicated bookmarks but don't overwrite duplicated shortcuts
#define IMPORT_OVERWRITE_SHORTCUT 2 // Overwrite duplicated shortcuts but don't overwrite duplicated bookmarks
#define IMPORT_OVERWRITE_ALL (IMPORT_OVERWRITE_BOOKMARK | IMPORT_OVERWRITE_SHORTCUT), // (3) Overwrite duplicated bookmarks and shortcuts
#define IMPORT_OVERWRITE_NO_PROMPT 4 // Not confirm for what to do when conflicts
#define IMPORT_DISCARD_ORIGINAL 8 // Discard all the original bookmarks
extern int importBookmarkProps;
int findBookmark(unsigned int address, int editmode);
int addBookmark(HWND hwnd, unsigned int address, int editmode);
@ -50,3 +67,8 @@ int removeBookmark(unsigned int index);
void updateBookmarkMenus(HMENU menu);
int handleBookmarkMenu(int bookmark);
void removeAllBookmarks(HMENU menu);
extern LRESULT APIENTRY FilterEditCtrlProc(HWND hDlg, UINT msg, WPARAM wP, LPARAM lP);
extern WNDPROC DefaultEditCtrlProc;
#endif

View File

@ -120,41 +120,54 @@ int storeDebuggerPreferences(FILE* f)
* Stores the preferences from the Hex window
*
* @param f File to write the preferences to
* @param source The source the preferences are read from
* @return 0 if everything went fine. An error code if something went wrong.
**/
int storeHexPreferences(FILE* f)
int storeHexPreferences(FILE* f, HexBookmarkList& source = hexBookmarks)
{
int i;
// Writes the number of bookmarks to save
if (fwrite(&nextBookmark, sizeof(nextBookmark), 1, f) != 1) return 1;
if (fwrite(&source.bookmarkCount, sizeof(source.bookmarkCount), 1, f) != 1) return 1;
for (i=0;i<nextBookmark;i++)
for (i=0;i<source.bookmarkCount;i++)
{
unsigned int len;
// Writes the bookmark address
if (fwrite(&hexBookmarks[i].address, sizeof(hexBookmarks[i].address), 1, f) != 1) return 1;
if (fwrite(&source[i].address, sizeof(source[i].address), 1, f) != 1) return 1;
len = strlen(hexBookmarks[i].description);
len = strlen(source[i].description);
// Writes the length of the bookmark description
if (fwrite(&len, sizeof(len), 1, f) != 1) return 1;
// Writes the actual bookmark description
if (fwrite(hexBookmarks[i].description, 1, len, f) != len) return 1;
if (fwrite(source[i].description, 1, len, f) != len) return 1;
}
// optional section: save bookmark shortcut matches
if (numHexBookmarkShortcut)
// Optional Section 1: Save bookmark shortcut matches
if (source.shortcutCount)
{
fwrite(&numHexBookmarkShortcut, sizeof(numHexBookmarkShortcut), 1, f);
fwrite(&source.shortcutCount, sizeof(source.shortcutCount), 1, f);
for (int i = 0; i < 10; ++i)
if (hexBookmarkShortcut[i] != -1)
if (source.shortcuts[i] != -1)
{
fwrite(&hexBookmarkShortcut[i], sizeof(hexBookmarkShortcut[i]), 1, f);
fwrite(&source.shortcuts[i], sizeof(source.shortcuts[i]), 1, f);
fwrite(&i, sizeof(i), 1, f);
}
}
/* Optional Section 2: Edit mode
The Hex Editor used to have a bug, it doesn't store the edit mode to
the preferences, which make the bookmarks outside NES memory are all
treated as NES memory bookmarks.
However, for the consideration of backward compatibility of the older
version of FCEUX, we can only add the extra data to the last of the file
to fix this problem.
*/
for (int i = 0; i < source.bookmarkCount; ++i)
if (fwrite(&source[i].editmode, sizeof(source[i].editmode), 1, f) != 1)
return 1;
return 0;
}
@ -348,48 +361,73 @@ int loadDebuggerPreferences(FILE* f)
* Loads HexView preferences from a file
*
* @param f File to write the preferences to
* @param target The target to load the preferences to
* @return 0 if everything went fine. An error code if something went wrong.
**/
int loadHexPreferences(FILE* f)
int loadHexPreferences(FILE* f, HexBookmarkList& target = hexBookmarks)
{
int i;
// Read number of bookmarks
if (fread(&nextBookmark, sizeof(nextBookmark), 1, f) != 1) return 1;
if (nextBookmark >= 64) return 1;
if (fread(&target.bookmarkCount, sizeof(target.bookmarkCount), 1, f) != 1) return 1;
if (target.bookmarkCount >= 64) return 1;
for (i=0;i<nextBookmark;i++)
// clean the garbage values
memset(&target.bookmarks, 0, sizeof(HexBookmark) * target.bookmarkCount);
for (i=0;i<target.bookmarkCount;i++)
{
unsigned int len;
// Read address
if (fread(&hexBookmarks[i].address, sizeof(hexBookmarks[i].address), 1, f) != 1) return 1;
if (fread(&target[i].address, sizeof(target[i].address), 1, f) != 1) return 1;
// Read length of description
if (fread(&len, sizeof(len), 1, f) != 1) return 1;
// Read the bookmark description
if (fread(hexBookmarks[i].description, 1, len, f) != len) return 1;
if (fread(target[i].description, 1, len, f) != len) return 1;
}
// optional section: read bookmark shortcut matches
// read number of shortcuts
// older versions of .deb file don't have this section, so the file would reach the end.
if (fread(&numHexBookmarkShortcut, sizeof(numHexBookmarkShortcut), 1, f) != EOF)
/* Optional Section 1: read bookmark shortcut matches
read number of shortcuts
older versions of .deb file don't have this section, so the file would reach the end.
*/
if (!feof(f))
{
fread(&target.shortcutCount, sizeof(target.shortcutCount), 1, f);
unsigned int bookmark_index, shortcut_index;
// read the matching index list of the shortcuts
for (unsigned int i = 0; i < numHexBookmarkShortcut; ++i)
for (unsigned int i = 0; i < target.shortcutCount; ++i)
if (fread(&bookmark_index, sizeof(bookmark_index), 1, f) != EOF && fread(&shortcut_index, sizeof(shortcut_index), 1, f) != EOF)
hexBookmarkShortcut[shortcut_index % 10] = bookmark_index;
target.shortcuts[shortcut_index % 10] = bookmark_index;
else
break;
}
else {
// use the default configruation based on the order of the bookmark list
numHexBookmarkShortcut = nextBookmark > 10 ? 10 : nextBookmark;
for (int i = 0; i < numHexBookmarkShortcut; ++i)
hexBookmarkShortcut[i] = i;
target.shortcutCount = target.bookmarkCount > 10 ? 10 : target.bookmarkCount;
for (int i = 0; i < target.shortcutCount; ++i)
target.shortcuts[i] = i;
}
/*
Optional Section 2: Edit mode
The Hex Editor used to have a bug, it doesn't store the edit mode to
the preferences, which make the bookmarks outside NES memory are all
treated as NES memory bookmarks.
However, for the consideration of backward compatibility of the older
version of FCEUX, we can only add the extra data to the last of the file
to fix this problem.
*/
int editmode;
if (!feof(f))
for (int i = 0; i < target.bookmarkCount; i++)
{
if (fread(&editmode, sizeof(editmode), 1, f) != EOF)
target[i].editmode = editmode;
else break;
}
return 0;
}
@ -429,7 +467,7 @@ int loadPreferences(const char* romname)
myNumWPs = 0;
break_on_instructions = break_on_cycles = FCEUI_Debugger().badopbreak = false;
break_instructions_limit = break_cycles_limit = 0;
nextBookmark = 0;
hexBookmarks.bookmarkCount = 0;
}
fclose(f);
} else

View File

@ -1659,6 +1659,16 @@ void SeparatorCache::Init(HWND hBox)
GetObject((HANDLE)SendMessage(hBox, WM_GETFONT, NULL, NULL), sizeof(logFont), &logFont);
sepFon = (HFONT)CreateFontIndirect((logFont.lfWeight = FW_SEMIBOLD, &logFont));
}
// if watches exists before separator cache initialize,
// recalculate their values as they are porbably incorrect.
if (WatchCount)
{
separatorCache.clear();
for (int i = 0; i < WatchCount; ++i)
if (rswatches[i].Type == 'S')
separatorCache[i] = SeparatorCache(RamWatchHWnd, rswatches[i].comment);
}
}
void SeparatorCache::DeInit()
@ -1670,6 +1680,8 @@ void SeparatorCache::DeInit()
sepPen = NULL;
sepPenSel = NULL;
sepFon = NULL;
separatorCache.clear();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by res.rc
// Microsoft Visual C++ 生成的包含文件。
// 供 res.rc 使用
//
#define CLOSE_BUTTON 1
#define BUTTON_CLOSE 1
@ -161,7 +161,7 @@
#define IDC_CHECK_CODE_TABBING 117
#define CHEAT_CONTEXT_LIST_POKECHEATVALUE 118
#define IDC_CHECK_LOG_STATUSES_TO_THE_LEFT 118
#define IDC_DEBUGGER_BOOKMARK_NAME 118
#define IDC_DEBUGGER_BOOKMARK_EDIT 118
#define CHEAT_CONTEXT_LIST_GOTOINHEXEDITOR 119
#define IDC_DEBUGGER_BREAK_ON_INSTRUCTIONS 119
#define IDC_CHECK_LOG_FRAMES_COUNT 119
@ -514,22 +514,33 @@
#define MW_VAL04 1014
#define MW_NAME05 1015
#define MW_ADDR05 1016
#define IDC_EDIT_SHORTCUT0 1016
#define MW_VAL05 1017
#define IDC_EDIT_SHORTCUT1 1017
#define IDC_PRGROM_COMBO 1018
#define MW_NAME06 1018
#define IDC_EDIT_SHORTCUT2 1018
#define MW_ADDR06 1019
#define IDC_CHRROM_COMBO 1019
#define IDC_EDIT_SHORTCUT7 1019
#define IDC_RADIO_MIRR_HORIZONTAL 1020
#define MW_VAL06 1020
#define IDC_EDIT_SHORTCUT6 1020
#define IDC_RADIO_MIRR_VERTICAL 1021
#define MW_NAME07 1021
#define IDC_EDIT6 1021
#define IDC_EDIT_SHORTCUT9 1021
#define MW_ADDR07 1022
#define IDC_RADIO_MIRR_4SCREEN 1022
#define IDC_EDIT_SHORTCUT5 1022
#define MW_VAL07 1023
#define IDC_EDIT_SHORTCUT4 1023
#define IDC_CHECK_TRAINER 1024
#define MW_NAME08 1024
#define IDC_EDIT_SHORTCUT8 1024
#define MW_ADDR08 1025
#define IDC_PRGRAM_COMBO 1025
#define IDC_EDIT_SHORTCUT3 1025
#define IDC_MAPPER_COMBO 1026
#define MW_VAL08 1026
#define IDC_SUBMAPPER_EDIT 1027
@ -625,12 +636,10 @@
#define IDC_MISCELLANEOUS_ROMS_EDIT 1087
#define IDC_EXTEND_SYSTEM_GROUP 1089
#define IDC_EXTEND_SYSTEM_TEXT 1090
#define IDC_BUTTON1 1094
#define IDC_CHEAT_SWITCH 1096
#define IDC_CHEAT_GLOBAL_SWITCH 1096
#define IDC_GAME_GENIE_LABEL 1097
#define IDC_CHEAT_GAME_GENIE_TEXT 1098
#define IDC_CHECK2 1099
#define IDC_RADIO_SHORTCUT1 1100
#define IDC_RADIO_SHORTCUT2 1101
#define IDC_RADIO_SHORTCUT3 1102
@ -641,17 +650,31 @@
#define IDC_RADIO_SHORTCUT8 1107
#define IDC_RADIO_SHORTCUT9 1108
#define IDC_RADIO_SHORTCUT0 1109
#define IDC_BOOKMARK_VIEW_TEXT 1110
#define IDC_BOOKMARK_COMBO_VIEW 1112
#define IDC_CHEAT_SHOWGG 1112
#define IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD 1114
#define IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE 1115
#define IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE 1116
#define BTN_ALLOW_LRUD 1117
#define IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE 1117
#define IDC_PRGROM_EDIT 1118
#define IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN 1118
#define IDC_CHRROM_EDIT 1119
#define BTN_PRESET_SET1 1119
#define IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP 1119
#define BTN_PRESET_SET2 1120
#define BTN_PRESET_SET3 1121
#define IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT 1121
#define BTN_PRESET_IMPORT1 1122
#define IDC_TEXT_BOOKMARKIMPORTOPTION 1122
#define BTN_PRESET_IMPORT2 1123
#define IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK 1123
#define BTN_PRESET_IMPORT3 1124
#define IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT 1124
#define IDC_PRGRAM_EDIT 1125
#define BTN_PRESET_EXPORT1 1125
#define IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT 1125
#define BTN_PRESET_EXPORT2 1126
#define BTN_PRESET_EXPORT3 1127
#define IDC_CHRRAM_EDIT 1128
@ -664,6 +687,7 @@
#define TASEDITOR_REWIND 1133
#define TASEDITOR_FORWARD 1134
#define TASEDITOR_REWIND_FULL 1135
#define IDC_EDIT10 1135
#define TASEDITOR_FORWARD_FULL 1136
#define TASEDITOR_PLAYSTOP 1137
#define IDC_RADIO_GREENZONE_SAVINGMODE_ALLFRAMES 1138
@ -868,6 +892,10 @@
#define IDC_GAME_GENIE_ADDR 1501
#define MENU_INESHEADEREDITOR 40001
#define MENU_INPUT_BARCODE 40004
#define ID_BOOKMARKS_IMPORT 40005
#define ID_BOOKMARKS_SAVEAS 40006
#define ID_BOOKMARKS_OPTION 40007
#define ID_BOOKMARKS_EXPORT 40008
#define MENU_NETWORK 40040
#define MENU_PALETTE 40041
#define MENU_SOUND 40042
@ -1163,9 +1191,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 306
#define _APS_NEXT_COMMAND_VALUE 40005
#define _APS_NEXT_CONTROL_VALUE 1101
#define _APS_NEXT_RESOURCE_VALUE 311
#define _APS_NEXT_COMMAND_VALUE 40009
#define _APS_NEXT_CONTROL_VALUE 1017
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -3374,7 +3374,6 @@ bool inline (*GetIsLetterLegal(UINT id))(char letter)
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

View File

@ -1201,6 +1201,7 @@ bool FCEU_IsValidUI(EFCEUI ui) {
case FCEUI_CLOSEGAME:
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR)) return false;
break;
case FCEUI_RECORDMOVIE:
case FCEUI_PLAYMOVIE:
case FCEUI_QUICKSAVE:
@ -1216,13 +1217,13 @@ bool FCEU_IsValidUI(EFCEUI ui) {
case FCEUI_STOPMOVIE:
case FCEUI_TOGGLERECORDINGMOVIE:
return(FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_FINISHED));
return FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_FINISHED);
case FCEUI_PLAYFROMBEGINNING:
return(FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_TASEDITOR | MOVIEMODE_FINISHED));
return FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD | MOVIEMODE_TASEDITOR | MOVIEMODE_FINISHED);
case FCEUI_TRUNCATEMOVIE:
return(FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD));
return FCEUMOV_Mode(MOVIEMODE_PLAY | MOVIEMODE_RECORD);
case FCEUI_STOPAVI:
return FCEUI_AviIsRecording();
@ -1243,7 +1244,12 @@ bool FCEU_IsValidUI(EFCEUI ui) {
#endif
if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false;
break;
case FCEUI_INPUT_BARCODE:
if (!GameInfo) return false;
if (!FCEUMOV_Mode(MOVIEMODE_INACTIVE)) return false;
}
return true;
}