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] == '\\') ) if ( (filepath[i] == '/') || (filepath[i] == '\\') )
{ {
j = i; j = i+1;
} }
i++; i++;
} }

View File

@ -12,6 +12,8 @@
#include <QMenuBar> #include <QMenuBar>
#include <QFileDialog> #include <QFileDialog>
#include <QColorDialog> #include <QColorDialog>
#include <QInputDialog>
#include <QMessageBox>
#include "../../types.h" #include "../../types.h"
#include "../../fceu.h" #include "../../fceu.h"
@ -35,6 +37,9 @@
#include "Qt/HexEditor.h" #include "Qt/HexEditor.h"
#include "Qt/ConsoleUtilities.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 ) 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) HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
: QDialog( parent ) : QDialog( parent )
{ {
@ -425,8 +675,6 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
// Bookmarks Menu // Bookmarks Menu
bookmarkMenu = menuBar->addMenu(tr("Bookmarks")); bookmarkMenu = menuBar->addMenu(tr("Bookmarks"));
populateBookmarkMenu();
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// Menu End // Menu End
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
@ -464,28 +712,81 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
connect( periodicTimer, &QTimer::timeout, this, &HexEditorDialog_t::updatePeriodic ); connect( periodicTimer, &QTimer::timeout, this, &HexEditorDialog_t::updatePeriodic );
periodicTimer->start( 100 ); // 10hz periodicTimer->start( 100 ); // 10hz
winList.push_back(this);
populateBookmarkMenu();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
HexEditorDialog_t::~HexEditorDialog_t(void) HexEditorDialog_t::~HexEditorDialog_t(void)
{ {
std::list <HexEditorDialog_t*>::iterator it;
printf("Hex Editor Deleted\n"); printf("Hex Editor Deleted\n");
periodicTimer->stop(); 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) void HexEditorDialog_t::populateBookmarkMenu(void)
{ {
QAction *act; QAction *act;
HexBookMarkMenuAction *hAct;
bookmarkMenu->clear(); bookmarkMenu->clear();
// Bookmarks -> Remove All Bookmarks // 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->setShortcuts(QKeySequence::Open);
act->setStatusTip(tr("Remove All Bookmarks")); 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->addAction(act);
bookmarkMenu->addSeparator(); 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) void HexEditorDialog_t::closeEvent(QCloseEvent *event)
@ -654,6 +955,7 @@ QHexEdit::QHexEdit(QWidget *parent)
{ {
QPalette pal; QPalette pal;
this->parent = (HexEditorDialog_t*)parent;
this->setFocusPolicy(Qt::StrongFocus); this->setFocusPolicy(Qt::StrongFocus);
font.setFamily("Courier New"); font.setFamily("Courier New");
@ -821,6 +1123,8 @@ void QHexEdit::setAddr( int newAddr )
cursorPosX = 2*((newAddr - addr)%16); cursorPosX = 2*((newAddr - addr)%16);
cursorPosY = (newAddr - addr)/16; cursorPosY = (newAddr - addr)/16;
vbar->setValue( lineOffset );
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void QHexEdit::setHorzScroll( int value ) void QHexEdit::setHorzScroll( int value )
@ -1205,7 +1509,7 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
int addr; int addr;
char stmp[128]; char stmp[128];
addr = convPixToAddr( event->pos() ); ctxAddr = addr = convPixToAddr( event->pos() );
//printf("contextMenuEvent\n"); //printf("contextMenuEvent\n");
switch ( viewMode ) 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); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
} }
break; break;
case MODE_NES_PPU: case MODE_NES_PPU:
{ {
act = new QAction(tr("TODO Add Bookmark"), this); act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
} }
break; break;
case MODE_NES_OAM: case MODE_NES_OAM:
{ {
act = new QAction(tr("TODO Add Bookmark"), this); act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
} }
break; break;
case MODE_NES_ROM: case MODE_NES_ROM:
{ {
act = new QAction(tr("TODO Add Bookmark"), this); act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
} }
break; 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) void QHexEdit::jumpToROM(void)
{ {
setMode( MODE_NES_ROM ); 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 #pragma once
#include <list>
#include <vector>
#include <QWidget> #include <QWidget>
#include <QDialog> #include <QDialog>
#include <QTimer> #include <QTimer>
#include <QAction>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QComboBox> #include <QComboBox>
@ -42,6 +46,54 @@ struct memBlock_t
int (*memAccessFunc)( unsigned int offset); 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 class QHexEdit : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -93,6 +145,8 @@ class QHexEdit : public QWidget
QColor highLightColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ]; QColor highLightColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ];
QColor rvActvTextColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ]; QColor rvActvTextColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ];
HexEditorDialog_t *parent;
uint64_t total_instructions_lp; uint64_t total_instructions_lp;
int viewMode; int viewMode;
@ -119,6 +173,7 @@ class QHexEdit : public QWidget
int editValue; int editValue;
int editMask; int editMask;
int jumpToRomValue; int jumpToRomValue;
int ctxAddr;
bool cursorBlink; bool cursorBlink;
bool reverseVideo; bool reverseVideo;
@ -126,6 +181,7 @@ class QHexEdit : public QWidget
private slots: private slots:
void jumpToROM(void); void jumpToROM(void);
void addBookMarkCB(void);
}; };
@ -137,11 +193,11 @@ class HexEditorDialog_t : public QDialog
HexEditorDialog_t(QWidget *parent = 0); HexEditorDialog_t(QWidget *parent = 0);
~HexEditorDialog_t(void); ~HexEditorDialog_t(void);
protected:
void closeEvent(QCloseEvent *bar);
void gotoAddress(int newAddr); void gotoAddress(int newAddr);
void populateBookmarkMenu(void); void populateBookmarkMenu(void);
protected:
void closeEvent(QCloseEvent *bar);
QScrollBar *vbar; QScrollBar *vbar;
QScrollBar *hbar; QScrollBar *hbar;
@ -168,4 +224,8 @@ class HexEditorDialog_t : public QDialog
void actvHighlightRVCB(bool value); void actvHighlightRVCB(bool value);
void pickForeGroundColor(void); void pickForeGroundColor(void);
void pickBackGroundColor(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/sdl-video.h"
#include "Qt/nes_shm.h" #include "Qt/nes_shm.h"
#include "Qt/unix-netplay.h" #include "Qt/unix-netplay.h"
#include "Qt/HexEditor.h"
#include "Qt/ConsoleWindow.h" #include "Qt/ConsoleWindow.h"
#include "Qt/fceux_git_info.h" #include "Qt/fceux_git_info.h"
@ -231,6 +232,8 @@ int LoadGame(const char *path)
return 0; return 0;
} }
hexEditorLoadBookmarks();
int state_to_load; int state_to_load;
g_config->getOption("SDL.AutoLoadState", &state_to_load); g_config->getOption("SDL.AutoLoadState", &state_to_load);
if (state_to_load >= 0 && state_to_load < 10){ if (state_to_load >= 0 && state_to_load < 10){
@ -277,6 +280,7 @@ CloseGame(void)
if(!isloaded) { if(!isloaded) {
return(0); return(0);
} }
hexEditorSaveBookmarks();
int state_to_save; int state_to_save;
g_config->getOption("SDL.AutoSaveState", &state_to_save); g_config->getOption("SDL.AutoSaveState", &state_to_save);

View File

@ -59,37 +59,23 @@
</div> </div>
<div id="page_content"> <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> <p>
first, install the prerequisites.<p> Qt5, SDL2, minizip, and zlib
<p> <p>
macports requires these prerequisites: scons, libsdl, zenity, lua, gtk2<p> If you are attempting to use the appveyor pipeline autobuild of fceux, you must install these
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> dependencies via the home brew package management tool. The following commands will install
<p> the necessary dependencies to run the autobuild:
Building instructions for fink:<p> <pre>
<p> brew install qt5
CFLAGS=-I/sw/include LDFLAGS=-L/sw/lib scons<p> brew install sdl2
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> brew install minizip
CFLAGS="-I/sw/include -arch i386" LDFLAGS="-L/sw/lib -arch i386" scons<p> </pre>
<p> If you are attempting to compile fceux, you can either install the dependencies via home brew
None of the modifications listed at the paperkettle URL were necessary in our latest fink test only 18-jul-2010<p> or you can install the dmg packages available from the Qt and SDL websites. The cmake and make
<p> build tools are required to compile fceux. See the README file in the root directory of the
This URL is a little old, but he got FCEUX compiling via fink<p> project for build instructions. You can also look at what is being done in the ./pipelines/macOS_build.sh
http://beesbuzz.biz/blog/e/2009/04/14-how_to_build_fceux_for_mac_os_x.php<p> script if you wish to build fceux in the same way the autobuild does.
<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>
</div> </div>
</div> </div>