Merge pull request #168 from mjbudd77/master

SDL Qt5 GUI Hex Editor Bookmark Functionality
This commit is contained in:
mjbudd77 2020-08-28 22:24:56 -04:00 committed by GitHub
commit 6d88d3df4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 466 additions and 43 deletions

View File

@ -59,7 +59,7 @@ int getFileBaseName( const char *filepath, char *base )
{
if ( (filepath[i] == '/') || (filepath[i] == '\\') )
{
j = i;
j = i+1;
}
i++;
}

View File

@ -12,6 +12,8 @@
#include <QMenuBar>
#include <QFileDialog>
#include <QColorDialog>
#include <QInputDialog>
#include <QMessageBox>
#include "../../types.h"
#include "../../fceu.h"
@ -35,6 +37,9 @@
#include "Qt/HexEditor.h"
#include "Qt/ConsoleUtilities.h"
static HexBookMarkManager_t hbm;
static std::list <HexEditorDialog_t*> winList;
static const char *memViewNames[] = { "RAM", "PPU", "OAM", "ROM", NULL };
//----------------------------------------------------------------------------
static int getRAM( unsigned int i )
{
@ -279,6 +284,251 @@ void memBlock_t::init(void)
}
}
//----------------------------------------------------------------------------
HexBookMark::HexBookMark(void)
{
addr = 0;
mode = 0;
desc[0] = 0;
}
//----------------------------------------------------------------------------
HexBookMark::~HexBookMark(void)
{
}
//----------------------------------------------------------------------------
HexBookMarkManager_t::HexBookMarkManager_t(void)
{
}
//----------------------------------------------------------------------------
HexBookMarkManager_t::~HexBookMarkManager_t(void)
{
removeAll();
}
//----------------------------------------------------------------------------
void HexBookMarkManager_t::removeAll(void)
{
HexBookMark *b;
while ( !ls.empty() )
{
b = ls.front();
delete b;
ls.pop_front();
}
v.clear();
}
//----------------------------------------------------------------------------
int HexBookMarkManager_t::addBookMark( int addr, int mode, const char *desc )
{
HexBookMark *b;
b = new HexBookMark();
b->addr = addr;
b->mode = mode;
if ( desc )
{
strncpy( b->desc, desc, 63 );
}
b->desc[63] = 0;
ls.push_back(b);
updateVector();
return 0;
}
//----------------------------------------------------------------------------
void HexBookMarkManager_t::updateVector(void)
{
std::list <HexBookMark*>::iterator it;
v.clear();
for (it=ls.begin(); it!=ls.end(); it++)
{
v.push_back( *it );
}
return;
}
//----------------------------------------------------------------------------
int HexBookMarkManager_t::size(void)
{
return ls.size();
}
//----------------------------------------------------------------------------
HexBookMark *HexBookMarkManager_t::getBookMark( int index )
{
if ( index < 0 )
{
return NULL;
}
else if ( index >= (int)v.size() )
{
return NULL;
}
return v[index];
}
//----------------------------------------------------------------------------
int HexBookMarkManager_t::loadFromFile(void)
{
int i,j,mode,addr;
FILE *fp;
QDir dir;
char line[256], fd[256], baseFile[512];
const char *romFile = getRomFile();
const char *baseDir = FCEUI_GetBaseDirectory();
std::string path;
if ( romFile == NULL )
{
return -1;
}
path = std::string(baseDir) + "/bookmarks/";
dir.mkpath( QString::fromStdString(path) );
getFileBaseName( romFile, baseFile );
path += std::string(baseFile) + ".txt";
fp = ::fopen( path.c_str(), "r");
if ( fp == NULL )
{
return -1;
}
while ( ::fgets( line, sizeof(line), fp ) != NULL )
{
i=0; j=0;
//printf("%s\n", line );
//
while ( isspace(line[i]) ) i++;
while ( isalpha(line[i]) )
{
fd[j] = line[i]; i++; j++;
}
fd[j] = 0;
mode = -1;
for (j=0; j<4; j++)
{
if ( strcmp( fd, memViewNames[j] ) == 0 )
{
mode = j; break;
}
}
if ( mode < 0 ) continue;
while ( isspace(line[i]) ) i++;
if ( line[i] == ':' ) i++;
while ( isspace(line[i]) ) i++;
j=0;
while ( isxdigit(line[i]) )
{
fd[j] = line[i]; i++; j++;
}
fd[j] = 0;
addr = strtol( fd, NULL, 16 );
while ( isspace(line[i]) ) i++;
if ( line[i] == ':' ) i++;
while ( isspace(line[i]) ) i++;
j=0;
while ( line[i] )
{
fd[j] = line[i]; i++; j++;
}
fd[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( fd[j] ) )
{
fd[j] = 0;
}
else
{
break;
}
j--;
}
addBookMark( addr, mode, fd );
}
::fclose(fp);
return 0;
}
//----------------------------------------------------------------------------
int HexBookMarkManager_t::saveToFile(void)
{
FILE *fp;
QDir dir;
char baseFile[512];
const char *romFile = getRomFile();
const char *baseDir = FCEUI_GetBaseDirectory();
std::string path;
if ( romFile == NULL )
{
return -1;
}
path = std::string(baseDir) + "/bookmarks/";
dir.mkpath( QString::fromStdString(path) );
getFileBaseName( romFile, baseFile );
path += std::string(baseFile) + ".txt";
fp = ::fopen( path.c_str(), "w");
if ( fp == NULL )
{
return -1;
}
for (int i=0; i<v.size(); i++)
{
fprintf( fp, "%s:%08X:%s\n",
memViewNames[ v[i]->mode ], v[i]->addr, v[i]->desc );
}
::fclose(fp);
return 0;
}
//----------------------------------------------------------------------------
HexBookMarkMenuAction::HexBookMarkMenuAction(QString desc, QWidget *parent)
: QAction( desc, parent )
{
bm = NULL; qedit = NULL;
}
//----------------------------------------------------------------------------
HexBookMarkMenuAction::~HexBookMarkMenuAction(void)
{
//printf("Hex Bookmark Menu Action Deleted\n");
}
//----------------------------------------------------------------------------
void HexBookMarkMenuAction::activateCB(void)
{
//printf("Activate Bookmark: %p \n", bm );
qedit->setMode( bm->mode );
qedit->setAddr( bm->addr );
}
//----------------------------------------------------------------------------
HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
: QDialog( parent )
{
@ -425,8 +675,6 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
// Bookmarks Menu
bookmarkMenu = menuBar->addMenu(tr("Bookmarks"));
populateBookmarkMenu();
//-----------------------------------------------------------------------
// Menu End
//-----------------------------------------------------------------------
@ -464,28 +712,81 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
connect( periodicTimer, &QTimer::timeout, this, &HexEditorDialog_t::updatePeriodic );
periodicTimer->start( 100 ); // 10hz
winList.push_back(this);
populateBookmarkMenu();
}
//----------------------------------------------------------------------------
HexEditorDialog_t::~HexEditorDialog_t(void)
{
std::list <HexEditorDialog_t*>::iterator it;
printf("Hex Editor Deleted\n");
periodicTimer->stop();
for (it = winList.begin(); it != winList.end(); it++)
{
if ( (*it) == this )
{
winList.erase(it);
//printf("Removing Hex Edit Window\n");
break;
}
}
}
//----------------------------------------------------------------------------
void HexEditorDialog_t::removeAllBookmarks(void)
{
int ret;
QMessageBox mbox(this);
mbox.setWindowTitle( tr("Bookmarks") );
mbox.setText( tr("Remove All Bookmarks?") );
mbox.setIcon( QMessageBox::Question );
mbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok );
ret = mbox.exec();
//printf("Ret: %i \n", ret );
if ( ret == QMessageBox::Ok )
{
hbm.removeAll();
populateBookmarkMenu();
}
}
//----------------------------------------------------------------------------
void HexEditorDialog_t::populateBookmarkMenu(void)
{
QAction *act;
HexBookMarkMenuAction *hAct;
bookmarkMenu->clear();
// Bookmarks -> Remove All Bookmarks
act = new QAction(tr("Remove All Bookmarks"), this);
act = new QAction(tr("Remove All Bookmarks"), bookmarkMenu);
//act->setShortcuts(QKeySequence::Open);
act->setStatusTip(tr("Remove All Bookmarks"));
//connect(act, SIGNAL(triggered(void)), this, SLOT(pickBackGroundColor(void)) );
connect(act, SIGNAL(triggered(void)), this, SLOT(removeAllBookmarks(void)) );
bookmarkMenu->addAction(act);
bookmarkMenu->addSeparator();
for (int i=0; i<hbm.size(); i++)
{
HexBookMark *b = hbm.getBookMark(i);
if ( b )
{
//printf("%p %p \n", b, editor );
hAct = new HexBookMarkMenuAction(tr(b->desc), bookmarkMenu);
bookmarkMenu->addAction(hAct);
hAct->bm = b; hAct->qedit = editor;
connect(hAct, SIGNAL(triggered(void)), hAct, SLOT(activateCB(void)) );
}
}
}
//----------------------------------------------------------------------------
void HexEditorDialog_t::closeEvent(QCloseEvent *event)
@ -654,6 +955,7 @@ QHexEdit::QHexEdit(QWidget *parent)
{
QPalette pal;
this->parent = (HexEditorDialog_t*)parent;
this->setFocusPolicy(Qt::StrongFocus);
font.setFamily("Courier New");
@ -821,6 +1123,8 @@ void QHexEdit::setAddr( int newAddr )
cursorPosX = 2*((newAddr - addr)%16);
cursorPosY = (newAddr - addr)/16;
vbar->setValue( lineOffset );
}
//----------------------------------------------------------------------------
void QHexEdit::setHorzScroll( int value )
@ -1205,7 +1509,7 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
int addr;
char stmp[128];
addr = convPixToAddr( event->pos() );
ctxAddr = addr = convPixToAddr( event->pos() );
//printf("contextMenuEvent\n");
switch ( viewMode )
@ -1241,26 +1545,30 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
}
}
act = new QAction(tr("TODO Add Bookmark"), this);
act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
}
break;
case MODE_NES_PPU:
{
act = new QAction(tr("TODO Add Bookmark"), this);
act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
}
break;
case MODE_NES_OAM:
{
act = new QAction(tr("TODO Add Bookmark"), this);
act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
}
break;
case MODE_NES_ROM:
{
act = new QAction(tr("TODO Add Bookmark"), this);
act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
}
break;
}
@ -1269,6 +1577,44 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
}
//----------------------------------------------------------------------------
void QHexEdit::addBookMarkCB(void)
{
int ret;
char stmp[64];
QInputDialog dialog(this);
switch ( viewMode )
{
default:
case MODE_NES_RAM:
sprintf( stmp, "RAM %04X", ctxAddr );
break;
case MODE_NES_PPU:
sprintf( stmp, "PPU %04X", ctxAddr );
break;
case MODE_NES_OAM:
sprintf( stmp, "OAM %04X", ctxAddr );
break;
case MODE_NES_ROM:
sprintf( stmp, "ROM %04X", ctxAddr );
break;
}
dialog.setWindowTitle( tr("Add Bookmark") );
dialog.setLabelText( tr("Specify New Bookmark Description") );
dialog.setOkButtonText( tr("Add") );
dialog.setTextValue( tr(stmp) );
dialog.show();
ret = dialog.exec();
if ( QDialog::Accepted == ret )
{
hbm.addBookMark( ctxAddr, viewMode, dialog.textValue().toStdString().c_str() );
parent->populateBookmarkMenu();
}
}
//----------------------------------------------------------------------------
void QHexEdit::jumpToROM(void)
{
setMode( MODE_NES_ROM );
@ -1531,3 +1877,30 @@ void QHexEdit::paintEvent(QPaintEvent *event)
}
//----------------------------------------------------------------------------
void hexEditorLoadBookmarks(void)
{
std::list <HexEditorDialog_t*>::iterator it;
hbm.removeAll();
hbm.loadFromFile();
for (it = winList.begin(); it != winList.end(); it++)
{
(*it)->populateBookmarkMenu();
}
}
//----------------------------------------------------------------------------
void hexEditorSaveBookmarks(void)
{
std::list <HexEditorDialog_t*>::iterator it;
printf("Save Bookmarks\n");
hbm.saveToFile();
hbm.removeAll();
for (it = winList.begin(); it != winList.end(); it++)
{
(*it)->populateBookmarkMenu();
}
}
//----------------------------------------------------------------------------

