Merge pull request #174 from mjbudd77/master

Qt/SDL Debugger Bookmark Update
This commit is contained in:
mjbudd77 2020-09-24 07:16:56 -04:00 committed by GitHub
commit e8bbb4fe0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 965 additions and 98 deletions

View File

@ -14,6 +14,7 @@
#include <QCloseEvent> #include <QCloseEvent>
#include <QGridLayout> #include <QGridLayout>
#include <QRadioButton> #include <QRadioButton>
#include <QInputDialog>
#include "../../types.h" #include "../../types.h"
#include "../../fceu.h" #include "../../fceu.h"
@ -37,6 +38,7 @@
#include "Qt/config.h" #include "Qt/config.h"
#include "Qt/nes_shm.h" #include "Qt/nes_shm.h"
#include "Qt/fceuWrapper.h" #include "Qt/fceuWrapper.h"
#include "Qt/HexEditor.h"
#include "Qt/ConsoleDebugger.h" #include "Qt/ConsoleDebugger.h"
#include "Qt/ConsoleUtilities.h" #include "Qt/ConsoleUtilities.h"
@ -44,6 +46,7 @@
extern int vblankScanLines; extern int vblankScanLines;
extern int vblankPixel; extern int vblankPixel;
debuggerBookmarkManager_t dbgBmMgr;
static std::list <ConsoleDebugger*> dbgWinList; static std::list <ConsoleDebugger*> dbgWinList;
static void DeleteBreak(int sel); static void DeleteBreak(int sel);
@ -361,6 +364,9 @@ ConsoleDebugger::ConsoleDebugger(QWidget *parent)
bmFrame = new QGroupBox( tr("Address Bookmarks") ); bmFrame = new QGroupBox( tr("Address Bookmarks") );
bmTree = new QTreeWidget(); bmTree = new QTreeWidget();
selBmAddr = new QLineEdit(); selBmAddr = new QLineEdit();
selBmAddrVal = 0;
connect( selBmAddr, SIGNAL(textChanged(const QString &)), this, SLOT(selBmAddrChanged(const QString &)));
bmTree->setColumnCount(2); bmTree->setColumnCount(2);
@ -379,19 +385,22 @@ ConsoleDebugger::ConsoleDebugger(QWidget *parent)
connect( bmTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), connect( bmTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
this, SLOT(bmItemClicked( QTreeWidgetItem*, int)) ); this, SLOT(bmItemClicked( QTreeWidgetItem*, int)) );
connect( bmTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
this, SLOT(bmItemDoubleClicked( QTreeWidgetItem*, int)) );
vbox->addWidget( selBmAddr ); vbox->addWidget( selBmAddr );
button = new QPushButton( tr("Add") ); button = new QPushButton( tr("Add") );
vbox->addWidget( button ); vbox->addWidget( button );
button->setEnabled(false); // TODO connect( button, SIGNAL(clicked(void)), this, SLOT(add_BM_CB(void)) );
button = new QPushButton( tr("Delete") ); button = new QPushButton( tr("Delete") );
vbox->addWidget( button ); vbox->addWidget( button );
button->setEnabled(false); // TODO connect( button, SIGNAL(clicked(void)), this, SLOT(delete_BM_CB(void)) );
button = new QPushButton( tr("Name") ); button = new QPushButton( tr("Name") );
vbox->addWidget( button ); vbox->addWidget( button );
button->setEnabled(false); // TODO connect( button, SIGNAL(clicked(void)), this, SLOT(edit_BM_CB(void)) );
hbox->addWidget( bmTree ); hbox->addWidget( bmTree );
hbox->addLayout( vbox ); hbox->addLayout( vbox );
@ -457,9 +466,13 @@ ConsoleDebugger::ConsoleDebugger(QWidget *parent)
connect( debFileChkBox , SIGNAL(stateChanged(int)), this, SLOT(debFileAutoLoadCB(int)) ); connect( debFileChkBox , SIGNAL(stateChanged(int)), this, SLOT(debFileAutoLoadCB(int)) );
button->setEnabled(false); // TODO button->setEnabled(false); // TODO
autoOpenChkBox->setEnabled(false); // TODO
//debFileChkBox->setEnabled(false); // TODO // IDA font is just a monospace font, we are forcing this anyway. It is just easier to read the assembly.
idaFontChkBox->setEnabled(false); // TODO // If a different font is desired, my thought is to open a QFontDialog and let the user pick a new font,
// rather than use a checkbox that selects between two. But for the moment, I have more important things
// to do.
idaFontChkBox->setEnabled(false);
idaFontChkBox->setChecked(true);
setLayout( mainLayout ); setLayout( mainLayout );
@ -556,12 +569,33 @@ void ConsoleDebugger::bpItemClicked( QTreeWidgetItem *item, int column)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ConsoleDebugger::bmItemClicked( QTreeWidgetItem *item, int column) void ConsoleDebugger::bmItemClicked( QTreeWidgetItem *item, int column)
{ {
int row = bmTree->indexOfTopLevelItem(item); //int row = bmTree->indexOfTopLevelItem(item);
printf("Row: %i Column: %i \n", row, column ); //printf("Row: %i Column: %i \n", row, column );
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ConsoleDebugger::bmItemDoubleClicked( QTreeWidgetItem *item, int column)
{
int addr, line;
//int row = bmTree->indexOfTopLevelItem(item);
//printf("Row: %i Column: %i \n", row, column );
addr = strtol( item->text(0).toStdString().c_str(), NULL, 16 );
line = asmView->getAsmLineFromAddr( addr );
asmView->setLine( line );
}
//----------------------------------------------------------------------------
void ConsoleDebugger::selBmAddrChanged(const QString &txt)
{
selBmAddrVal = strtol( txt.toStdString().c_str(), NULL, 16 );
//printf("selBmAddrVal = %04X\n", selBmAddrVal );
}
//----------------------------------------------------------------------------
void ConsoleDebugger::openBpEditWindow( int editIdx, watchpointinfo *wp ) void ConsoleDebugger::openBpEditWindow( int editIdx, watchpointinfo *wp )
{ {
int ret; int ret;
@ -1040,6 +1074,138 @@ void ConsoleDebugger::bpListUpdate( bool reset )
bpTree->viewport()->update(); bpTree->viewport()->update();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ConsoleDebugger::add_BM_CB(void)
{
dbgBmMgr.addBookmark( selBmAddrVal );
bmListUpdate(false);
}
//----------------------------------------------------------------------------
void ConsoleDebugger::edit_BM_CB(void)
{
int addr;
std::string s;
QTreeWidgetItem *item;
item = bmTree->currentItem();
if ( item == NULL )
{
printf( "No Item Selected\n");
return;
}
s = item->text(0).toStdString();
addr = strtol( s.c_str(), NULL, 16 );
edit_BM_name( addr );
}
//----------------------------------------------------------------------------
void ConsoleDebugger::delete_BM_CB(void)
{
int addr;
std::string s;
QTreeWidgetItem *item;
item = bmTree->currentItem();
if ( item == NULL )
{
printf( "No Item Selected\n");
return;
}
s = item->text(0).toStdString();
addr = strtol( s.c_str(), NULL, 16 );
dbgBmMgr.deleteBookmark( addr );
bmListUpdate(true);
}
//----------------------------------------------------------------------------
void ConsoleDebugger::edit_BM_name( int addr )
{
int ret;
debuggerBookmark_t *bm;
QInputDialog dialog(this);
char stmp[128];
bm = dbgBmMgr.getAddr( addr );
sprintf( stmp, "Specify Bookmark Name for %04X", addr );
dialog.setWindowTitle( tr("Edit Bookmark") );
dialog.setLabelText( tr(stmp) );
dialog.setOkButtonText( tr("Edit") );
if ( bm != NULL )
{
dialog.setTextValue( tr(bm->name.c_str()) );
}
dialog.show();
ret = dialog.exec();
if ( QDialog::Accepted == ret )
{
bm->name = dialog.textValue().toStdString();
bmListUpdate(false);
}
}
//----------------------------------------------------------------------------
void ConsoleDebugger::bmListUpdate( bool reset )
{
int i=0;
QTreeWidgetItem *item;
debuggerBookmark_t *bm;
char addrStr[32];
if ( reset )
{
bmTree->clear();
}
bm = dbgBmMgr.begin();
while ( bm != NULL )
{
if ( bmTree->topLevelItemCount() > i )
{
item = bmTree->topLevelItem(i);
}
else
{
item = NULL;
}
if ( item == NULL )
{
item = new QTreeWidgetItem();
bmTree->addTopLevelItem( item );
}
sprintf( addrStr, "%04X", bm->addr );
//item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsUserCheckable );
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemNeverHasChildren );
item->setFont( 0, font );
item->setFont( 1, font );
item->setText( 0, tr(addrStr));
item->setText( 1, tr(bm->name.c_str()) );
item->setTextAlignment( 0, Qt::AlignLeft);
item->setTextAlignment( 1, Qt::AlignLeft);
bm = dbgBmMgr.next(); i++;
}
bmTree->viewport()->update();
}
//----------------------------------------------------------------------------
void ConsoleDebugger::add_BP_CB(void) void ConsoleDebugger::add_BP_CB(void)
{ {
openBpEditWindow(-1); openBpEditWindow(-1);
@ -1428,6 +1594,48 @@ void ConsoleDebugger::asmViewCtxMenuAddBP(void)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ConsoleDebugger::asmViewCtxMenuAddBM(void)
{
int addr = asmView->getCtxMenuAddr();
dbgBmMgr.addBookmark( addr );
edit_BM_name( addr );
bmListUpdate(false);
}
//----------------------------------------------------------------------------
void ConsoleDebugger::asmViewCtxMenuOpenHexEdit(void)
{
int romAddr = -1;
int addr = asmView->getCtxMenuAddr();
if (addr >= 0x8000)
{
romAddr = GetNesFileAddress(addr);
}
if ( romAddr >= 0 )
{
hexEditorOpenFromDebugger( QHexEdit::MODE_NES_ROM, romAddr );
}
else
{
hexEditorOpenFromDebugger( QHexEdit::MODE_NES_RAM, addr );
}
}
//----------------------------------------------------------------------------
void ConsoleDebugger::setBookmarkSelectedAddress( int addr )
{
char stmp[32];
sprintf( stmp, "%04X", addr );
selBmAddr->setText( tr(stmp) );
selBmAddrVal = addr;
}
//----------------------------------------------------------------------------
void ConsoleDebugger::asmViewCtxMenuAddSym(void) void ConsoleDebugger::asmViewCtxMenuAddSym(void)
{ {
openDebugSymbolEditWindow( asmView->getCtxMenuAddr() ); openDebugSymbolEditWindow( asmView->getCtxMenuAddr() );
@ -2066,6 +2274,11 @@ void ConsoleDebugger::updateWindowData(void)
windowUpdateReq = false; windowUpdateReq = false;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ConsoleDebugger::queueUpdate(void)
{
windowUpdateReq = true;
}
//----------------------------------------------------------------------------
void ConsoleDebugger::updatePeriodic(void) void ConsoleDebugger::updatePeriodic(void)
{ {
//printf("Update Periodic\n"); //printf("Update Periodic\n");
@ -2094,6 +2307,12 @@ void ConsoleDebugger::updatePeriodic(void)
printf("Breakpoint Tree Update\n"); printf("Breakpoint Tree Update\n");
bpListUpdate( true ); bpListUpdate( true );
} }
if ( bmTree->topLevelItemCount() != dbgBmMgr.size() )
{
printf("Bookmark Tree Update\n");
bmListUpdate( true );
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ConsoleDebugger::breakPointNotify( int bpNum ) void ConsoleDebugger::breakPointNotify( int bpNum )
@ -2176,6 +2395,21 @@ void FCEUD_DebugBreakpoint( int bpNum )
fceuWrapperLock(); fceuWrapperLock();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool debuggerWindowIsOpen(void)
{
return (dbgWinList.size() > 0);
}
//----------------------------------------------------------------------------
void updateAllDebuggerWindows( void )
{
std::list <ConsoleDebugger*>::iterator it;
for (it=dbgWinList.begin(); it!=dbgWinList.end(); it++)
{
(*it)->queueUpdate();
}
}
//----------------------------------------------------------------------------
static int getGameDebugBreakpointFileName(char *filepath) static int getGameDebugBreakpointFileName(char *filepath)
{ {
int i,j; int i,j;
@ -2229,6 +2463,7 @@ void saveGameDebugBreakpoints(void)
FILE *fp; FILE *fp;
char stmp[512]; char stmp[512];
char flags[8]; char flags[8];
debuggerBookmark_t *bm;
// If no breakpoints are loaded, skip saving // If no breakpoints are loaded, skip saving
if ( numWPs == 0 ) if ( numWPs == 0 )
@ -2276,18 +2511,94 @@ void saveGameDebugBreakpoints(void)
(watchpoint[i].desc != NULL) ? watchpoint[i].desc : ""); (watchpoint[i].desc != NULL) ? watchpoint[i].desc : "");
} }
bm = dbgBmMgr.begin();
while ( bm != NULL )
{
fprintf( fp, "Bookmark: addr=%04X desc=\"%s\" \n", bm->addr, bm->name.c_str() );
bm = dbgBmMgr.next();
}
fclose(fp); fclose(fp);
return; return;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static int getKeyValuePair( int i, const char *stmp, char *id, char *data )
{
int j=0;
char literal=0;
id[0] = 0; data[0] = 0;
if ( stmp[i] == 0 ) return i;
while ( isspace(stmp[i]) ) i++;
j=0;
while ( isalnum(stmp[i]) )
{
id[j] = stmp[i]; j++; i++;
}
id[j] = 0;
if ( j == 0 )
{
return i;
}
if ( stmp[i] != '=' )
{
return i;
}
i++; j=0;
if ( stmp[i] == '\"' )
{
literal = 0;
i++;
while ( stmp[i] != 0 )
{
if ( literal )
{
data[j] = stmp[i]; i++; j++;
literal = 0;
}
else
{
if ( stmp[i] == '\\' )
{
literal = 1; i++;
}
else if ( stmp[i] == '\"' )
{
i++; break;
}
else
{
data[j] = stmp[i]; j++; i++;
}
}
}
data[j] = 0;
}
else
{
j=0;
while ( !isspace(stmp[i]) )
{
data[j] = stmp[i]; j++; i++;
}
data[j] = 0;
}
return i;
}
//----------------------------------------------------------------------------
void loadGameDebugBreakpoints(void) void loadGameDebugBreakpoints(void)
{ {
int i,j; int i,j;
FILE *fp; FILE *fp;
char stmp[512]; char stmp[512];
char id[64], data[128]; char id[64], data[128];
char literal;
// If no debug windows are open, skip loading breakpoints // If no debug windows are open, skip loading breakpoints
if ( dbgWinList.size() == 0 ) if ( dbgWinList.size() == 0 )
@ -2338,62 +2649,7 @@ void loadGameDebugBreakpoints(void)
while ( stmp[i] != 0 ) while ( stmp[i] != 0 )
{ {
while ( isspace(stmp[i]) ) i++; i = getKeyValuePair( i, stmp, id, data );
j=0;
while ( isalnum(stmp[i]) )
{
id[j] = stmp[i]; j++; i++;
}
id[j] = 0;
if ( j == 0 )
{
break;
}
if ( stmp[i] != '=' )
{
break;
}
i++; j=0;
if ( stmp[i] == '\"' )
{
literal = 0;
i++;
while ( stmp[i] != 0 )
{
if ( literal )
{
data[j] = stmp[i]; i++; j++;
literal = 0;
}
else
{
if ( stmp[i] == '\\' )
{
literal = 1; i++;
}
else if ( stmp[i] == '\"' )
{
i++; break;
}
else
{
data[j] = stmp[i]; j++; i++;
}
}
}
data[j] = 0;
}
else
{
j=0;
while ( !isspace(stmp[i]) )
{
data[j] = stmp[i]; j++; i++;
}
data[j] = 0;
}
//printf("ID:'%s' DATA:'%s' \n", id, data ); //printf("ID:'%s' DATA:'%s' \n", id, data );
@ -2452,6 +2708,37 @@ void loadGameDebugBreakpoints(void)
} }
} }
} }
else if ( strcmp( id, "Bookmark" ) == 0 )
{
int addr = -1;
char desc[256];
desc[0] = 0;
while ( stmp[i] != 0 )
{
i = getKeyValuePair( i, stmp, id, data );
//printf("ID:'%s' DATA:'%s' \n", id, data );
if ( strcmp( id, "addr" ) == 0 )
{
addr = strtol( data, NULL, 16 );
}
else if ( strcmp( id, "desc" ) == 0 )
{
strcpy( desc, data );
}
}
if ( addr >= 0 )
{
if ( dbgBmMgr.addBookmark( addr, desc ) )
{
printf("Error:Failed to add debug bookmark: $%04X '%s' \n", addr, desc );
}
}
}
} }
fclose(fp); fclose(fp);
@ -2715,17 +3002,19 @@ void QAsmView::mouseMoveEvent(QMouseEvent * event)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void QAsmView::mousePressEvent(QMouseEvent * event) void QAsmView::mousePressEvent(QMouseEvent * event)
{ {
//int line; int line;
//QPoint c = convPixToCursor( event->pos() ); QPoint c = convPixToCursor( event->pos() );
//line = lineOffset + c.y(); line = lineOffset + c.y();
//
//if ( line < asmEntry.size() )
//{
// int addr;
// addr = asmEntry[line]->addr; if ( line < asmEntry.size() )
//} {
int addr;
addr = asmEntry[line]->addr;
parent->setBookmarkSelectedAddress( addr );
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void QAsmView::contextMenuEvent(QContextMenuEvent *event) void QAsmView::contextMenuEvent(QContextMenuEvent *event)
@ -2749,10 +3038,17 @@ void QAsmView::contextMenuEvent(QContextMenuEvent *event)
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddBP(void)) ); connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddBP(void)) );
act = new QAction(tr("Add Symbolic Debug Name"), this); act = new QAction(tr("Add Symbolic Debug Marker"), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddSym(void)) ); connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddSym(void)) );
//connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
act = new QAction(tr("Add Bookmark"), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddBM(void)) );
act = new QAction(tr("Open Hex Editor"), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuOpenHexEdit(void)) );
menu.exec(event->globalPos()); menu.exec(event->globalPos());
} }
@ -2760,7 +3056,7 @@ void QAsmView::contextMenuEvent(QContextMenuEvent *event)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void QAsmView::paintEvent(QPaintEvent *event) void QAsmView::paintEvent(QPaintEvent *event)
{ {
int x,y,l, row, nrow; int x,y,l, row, nrow, selAddr;
QPainter painter(this); QPainter painter(this);
painter.setFont(font); painter.setFont(font);
@ -2792,6 +3088,7 @@ void QAsmView::paintEvent(QPaintEvent *event)
{ {
lineOffset = maxLineOffset; lineOffset = maxLineOffset;
} }
selAddr = parent->getBookmarkSelectedAddress();
painter.fillRect( 0, 0, viewWidth, viewHeight, this->palette().color(QPalette::Background) ); painter.fillRect( 0, 0, viewWidth, viewHeight, this->palette().color(QPalette::Background) );
@ -2818,8 +3115,162 @@ void QAsmView::paintEvent(QPaintEvent *event)
painter.fillRect( 0, y - pxLineSpacing + pxLineLead, viewWidth, pxLineSpacing, QColor("light blue") ); painter.fillRect( 0, y - pxLineSpacing + pxLineLead, viewWidth, pxLineSpacing, QColor("light blue") );
} }
painter.drawText( x, y, tr(asmEntry[l]->text.c_str()) ); painter.drawText( x, y, tr(asmEntry[l]->text.c_str()) );
if ( selAddr == asmEntry[l]->addr )
{ // Highlight ASM line for selected address.
if ( !displayROMoffsets && (asmEntry[l]->type == dbg_asm_entry_t::ASM_TEXT) )
{
int ax;
char addrString[16];
ax = 4*pxCharWidth;
painter.fillRect( ax, y - pxLineSpacing + pxLineLead, 4*pxCharWidth, pxLineSpacing, QColor("blue") );
sprintf( addrString, "%04X", selAddr );
painter.setPen( this->palette().color(QPalette::Background));
painter.drawText( ax, y, tr(addrString) );
painter.setPen( this->palette().color(QPalette::WindowText));
}
}
} }
y += pxLineSpacing; y += pxLineSpacing;
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Bookmark Manager Methods
//----------------------------------------------------------------------------
debuggerBookmarkManager_t::debuggerBookmarkManager_t(void)
{
internal_iter = bmMap.begin();
}
//----------------------------------------------------------------------------
debuggerBookmarkManager_t::~debuggerBookmarkManager_t(void)
{
this->clear();
}
//----------------------------------------------------------------------------
void debuggerBookmarkManager_t::clear(void)
{
std::map <int, debuggerBookmark_t*>::iterator it;
for (it=bmMap.begin(); it!=bmMap.end(); it++)
{
delete it->second;
}
bmMap.clear();
internal_iter = bmMap.begin();
}
//----------------------------------------------------------------------------
int debuggerBookmarkManager_t::addBookmark( int addr, const char *name )
{
int retval = -1;
debuggerBookmark_t *bm = NULL;
std::map <int, debuggerBookmark_t*>::iterator it;
it = bmMap.find( addr );
if ( it == bmMap.end() )
{
bm = new debuggerBookmark_t();
bm->addr = addr;
if ( name != NULL )
{
bm->name.assign( name );
}
bmMap[ addr ] = bm;
retval = 0;
}
return retval;
}
//----------------------------------------------------------------------------
int debuggerBookmarkManager_t::editBookmark( int addr, const char *name )
{
int retval = -1;
debuggerBookmark_t *bm = NULL;
std::map <int, debuggerBookmark_t*>::iterator it;
it = bmMap.find( addr );
if ( it != bmMap.end() )
{
bm = it->second;
if ( name != NULL )
{
bm->name.assign( name );
}
retval = 0;
}
return retval;
}
//----------------------------------------------------------------------------
int debuggerBookmarkManager_t::deleteBookmark( int addr )
{
int retval = -1;
std::map <int, debuggerBookmark_t*>::iterator it;
it = bmMap.find( addr );
if ( it != bmMap.end() )
{
bmMap.erase(it);
retval = 0;
}
return retval;
}
//----------------------------------------------------------------------------
int debuggerBookmarkManager_t::size(void)
{
return bmMap.size();
}
//----------------------------------------------------------------------------
debuggerBookmark_t *debuggerBookmarkManager_t::begin(void)
{
internal_iter = bmMap.begin();
if ( internal_iter == bmMap.end() )
{
return NULL;
}
return internal_iter->second;
}
//----------------------------------------------------------------------------
debuggerBookmark_t *debuggerBookmarkManager_t::next(void)
{
if ( internal_iter == bmMap.end() )
{
return NULL;
}
internal_iter++;
if ( internal_iter == bmMap.end() )
{
return NULL;
}
return internal_iter->second;
}
//----------------------------------------------------------------------------
debuggerBookmark_t *debuggerBookmarkManager_t::getAddr( int addr )
{
std::map <int, debuggerBookmark_t*>::iterator it;
it = bmMap.find( addr );
if ( it != bmMap.end() )
{
return it->second;
}
return NULL;
}
//----------------------------------------------------------------------------