View File

@ -3,9 +3,13 @@
#pragma once
#include <list>
#include <vector>
#include <QWidget>
#include <QDialog>
#include <QTimer>
#include <QAction>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
@ -42,6 +46,54 @@ struct memBlock_t
int (*memAccessFunc)( unsigned int offset);
};
class HexBookMark
{
public:
HexBookMark(void);
~HexBookMark(void);
int addr;
int mode;
char desc[64];
};
class HexBookMarkManager_t
{
public:
HexBookMarkManager_t(void);
~HexBookMarkManager_t(void);
void removeAll(void);
int addBookMark( int addr, int mode, const char *desc );
int size(void);
HexBookMark *getBookMark( int index );
int saveToFile(void);
int loadFromFile(void);
private:
void updateVector(void);
std::list <HexBookMark*> ls;
std::vector <HexBookMark*> v;
};
class QHexEdit;
class HexBookMarkMenuAction : public QAction
{
Q_OBJECT
public:
HexBookMarkMenuAction( QString desc, QWidget *parent = 0);
~HexBookMarkMenuAction(void);
QHexEdit *qedit;
HexBookMark *bm;
public slots:
void activateCB(void);
};
class HexEditorDialog_t;
class QHexEdit : public QWidget
{
Q_OBJECT
@ -93,6 +145,8 @@ class QHexEdit : public QWidget
QColor highLightColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ];
QColor rvActvTextColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ];
HexEditorDialog_t *parent;
uint64_t total_instructions_lp;
int viewMode;
@ -119,6 +173,7 @@ class QHexEdit : public QWidget
int editValue;
int editMask;
int jumpToRomValue;
int ctxAddr;
bool cursorBlink;
bool reverseVideo;
@ -126,6 +181,7 @@ class QHexEdit : public QWidget
private slots:
void jumpToROM(void);
void addBookMarkCB(void);
};
@ -137,11 +193,11 @@ class HexEditorDialog_t : public QDialog
HexEditorDialog_t(QWidget *parent = 0);
~HexEditorDialog_t(void);
protected:
void closeEvent(QCloseEvent *bar);
void gotoAddress(int newAddr);
void populateBookmarkMenu(void);
protected:
void closeEvent(QCloseEvent *bar);
QScrollBar *vbar;
QScrollBar *hbar;
@ -168,4 +224,8 @@ class HexEditorDialog_t : public QDialog
void actvHighlightRVCB(bool value);
void pickForeGroundColor(void);
void pickBackGroundColor(void);
void removeAllBookmarks(void);
};
void hexEditorLoadBookmarks(void);
void hexEditorSaveBookmarks(void);

View File

@ -14,6 +14,7 @@
#include "Qt/sdl-video.h"
#include "Qt/nes_shm.h"
#include "Qt/unix-netplay.h"
#include "Qt/HexEditor.h"
#include "Qt/ConsoleWindow.h"
#include "Qt/fceux_git_info.h"
@ -231,6 +232,8 @@ int LoadGame(const char *path)
return 0;
}
hexEditorLoadBookmarks();
int state_to_load;
g_config->getOption("SDL.AutoLoadState", &state_to_load);
if (state_to_load >= 0 && state_to_load < 10){
@ -277,6 +280,7 @@ CloseGame(void)
if(!isloaded) {
return(0);
}
hexEditorSaveBookmarks();
int state_to_save;
g_config->getOption("SDL.AutoSaveState", &state_to_save);

View File

@ -59,37 +59,23 @@
</div>
<div id="page_content">
To compile FCEUX in osx, you must have fink or macports. The FCEUX developers recommend fink, since that's what they use, but then again, the only time they compile software on osx is when folks come nagging.<p>
To run FCEUX in Mac OSX, you must have the following library dependencies installed on your system:
<p>
first, install the prerequisites.<p>
Qt5, SDL2, minizip, and zlib
<p>
macports requires these prerequisites: scons, libsdl, zenity, lua, gtk2<p>
fink requires these prerequisites: try all the same ones as macports, but i know at least one of them is named gtk+2 instead. please report your results.<p>
<p>
Building instructions for fink:<p>
<p>
CFLAGS=-I/sw/include LDFLAGS=-L/sw/lib scons<p>
if you are getting link errors about 64bitness then your system is compiling fceux as 64bit but fink is providing i386 libraries. you need to force fceux to compile 32 bits:<p>
CFLAGS="-I/sw/include -arch i386" LDFLAGS="-L/sw/lib -arch i386" scons<p>
<p>
None of the modifications listed at the paperkettle URL were necessary in our latest fink test only 18-jul-2010<p>
<p>
This URL is a little old, but he got FCEUX compiling via fink<p>
http://beesbuzz.biz/blog/e/2009/04/14-how_to_build_fceux_for_mac_os_x.php<p>
<p>
Building instructions for macports:<p>
<p>
CFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib scons<p>
<p>
This URL is fresh, and he got FCEUX compiling via macports:<p>
http://www.paperkettle.com/blog/2010/07/17/fceux-2-14a-compiled-on-mac-osx-10-6/<p>
<p>
---<p>
<p>
At any given time while fooling around you may discover that scons begins behaving irrationally. To fix this, try deleting .sconsign.dblite which will clear out its memory of what has come before.<p>
<p>
To clean your scons build, issue the main scons build command as discussed above with the -c parameter<p>
If you are attempting to use the appveyor pipeline autobuild of fceux, you must install these
dependencies via the home brew package management tool. The following commands will install
the necessary dependencies to run the autobuild:
<pre>
brew install qt5
brew install sdl2
brew install minizip
</pre>
If you are attempting to compile fceux, you can either install the dependencies via home brew
or you can install the dmg packages available from the Qt and SDL websites. The cmake and make
build tools are required to compile fceux. See the README file in the root directory of the
project for build instructions. You can also look at what is being done in the ./pipelines/macOS_build.sh
script if you wish to build fceux in the same way the autobuild does.
</div>
</div>