View File

@ -57,6 +57,38 @@ struct dbg_asm_entry_t
} }
}; };
class debuggerBookmark_t
{
public:
int addr;
std::string name;
debuggerBookmark_t(void)
{
addr = 0;
}
};
class debuggerBookmarkManager_t
{
public:
debuggerBookmarkManager_t(void);
~debuggerBookmarkManager_t(void);
int addBookmark( int addr, const char *name = NULL );
int editBookmark( int addr, const char *name );
int deleteBookmark( int addr );
int size(void);
void clear(void);
debuggerBookmark_t *begin(void);
debuggerBookmark_t *next(void);
debuggerBookmark_t *getAddr( int addr );
private:
std::map <int, debuggerBookmark_t*> bmMap;
std::map <int, debuggerBookmark_t*>::iterator internal_iter;
};
class ConsoleDebugger; class ConsoleDebugger;
class QAsmView : public QWidget class QAsmView : public QWidget
@ -134,6 +166,10 @@ class ConsoleDebugger : public QDialog
void breakPointNotify(int bpNum); void breakPointNotify(int bpNum);
void openBpEditWindow(int editIdx = -1, watchpointinfo *wp = NULL ); void openBpEditWindow(int editIdx = -1, watchpointinfo *wp = NULL );
void openDebugSymbolEditWindow( int addr ); void openDebugSymbolEditWindow( int addr );
void setBookmarkSelectedAddress( int addr );
int getBookmarkSelectedAddress(void){ return selBmAddrVal; };
void edit_BM_name( int addr );
void queueUpdate(void);
QLabel *asmLineSelLbl; QLabel *asmLineSelLbl;
protected: protected:
@ -189,16 +225,20 @@ class ConsoleDebugger : public QDialog
QTimer *periodicTimer; QTimer *periodicTimer;
QFont font; QFont font;
int selBmAddrVal;
bool windowUpdateReq; bool windowUpdateReq;
private: private:
void setRegsFromEntry(void); void setRegsFromEntry(void);
void bpListUpdate( bool reset = false ); void bpListUpdate( bool reset = false );
void bmListUpdate( bool reset = false );
public slots: public slots:
void closeWindow(void); void closeWindow(void);
void asmViewCtxMenuAddBP(void); void asmViewCtxMenuAddBP(void);
void asmViewCtxMenuAddBM(void);
void asmViewCtxMenuAddSym(void); void asmViewCtxMenuAddSym(void);
void asmViewCtxMenuOpenHexEdit(void);
private slots: private slots:
void updatePeriodic(void); void updatePeriodic(void);
void hbarChanged(int value); void hbarChanged(int value);
@ -214,6 +254,9 @@ class ConsoleDebugger : public QDialog
void add_BP_CB(void); void add_BP_CB(void);
void edit_BP_CB(void); void edit_BP_CB(void);
void delete_BP_CB(void); void delete_BP_CB(void);
void add_BM_CB(void);
void edit_BM_CB(void);
void delete_BM_CB(void);
void resetCountersCB (void); void resetCountersCB (void);
void reloadSymbolsCB(void); void reloadSymbolsCB(void);
void displayROMoffsetCB(int value); void displayROMoffsetCB(int value);
@ -226,11 +269,17 @@ class ConsoleDebugger : public QDialog
void breakOnInstructionsCB( int value ); void breakOnInstructionsCB( int value );
void bpItemClicked( QTreeWidgetItem *item, int column); void bpItemClicked( QTreeWidgetItem *item, int column);
void bmItemClicked( QTreeWidgetItem *item, int column); void bmItemClicked( QTreeWidgetItem *item, int column);
void bmItemDoubleClicked( QTreeWidgetItem *item, int column);
void cpuCycleThresChanged(const QString &txt); void cpuCycleThresChanged(const QString &txt);
void instructionsThresChanged(const QString &txt); void instructionsThresChanged(const QString &txt);
void selBmAddrChanged(const QString &txt);
}; };
bool debuggerWindowIsOpen(void);
void saveGameDebugBreakpoints(void); void saveGameDebugBreakpoints(void);
void loadGameDebugBreakpoints(void); void loadGameDebugBreakpoints(void);
void debuggerClearAllBreakpoints(void); void debuggerClearAllBreakpoints(void);
void updateAllDebuggerWindows(void);
extern debuggerBookmarkManager_t dbgBmMgr;

View File

@ -113,6 +113,9 @@ class consoleWin_t : public QMainWindow
private: private:
void createMainMenu(void); void createMainMenu(void);
public slots:
void openDebugWindow(void);
void openHexEditor(void);
private slots: private slots:
void closeApp(void); void closeApp(void);
void openROMFile(void); void openROMFile(void);
@ -156,8 +159,6 @@ class consoleWin_t : public QMainWindow
void fdsEjectDisk(void); void fdsEjectDisk(void);
void fdsLoadBiosFile(void); void fdsLoadBiosFile(void);
void openCheats(void); void openCheats(void);
void openDebugWindow(void);
void openHexEditor(void);
void openMovie(void); void openMovie(void);
void stopMovie(void); void stopMovie(void);
void recordMovie(void); void recordMovie(void);

View File

@ -35,7 +35,10 @@
#include "Qt/keyscan.h" #include "Qt/keyscan.h"
#include "Qt/fceuWrapper.h" #include "Qt/fceuWrapper.h"
#include "Qt/HexEditor.h" #include "Qt/HexEditor.h"
#include "Qt/SymbolicDebug.h"
#include "Qt/ConsoleDebugger.h"
#include "Qt/ConsoleUtilities.h" #include "Qt/ConsoleUtilities.h"
#include "Qt/ConsoleWindow.h"
static HexBookMarkManager_t hbm; static HexBookMarkManager_t hbm;
static std::list <HexEditorDialog_t*> winList; static std::list <HexEditorDialog_t*> winList;
@ -537,12 +540,11 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent)
QMenuBar *menuBar; QMenuBar *menuBar;
QMenu *fileMenu, *viewMenu, *colorMenu; QMenu *fileMenu, *viewMenu, *colorMenu;
QAction *saveROM, *closeAct; QAction *saveROM, *closeAct;
QAction *viewRAM, *viewPPU, *viewOAM, *viewROM;
QAction *actHlgt, *actHlgtRV, *actColorFG, *actColorBG; QAction *actHlgt, *actHlgtRV, *actColorFG, *actColorBG;
QActionGroup *group; QActionGroup *group;
int useNativeMenuBar; int useNativeMenuBar;
setWindowTitle("Hex Editor"); QDialog::setWindowTitle( tr("Hex Editor") );
resize( 512, 512 ); resize( 512, 512 );
@ -737,6 +739,19 @@ HexEditorDialog_t::~HexEditorDialog_t(void)
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void HexEditorDialog_t::setWindowTitle(void)
{
const char *modeString;
char stmp[128];
modeString = memViewNames[ editor->getMode() ];
sprintf( stmp, "Hex Editor - %s: 0x%04X", modeString, editor->getAddr() );
QDialog::setWindowTitle( tr(stmp) );
}
//----------------------------------------------------------------------------
void HexEditorDialog_t::removeAllBookmarks(void) void HexEditorDialog_t::removeAllBookmarks(void)
{ {
int ret; int ret;
@ -947,6 +962,134 @@ void HexEditorDialog_t::actvHighlightRVCB(bool enable)
editor->setHighlightReverseVideo( enable ); editor->setHighlightReverseVideo( enable );
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void HexEditorDialog_t::openDebugSymbolEditWindow( int addr )
{
int ret, bank, charWidth;
QDialog dialog(this);
QHBoxLayout *hbox;
QVBoxLayout *mainLayout;
QLabel *lbl;
QLineEdit *filepath, *addrEntry, *nameEntry, *commentEntry;
QPushButton *okButton, *cancelButton;
char stmp[512];
debugSymbol_t *sym;
QFont font;
font.setFamily("Courier New");
font.setStyle( QFont::StyleNormal );
font.setStyleHint( QFont::Monospace );
QFontMetrics fm(font);
#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
charWidth = fm.horizontalAdvance(QLatin1Char('2'));
#else
charWidth = fm.width(QLatin1Char('2'));
#endif
if ( addr < 0x8000 )
{
bank = -1;
}
else
{
bank = getBank( addr );
}
sym = debugSymbolTable.getSymbolAtBankOffset( bank, addr );
generateNLFilenameForAddress( addr, stmp );
dialog.setWindowTitle( tr("Symbolic Debug Naming") );
hbox = new QHBoxLayout();
mainLayout = new QVBoxLayout();
lbl = new QLabel( tr("File") );
filepath = new QLineEdit();
filepath->setFont( font );
filepath->setText( tr(stmp) );
filepath->setReadOnly( true );
filepath->setMinimumWidth( charWidth * (filepath->text().size() + 4) );
hbox->addWidget( lbl );
hbox->addWidget( filepath );
mainLayout->addLayout( hbox );
sprintf( stmp, "%04X", addr );
hbox = new QHBoxLayout();
lbl = new QLabel( tr("Address") );
addrEntry = new QLineEdit();
addrEntry->setFont( font );
addrEntry->setText( tr(stmp) );
addrEntry->setReadOnly( true );
addrEntry->setAlignment(Qt::AlignCenter);
addrEntry->setMaximumWidth( charWidth * 6 );
hbox->addWidget( lbl );
hbox->addWidget( addrEntry );
lbl = new QLabel( tr("Name") );
nameEntry = new QLineEdit();
hbox->addWidget( lbl );
hbox->addWidget( nameEntry );
mainLayout->addLayout( hbox );
hbox = new QHBoxLayout();
lbl = new QLabel( tr("Comment") );
commentEntry = new QLineEdit();
hbox->addWidget( lbl );
hbox->addWidget( commentEntry );
mainLayout->addLayout( hbox );
hbox = new QHBoxLayout();
okButton = new QPushButton( tr("OK") );
cancelButton = new QPushButton( tr("Cancel") );
mainLayout->addLayout( hbox );
hbox->addWidget( cancelButton );
hbox->addWidget( okButton );
connect( okButton, SIGNAL(clicked(void)), &dialog, SLOT(accept(void)) );
connect( cancelButton, SIGNAL(clicked(void)), &dialog, SLOT(reject(void)) );
if ( sym != NULL )
{
nameEntry->setText( tr(sym->name.c_str()) );
commentEntry->setText( tr(sym->comment.c_str()) );
}
dialog.setLayout( mainLayout );
ret = dialog.exec();
if ( ret == QDialog::Accepted )
{
if ( sym == NULL )
{
sym = new debugSymbol_t();
sym->ofs = addr;
sym->name = nameEntry->text().toStdString();
sym->comment = commentEntry->text().toStdString();
debugSymbolTable.addSymbolAtBankOffset( bank, addr, sym );
}
else
{
sym->name = nameEntry->text().toStdString();
sym->comment = commentEntry->text().toStdString();
}
//fceuWrapperLock();
updateAllDebuggerWindows();
//fceuWrapperUnLock();
}
}
//----------------------------------------------------------------------------
void HexEditorDialog_t::updatePeriodic(void) void HexEditorDialog_t::updatePeriodic(void)
{ {
//printf("Update Periodic\n"); //printf("Update Periodic\n");
@ -956,6 +1099,36 @@ void HexEditorDialog_t::updatePeriodic(void)
editor->memModeUpdate(); editor->memModeUpdate();
editor->update(); editor->update();
setWindowTitle();
switch ( editor->getMode() )
{
case QHexEdit::MODE_NES_RAM:
if ( !viewRAM->isChecked() )
{
viewRAM->setChecked(true);
}
break;
case QHexEdit::MODE_NES_PPU:
if ( !viewPPU->isChecked() )
{
viewPPU->setChecked(true);
}
break;
case QHexEdit::MODE_NES_OAM:
if ( !viewOAM->isChecked() )
{
viewOAM->setChecked(true);
}
break;
case QHexEdit::MODE_NES_ROM:
if ( !viewROM->isChecked() )
{
viewROM->setChecked(true);
}
break;
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
QHexEdit::QHexEdit(QWidget *parent) QHexEdit::QHexEdit(QWidget *parent)
@ -992,6 +1165,7 @@ QHexEdit::QHexEdit(QWidget *parent)
lineOffset = 0; lineOffset = 0;
cursorPosX = 0; cursorPosX = 0;
cursorPosY = 0; cursorPosY = 0;
cursorAddr = 0;
cursorBlink = true; cursorBlink = true;
cursorBlinkCount = 0; cursorBlinkCount = 0;
maxLineOffset = 0; maxLineOffset = 0;
@ -1531,20 +1705,24 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
{ {
case MODE_NES_RAM: case MODE_NES_RAM:
{ {
act = new QAction(tr("TODO Add Symbolic Debug Name"), this); act = new QAction(tr("Add Symbolic Debug Name"), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addDebugSym(void)) );
sprintf( stmp, "TODO Add Read Breakpoint for Address $%04X", addr ); sprintf( stmp, "Add Read Breakpoint for Address $%04X", addr );
act = new QAction(tr(stmp), this); act = new QAction(tr(stmp), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addRamReadBP(void)) );
sprintf( stmp, "TODO Add Write Breakpoint for Address $%04X", addr ); sprintf( stmp, "Add Write Breakpoint for Address $%04X", addr );
act = new QAction(tr(stmp), this); act = new QAction(tr(stmp), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addRamWriteBP(void)) );
sprintf( stmp, "TODO Add Execute Breakpoint for Address $%04X", addr ); sprintf( stmp, "Add Execute Breakpoint for Address $%04X", addr );
act = new QAction(tr(stmp), this); act = new QAction(tr(stmp), this);
menu.addAction(act); menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addRamExecuteBP(void)) );
if ( addr > 0x6000 ) if ( addr > 0x6000 )
{ {
@ -1567,6 +1745,16 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
break; break;
case MODE_NES_PPU: case MODE_NES_PPU:
{ {
sprintf( stmp, "Add Read Breakpoint for Address $%04X", addr );
act = new QAction(tr(stmp), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addPpuReadBP(void)) );
sprintf( stmp, "Add Write Breakpoint for Address $%04X", addr );
act = new QAction(tr(stmp), this);
menu.addAction(act);
connect( act, SIGNAL(triggered(void)), this, SLOT(addPpuWriteBP(void)) );
act = new QAction(tr("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)) ); connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
@ -1630,6 +1818,136 @@ void QHexEdit::addBookMarkCB(void)
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void QHexEdit::addDebugSym(void)
{
parent->openDebugSymbolEditWindow( ctxAddr );
}
//----------------------------------------------------------------------------
void QHexEdit::addRamReadBP(void)
{
int retval, type;
char cond[64], name[64];
type = BT_C | WP_R;
cond[0] = 0;
name[0] = 0;
if ( ctxAddr >= 0x8000 )
{
sprintf(cond, "K==#%02X", getBank(ctxAddr));
}
retval = NewBreak( name, ctxAddr, -1, type, cond, numWPs, true);
if ( (retval == 1) || (retval == 2) )
{
printf("Breakpoint Add Failed\n");
}
else
{
numWPs++;
}
}
//----------------------------------------------------------------------------
void QHexEdit::addRamWriteBP(void)
{
int retval, type;
char cond[64], name[64];
type = BT_C | WP_W;
cond[0] = 0;
name[0] = 0;
if ( ctxAddr >= 0x8000 )
{
sprintf(cond, "K==#%02X", getBank(ctxAddr));
}
retval = NewBreak( name, ctxAddr, -1, type, cond, numWPs, true);
if ( (retval == 1) || (retval == 2) )
{
printf("Breakpoint Add Failed\n");
}
else
{
numWPs++;
}
}
//----------------------------------------------------------------------------
void QHexEdit::addRamExecuteBP(void)
{
int retval, type;
char cond[64], name[64];
type = BT_C | WP_X;
cond[0] = 0;
name[0] = 0;
if ( ctxAddr >= 0x8000 )
{
sprintf(cond, "K==#%02X", getBank(ctxAddr));
}
retval = NewBreak( name, ctxAddr, -1, type, cond, numWPs, true);
if ( (retval == 1) || (retval == 2) )
{
printf("Breakpoint Add Failed\n");
}
else
{
numWPs++;
}
}
//----------------------------------------------------------------------------
void QHexEdit::addPpuReadBP(void)
{
int retval, type;
char cond[64], name[64];
type = BT_P | WP_R;
cond[0] = 0;
name[0] = 0;
retval = NewBreak( name, ctxAddr, -1, type, cond, numWPs, true);
if ( (retval == 1) || (retval == 2) )
{
printf("Breakpoint Add Failed\n");
}
else
{
numWPs++;
}
}
//----------------------------------------------------------------------------
void QHexEdit::addPpuWriteBP(void)
{
int retval, type;
char cond[64], name[64];
type = BT_P | WP_W;
cond[0] = 0;
name[0] = 0;
retval = NewBreak( name, ctxAddr, -1, type, cond, numWPs, true);
if ( (retval == 1) || (retval == 2) )
{
printf("Breakpoint Add Failed\n");
}
else
{
numWPs++;
}
}
//----------------------------------------------------------------------------
void QHexEdit::jumpToROM(void) void QHexEdit::jumpToROM(void)
{ {
setMode( MODE_NES_ROM ); setMode( MODE_NES_ROM );
@ -1732,6 +2050,9 @@ void QHexEdit::memModeUpdate(void)
printf("Error: Failed to allocate memview buffer size\n"); printf("Error: Failed to allocate memview buffer size\n");
return; return;
} }
maxLineOffset = mb.numLines() - viewLines + 1;
vbar->setMaximum( memSize / 16 );
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1807,6 +2128,7 @@ void QHexEdit::paintEvent(QPaintEvent *event)
ca = 16*(lineOffset + cursorPosY) + a; ca = 16*(lineOffset + cursorPosY) + a;
} }
cursorAddr = ca;
if ( cursorBlink ) if ( cursorBlink )
{ {
@ -1928,3 +2250,30 @@ void hexEditorSaveBookmarks(void)
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int hexEditorNumWindows(void)
{
return winList.size();
}
//----------------------------------------------------------------------------
int hexEditorOpenFromDebugger( int mode, int addr )
{
HexEditorDialog_t *win = NULL;
if ( winList.size() > 0 )
{
win = winList.front();
}
if ( win == NULL )
{
win = new HexEditorDialog_t(consoleWindow);
win->show();
}
win->editor->setMode( mode );
win->editor->setAddr( addr );
return 0;
}
//----------------------------------------------------------------------------

View File

@ -114,6 +114,7 @@ class QHexEdit : public QWidget
void setBackGroundColor( QColor bg ); void setBackGroundColor( QColor bg );
void memModeUpdate(void); void memModeUpdate(void);
int checkMemActivity(void); int checkMemActivity(void);
int getAddr(void){ return cursorAddr; };
enum { enum {
MODE_NES_RAM = 0, MODE_NES_RAM = 0,
@ -164,6 +165,7 @@ class QHexEdit : public QWidget
int pxHexAscii; int pxHexAscii;
int cursorPosX; int cursorPosX;
int cursorPosY; int cursorPosY;
int cursorAddr;
int cursorBlinkCount; int cursorBlinkCount;
int viewLines; int viewLines;
int viewWidth; int viewWidth;
@ -182,6 +184,12 @@ class QHexEdit : public QWidget
private slots: private slots:
void jumpToROM(void); void jumpToROM(void);
void addBookMarkCB(void); void addBookMarkCB(void);
void addDebugSym(void);
void addRamReadBP(void);
void addRamWriteBP(void);
void addRamExecuteBP(void);
void addPpuReadBP(void);
void addPpuWriteBP(void);
}; };
@ -195,15 +203,22 @@ class HexEditorDialog_t : public QDialog
void gotoAddress(int newAddr); void gotoAddress(int newAddr);
void populateBookmarkMenu(void); void populateBookmarkMenu(void);
void setWindowTitle(void);
void openDebugSymbolEditWindow( int addr );
QHexEdit *editor;
protected: protected:
void closeEvent(QCloseEvent *bar); void closeEvent(QCloseEvent *bar);
QScrollBar *vbar; QScrollBar *vbar;
QScrollBar *hbar; QScrollBar *hbar;
QHexEdit *editor;
QTimer *periodicTimer; QTimer *periodicTimer;
QMenu *bookmarkMenu; QMenu *bookmarkMenu;
QAction *viewRAM;
QAction *viewPPU;
QAction *viewOAM;
QAction *viewROM;
private: private:
@ -227,5 +242,7 @@ class HexEditorDialog_t : public QDialog
void removeAllBookmarks(void); void removeAllBookmarks(void);
}; };
int hexEditorNumWindows(void);
void hexEditorLoadBookmarks(void); void hexEditorLoadBookmarks(void);
void hexEditorSaveBookmarks(void); void hexEditorSaveBookmarks(void);
int hexEditorOpenFromDebugger( int mode, int addr );

View File

@ -229,13 +229,6 @@ int LoadGame(const char *path)
return 0; return 0;
} }
g_config->getOption( "SDL.AutoOpenDebugger", &autoOpenDebugger );
if ( autoOpenDebugger )
{
// TODO Auto Open Debugger
}
hexEditorLoadBookmarks(); hexEditorLoadBookmarks();
g_config->getOption( "SDL.AutoLoadDebugFiles", &autoLoadDebug ); g_config->getOption( "SDL.AutoLoadDebugFiles", &autoLoadDebug );
@ -245,6 +238,13 @@ int LoadGame(const char *path)
loadGameDebugBreakpoints(); loadGameDebugBreakpoints();
} }
g_config->getOption( "SDL.AutoOpenDebugger", &autoOpenDebugger );
if ( autoOpenDebugger && !debuggerWindowIsOpen() )
{
consoleWindow->openDebugWindow();
}
debugSymbolTable.loadGameSymbols(); debugSymbolTable.loadGameSymbols();
int state_to_load; int state_to_load;