commit
debdf6cfa7
2
README
2
README
|
@ -56,7 +56,7 @@ To compile faster with multiple processes in parallel:
|
|||
After a sucessful compilation, the fceux binary will be generated to
|
||||
./build/src/fceux . You can install fceux to your system with the following command:
|
||||
|
||||
make install
|
||||
sudo make install
|
||||
|
||||
You can optionally define a install prefix when running cmake from the previous step:
|
||||
|
||||
|
|
4
TODO-SDL
4
TODO-SDL
|
@ -42,10 +42,10 @@ RAM Search Window | NO | NO
|
|||
RAM Watch Window | NO | YES |
|
||||
Memory Watch Window | NO | NO |
|
||||
TAS Editor | NO | NO |
|
||||
6502 Debugger Window | NO | YES |
|
||||
6502 Debugger Window | YES | YES |
|
||||
PPU Viewer | NO | NO |
|
||||
Name Table Viewer | NO | NO |
|
||||
Memory Hex Editor | NO | YES |
|
||||
Memory Hex Editor | YES | YES |
|
||||
Trace Logger | NO | NO |
|
||||
Code/Data Logger | NO | NO |
|
||||
Game Genie Encoder/Decoder | NO | NO |
|
||||
|
|
|
@ -432,6 +432,8 @@ set(SRC_DRIVERS_SDL
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/LuaControl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CheatsConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HexEditor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/SymbolicDebug.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleDebugger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleUtilities.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleVideoConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleSoundConf.cpp
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct {
|
|||
//mbg merge 7/18/06 had to make this extern
|
||||
extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step over
|
||||
|
||||
extern unsigned int debuggerPageSize;
|
||||
int getBank(int offs);
|
||||
int GetNesFileAddress(int A);
|
||||
int GetPRGAddress(int A);
|
||||
|
|
|
@ -45,6 +45,7 @@ GuiCheatsDialog_t::GuiCheatsDialog_t(QWidget *parent)
|
|||
//printf("Pix Ratio: %f \n", devPixRatio );
|
||||
}
|
||||
|
||||
font.setFamily("Courier New");
|
||||
font.setStyle( QFont::StyleNormal );
|
||||
font.setStyleHint( QFont::Monospace );
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,236 @@
|
|||
// ConsoleDebugger.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QGroupBox>
|
||||
#include <QPushButton>
|
||||
#include <QFont>
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
#include <QFrame>
|
||||
#include <QGroupBox>
|
||||
#include <QTreeView>
|
||||
#include <QTreeWidget>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QLineEdit>
|
||||
#include <QTextEdit>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "Qt/main.h"
|
||||
#include "Qt/SymbolicDebug.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
struct dbg_asm_entry_t
|
||||
{
|
||||
int addr;
|
||||
int bank;
|
||||
int rom;
|
||||
int size;
|
||||
int line;
|
||||
uint8 opcode[3];
|
||||
std::string text;
|
||||
|
||||
enum
|
||||
{
|
||||
ASM_TEXT = 0,
|
||||
SYMBOL_NAME,
|
||||
SYMBOL_COMMENT
|
||||
} type;
|
||||
|
||||
dbg_asm_entry_t(void)
|
||||
{
|
||||
addr = 0; bank = -1; rom = -1;
|
||||
size = 0; line = 0; type = ASM_TEXT;
|
||||
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
opcode[i] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ConsoleDebugger;
|
||||
|
||||
class QAsmView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QAsmView(QWidget *parent = 0);
|
||||
~QAsmView(void);
|
||||
|
||||
void setScrollBars( QScrollBar *h, QScrollBar *v );
|
||||
void updateAssemblyView(void);
|
||||
void asmClear(void);
|
||||
int getAsmLineFromAddr(int addr);
|
||||
void setLine(int lineNum);
|
||||
void setXScroll(int value);
|
||||
void scrollToPC(void);
|
||||
void setDisplayROMoffsets( bool value );
|
||||
void setSymbolDebugEnable( bool value );
|
||||
void setRegisterNameEnable( bool value );
|
||||
int getCtxMenuAddr(void){ return ctxMenuAddr; };
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void keyReleaseEvent(QKeyEvent *event);
|
||||
void mousePressEvent(QMouseEvent * event);
|
||||
void mouseMoveEvent(QMouseEvent * event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void contextMenuEvent(QContextMenuEvent *event);
|
||||
|
||||
void calcFontData(void);
|
||||
QPoint convPixToCursor( QPoint p );
|
||||
|
||||
private:
|
||||
ConsoleDebugger *parent;
|
||||
QFont font;
|
||||
QScrollBar *vbar;
|
||||
QScrollBar *hbar;
|
||||
|
||||
int ctxMenuAddr;
|
||||
int maxLineLen;
|
||||
int pxCharWidth;
|
||||
int pxCharHeight;
|
||||
int pxCursorHeight;
|
||||
int pxLineSpacing;
|
||||
int pxLineLead;
|
||||
int viewLines;
|
||||
int viewWidth;
|
||||
int viewHeight;
|
||||
int lineOffset;
|
||||
int maxLineOffset;
|
||||
int pxLineWidth;
|
||||
int pxLineXScroll;
|
||||
int cursorPosX;
|
||||
int cursorPosY;
|
||||
|
||||
dbg_asm_entry_t *asmPC;
|
||||
std::vector <dbg_asm_entry_t*> asmEntry;
|
||||
|
||||
bool displayROMoffsets;
|
||||
bool symbolicDebugEnable;
|
||||
bool registerNameEnable;
|
||||
};
|
||||
|
||||
class ConsoleDebugger : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConsoleDebugger(QWidget *parent = 0);
|
||||
~ConsoleDebugger(void);
|
||||
|
||||
void updateWindowData(void);
|
||||
void updateRegisterView(void);
|
||||
void breakPointNotify(int bpNum);
|
||||
void openBpEditWindow(int editIdx = -1, watchpointinfo *wp = NULL );
|
||||
void openDebugSymbolEditWindow( int addr );
|
||||
|
||||
QLabel *asmLineSelLbl;
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
//void keyPressEvent(QKeyEvent *event);
|
||||
//void keyReleaseEvent(QKeyEvent *event);
|
||||
|
||||
//QTreeWidget *tree;
|
||||
QScrollBar *vbar;
|
||||
QScrollBar *hbar;
|
||||
QAsmView *asmView;
|
||||
QPlainTextEdit *stackText;
|
||||
QLineEdit *seekEntry;
|
||||
QLineEdit *pcEntry;
|
||||
QLineEdit *regAEntry;
|
||||
QLineEdit *regXEntry;
|
||||
QLineEdit *regYEntry;
|
||||
QLineEdit *cpuCycExdVal;
|
||||
QLineEdit *instrExdVal;
|
||||
QLineEdit *selBmAddr;
|
||||
QGroupBox *stackFrame;
|
||||
QGroupBox *bpFrame;
|
||||
QGroupBox *sfFrame;
|
||||
QGroupBox *bmFrame;
|
||||
QTreeWidget *bpTree;
|
||||
QTreeWidget *bmTree;
|
||||
QCheckBox *brkBadOpsCbox;
|
||||
QCheckBox *N_chkbox;
|
||||
QCheckBox *V_chkbox;
|
||||
QCheckBox *U_chkbox;
|
||||
QCheckBox *B_chkbox;
|
||||
QCheckBox *D_chkbox;
|
||||
QCheckBox *I_chkbox;
|
||||
QCheckBox *Z_chkbox;
|
||||
QCheckBox *C_chkbox;
|
||||
QCheckBox *brkCpuCycExd;
|
||||
QCheckBox *brkInstrsExd;
|
||||
QCheckBox *romOfsChkBox;
|
||||
QCheckBox *symDbgChkBox;
|
||||
QCheckBox *regNamChkBox;
|
||||
QCheckBox *autoOpenChkBox;
|
||||
QCheckBox *debFileChkBox;
|
||||
QCheckBox *idaFontChkBox;
|
||||
QLabel *emuStatLbl;
|
||||
QLabel *ppuLbl;
|
||||
QLabel *spriteLbl;
|
||||
QLabel *scanLineLbl;
|
||||
QLabel *pixLbl;
|
||||
QLabel *cpuCyclesLbl1;
|
||||
QLabel *cpuCyclesLbl2;
|
||||
QLabel *cpuInstrsLbl1;
|
||||
QLabel *cpuInstrsLbl2;
|
||||
QTimer *periodicTimer;
|
||||
QFont font;
|
||||
|
||||
bool windowUpdateReq;
|
||||
|
||||
private:
|
||||
void setRegsFromEntry(void);
|
||||
void bpListUpdate( bool reset = false );
|
||||
|
||||
public slots:
|
||||
void closeWindow(void);
|
||||
void asmViewCtxMenuAddBP(void);
|
||||
void asmViewCtxMenuAddSym(void);
|
||||
private slots:
|
||||
void updatePeriodic(void);
|
||||
void hbarChanged(int value);
|
||||
void vbarChanged(int value);
|
||||
void debugRunCB(void);
|
||||
void debugStepIntoCB(void);
|
||||
void debugStepOutCB(void);
|
||||
void debugStepOverCB(void);
|
||||
void debugRunLineCB(void);
|
||||
void debugRunLine128CB(void);
|
||||
void seekToCB(void);
|
||||
void seekPCCB(void);
|
||||
void add_BP_CB(void);
|
||||
void edit_BP_CB(void);
|
||||
void delete_BP_CB(void);
|
||||
void resetCountersCB (void);
|
||||
void reloadSymbolsCB(void);
|
||||
void displayROMoffsetCB(int value);
|
||||
void symbolDebugEnableCB(int value);
|
||||
void registerNameEnableCB(int value);
|
||||
void autoOpenDebugCB( int value );
|
||||
void debFileAutoLoadCB( int value );
|
||||
void breakOnBadOpcodeCB(int value);
|
||||
void breakOnCyclesCB( int value );
|
||||
void breakOnInstructionsCB( int value );
|
||||
void bpItemClicked( QTreeWidgetItem *item, int column);
|
||||
void bmItemClicked( QTreeWidgetItem *item, int column);
|
||||
void cpuCycleThresChanged(const QString &txt);
|
||||
void instructionsThresChanged(const QString &txt);
|
||||
|
||||
};
|
||||
|
||||
void saveGameDebugBreakpoints(void);
|
||||
void loadGameDebugBreakpoints(void);
|
||||
void debuggerClearAllBreakpoints(void);
|
|
@ -25,6 +25,7 @@
|
|||
#include "Qt/LuaControl.h"
|
||||
#include "Qt/CheatsConf.h"
|
||||
#include "Qt/HexEditor.h"
|
||||
#include "Qt/ConsoleDebugger.h"
|
||||
#include "Qt/ConsoleUtilities.h"
|
||||
#include "Qt/ConsoleSoundConf.h"
|
||||
#include "Qt/ConsoleVideoConf.h"
|
||||
|
@ -85,14 +86,14 @@ consoleWin_t::~consoleWin_t(void)
|
|||
|
||||
closeGamePadConfWindow();
|
||||
|
||||
//printf("Thread Finished: %i \n", gameThread->isFinished() );
|
||||
emulatorThread->quit();
|
||||
emulatorThread->wait( 1000 );
|
||||
|
||||
fceuWrapperLock();
|
||||
fceuWrapperClose();
|
||||
fceuWrapperUnLock();
|
||||
|
||||
//printf("Thread Finished: %i \n", gameThread->isFinished() );
|
||||
emulatorThread->quit();
|
||||
emulatorThread->wait();
|
||||
|
||||
if ( viewport_GL != NULL )
|
||||
{
|
||||
delete viewport_GL; viewport_GL = NULL;
|
||||
|
@ -482,6 +483,14 @@ void consoleWin_t::createMainMenu(void)
|
|||
// Debug
|
||||
debugMenu = menuBar()->addMenu(tr("Debug"));
|
||||
|
||||
// Debug -> Hex Editor
|
||||
debuggerAct = new QAction(tr("Debugger..."), this);
|
||||
//debuggerAct->setShortcut( QKeySequence(tr("Shift+F7")));
|
||||
debuggerAct->setStatusTip(tr("Open 6502 Debugger"));
|
||||
connect(debuggerAct, SIGNAL(triggered()), this, SLOT(openDebugWindow(void)) );
|
||||
|
||||
debugMenu->addAction(debuggerAct);
|
||||
|
||||
// Debug -> Hex Editor
|
||||
hexEditAct = new QAction(tr("Hex Editor..."), this);
|
||||
//hexEditAct->setShortcut( QKeySequence(tr("Shift+F7")));
|
||||
|
@ -551,6 +560,9 @@ void consoleWin_t::closeApp(void)
|
|||
{
|
||||
nes_shm->runEmulator = 0;
|
||||
|
||||
emulatorThread->quit();
|
||||
emulatorThread->wait( 1000 );
|
||||
|
||||
fceuWrapperLock();
|
||||
fceuWrapperClose();
|
||||
fceuWrapperUnLock();
|
||||
|
@ -559,7 +571,6 @@ void consoleWin_t::closeApp(void)
|
|||
// clear the NetworkIP field so this doesn't happen unintentionally
|
||||
g_config->setOption ("SDL.NetworkIP", "");
|
||||
g_config->save ();
|
||||
//SDL_Quit (); // Already called by fceuWrapperClose
|
||||
|
||||
//qApp::quit();
|
||||
qApp->quit();
|
||||
|
@ -970,6 +981,17 @@ void consoleWin_t::openCheats(void)
|
|||
cheatWin->show();
|
||||
}
|
||||
|
||||
void consoleWin_t::openDebugWindow(void)
|
||||
{
|
||||
ConsoleDebugger *debugWin;
|
||||
|
||||
//printf("Open GUI 6502 Debugger Window\n");
|
||||
|
||||
debugWin = new ConsoleDebugger(this);
|
||||
|
||||
debugWin->show();
|
||||
}
|
||||
|
||||
void consoleWin_t::openHexEditor(void)
|
||||
{
|
||||
HexEditorDialog_t *hexEditWin;
|
||||
|
|
|
@ -89,6 +89,7 @@ class consoleWin_t : public QMainWindow
|
|||
QAction *fdsEjectAct;
|
||||
QAction *fdsLoadBiosAct;
|
||||
QAction *cheatsAct;
|
||||
QAction *debuggerAct;
|
||||
QAction *hexEditAct;
|
||||
QAction *openMovAct;
|
||||
QAction *stopMovAct;
|
||||
|
@ -155,6 +156,7 @@ class consoleWin_t : public QMainWindow
|
|||
void fdsEjectDisk(void);
|
||||
void fdsLoadBiosFile(void);
|
||||
void openCheats(void);
|
||||
void openDebugWindow(void);
|
||||
void openHexEditor(void);
|
||||
void openMovie(void);
|
||||
void stopMovie(void);
|
||||
|
|
|
@ -1764,6 +1764,15 @@ void QHexEdit::paintEvent(QPaintEvent *event)
|
|||
//
|
||||
maxLineOffset = mb.numLines() - nrow + 1;
|
||||
|
||||
if ( maxLineOffset < 0 )
|
||||
{
|
||||
maxLineOffset = 0;
|
||||
}
|
||||
|
||||
if ( lineOffset < 0 )
|
||||
{
|
||||
lineOffset = 0;
|
||||
}
|
||||
if ( lineOffset > maxLineOffset )
|
||||
{
|
||||
lineOffset = maxLineOffset;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// GamePadConf.h
|
||||
// HotKeyConf.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
|
@ -0,0 +1,568 @@
|
|||
// SymbolicDebug.cpp
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "../../fceu.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../driver.h"
|
||||
#include "../../cart.h"
|
||||
#include "../../ines.h"
|
||||
|
||||
#include "Qt/SymbolicDebug.h"
|
||||
#include "Qt/ConsoleUtilities.h"
|
||||
|
||||
debugSymbolTable_t debugSymbolTable;
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// debugSymbolPage_t
|
||||
//--------------------------------------------------------------
|
||||
debugSymbolPage_t::debugSymbolPage_t(void)
|
||||
{
|
||||
pageNum = -1;
|
||||
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
debugSymbolPage_t::~debugSymbolPage_t(void)
|
||||
{
|
||||
std::map <int, debugSymbol_t*>::iterator it;
|
||||
|
||||
for (it=symMap.begin(); it!=symMap.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
symMap.clear();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int debugSymbolPage_t::addSymbol( debugSymbol_t*sym )
|
||||
{
|
||||
std::map <int, debugSymbol_t*>::iterator it;
|
||||
|
||||
it = symMap.find( sym->ofs );
|
||||
|
||||
if ( it != symMap.end() )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
symMap[ sym->ofs ] = sym;
|
||||
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
debugSymbol_t *debugSymbolPage_t::getSymbolAtOffset( int ofs )
|
||||
{
|
||||
debugSymbol_t*sym = NULL;
|
||||
std::map <int, debugSymbol_t*>::iterator it;
|
||||
|
||||
it = symMap.find( ofs );
|
||||
|
||||
if ( it != symMap.end() )
|
||||
{
|
||||
sym = it->second;
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int debugSymbolPage_t::save(void)
|
||||
{
|
||||
FILE *fp;
|
||||
debugSymbol_t *sym;
|
||||
std::map <int, debugSymbol_t*>::iterator it;
|
||||
const char *romFile;
|
||||
char stmp[512];
|
||||
int i,j;
|
||||
|
||||
romFile = getRomFile();
|
||||
|
||||
if ( romFile == NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
i=0;
|
||||
while ( romFile[i] != 0 )
|
||||
{
|
||||
|
||||
if ( romFile[i] == '|' )
|
||||
{
|
||||
stmp[i] = '.';
|
||||
}
|
||||
else
|
||||
{
|
||||
stmp[i] = romFile[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
stmp[i] = 0;
|
||||
|
||||
if ( pageNum < 0 )
|
||||
{
|
||||
strcat( stmp, ".ram.nl" );
|
||||
}
|
||||
else
|
||||
{
|
||||
char suffix[32];
|
||||
|
||||
sprintf( suffix, ".%X.nl", pageNum );
|
||||
|
||||
strcat( stmp, suffix );
|
||||
}
|
||||
|
||||
fp = fopen( stmp, "w" );
|
||||
|
||||
if ( fp == NULL )
|
||||
{
|
||||
printf("Error: Could not open file '%s' for writing\n", stmp );
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (it=symMap.begin(); it!=symMap.end(); it++)
|
||||
{
|
||||
const char *c;
|
||||
|
||||
sym = it->second;
|
||||
|
||||
i=0; j=0; c = sym->comment.c_str();
|
||||
|
||||
while ( c[i] != 0 )
|
||||
{
|
||||
if ( c[i] == '\n' )
|
||||
{
|
||||
i++; break;
|
||||
}
|
||||
else
|
||||
{
|
||||
stmp[j] = c[i]; j++; i++;
|
||||
}
|
||||
}
|
||||
stmp[j] = 0;
|
||||
|
||||
fprintf( fp, "$%04X#%s#%s\n", sym->ofs, sym->name.c_str(), stmp );
|
||||
|
||||
j=0;
|
||||
while ( c[i] != 0 )
|
||||
{
|
||||
if ( c[i] == '\n' )
|
||||
{
|
||||
i++; stmp[j] = 0;
|
||||
|
||||
if ( j > 0 )
|
||||
{
|
||||
fprintf( fp, "\\%s\n", stmp );
|
||||
}
|
||||
j=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stmp[j] = c[i]; j++; i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void debugSymbolPage_t::print(void)
|
||||
{
|
||||
FILE *fp;
|
||||
debugSymbol_t *sym;
|
||||
std::map <int, debugSymbol_t*>::iterator it;
|
||||
|
||||
fp = stdout;
|
||||
|
||||
fprintf( fp, "Page: %X \n", pageNum );
|
||||
|
||||
for (it=symMap.begin(); it!=symMap.end(); it++)
|
||||
{
|
||||
sym = it->second;
|
||||
|
||||
fprintf( fp, " Sym: $%04X '%s' \n", sym->ofs, sym->name.c_str() );
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
// debugSymbolTable_t
|
||||
//--------------------------------------------------------------
|
||||
debugSymbolTable_t::debugSymbolTable_t(void)
|
||||
{
|
||||
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
debugSymbolTable_t::~debugSymbolTable_t(void)
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void debugSymbolTable_t::clear(void)
|
||||
{
|
||||
std::map <int, debugSymbolPage_t*>::iterator it;
|
||||
|
||||
for (it=pageMap.begin(); it!=pageMap.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
pageMap.clear();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int generateNLFilenameForAddress(int address, char *NLfilename)
|
||||
{
|
||||
int bank;
|
||||
|
||||
if (address < 0x8000)
|
||||
{
|
||||
bank = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bank = getBank(address);
|
||||
#ifdef DW3_NL_0F_1F_HACK
|
||||
if(bank == 0x0F)
|
||||
bank = 0x1F;
|
||||
#endif
|
||||
}
|
||||
return generateNLFilenameForBank( bank, NLfilename );
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int generateNLFilenameForBank(int bank, char *NLfilename)
|
||||
{
|
||||
int i;
|
||||
const char *romFile;
|
||||
|
||||
romFile = getRomFile();
|
||||
|
||||
if ( romFile == NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
i=0;
|
||||
while ( romFile[i] != 0 )
|
||||
{
|
||||
|
||||
if ( romFile[i] == '|' )
|
||||
{
|
||||
NLfilename[i] = '.';
|
||||
}
|
||||
else
|
||||
{
|
||||
NLfilename[i] = romFile[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
NLfilename[i] = 0;
|
||||
|
||||
if (bank < 0)
|
||||
{
|
||||
// The NL file for the RAM addresses has the name nesrom.nes.ram.nl
|
||||
strcat(NLfilename, ".ram.nl");
|
||||
}
|
||||
else
|
||||
{
|
||||
char stmp[64];
|
||||
#ifdef DW3_NL_0F_1F_HACK
|
||||
if(bank == 0x0F)
|
||||
bank = 0x1F;
|
||||
#endif
|
||||
sprintf( stmp, ".%X.nl", bank);
|
||||
strcat(NLfilename, stmp );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int debugSymbolTable_t::loadFileNL( int bank )
|
||||
{
|
||||
FILE *fp;
|
||||
int i, j, ofs, lineNum = 0, literal = 0;
|
||||
char fileName[512], line[512];
|
||||
char stmp[512];
|
||||
debugSymbolPage_t *page = NULL;
|
||||
debugSymbol_t *sym = NULL;
|
||||
|
||||
//printf("Looking to Load Debug Bank: $%X \n", bank );
|
||||
|
||||
if ( generateNLFilenameForBank( bank, fileName ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
//printf("Loading NL File: %s\n", fileName );
|
||||
|
||||
fp = ::fopen( fileName, "r" );
|
||||
|
||||
if ( fp == NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
page = new debugSymbolPage_t;
|
||||
|
||||
page->pageNum = bank;
|
||||
|
||||
pageMap[ page->pageNum ] = page;
|
||||
|
||||
while ( fgets( line, sizeof(line), fp ) != 0 )
|
||||
{
|
||||
i=0; lineNum++;
|
||||
printf("%4i:%s", lineNum, line );
|
||||
|
||||
if ( line[i] == '\\' )
|
||||
{
|
||||
// Line is a comment continuation line.
|
||||
i++;
|
||||
|
||||
j=0;
|
||||
stmp[j] = '\n'; j++;
|
||||
|
||||
while ( line[i] != 0 )
|
||||
{
|
||||
stmp[j] = line[i]; j++; i++;
|
||||
}
|
||||
stmp[j] = 0;
|
||||
|
||||
j--;
|
||||
while ( j >= 0 )
|
||||
{
|
||||
if ( isspace( stmp[j] ) )
|
||||
{
|
||||
stmp[j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
j--;
|
||||
}
|
||||
if ( sym != NULL )
|
||||
{
|
||||
sym->comment.append( stmp );
|
||||
}
|
||||
}
|
||||
else if ( line[i] == '$' )
|
||||
{
|
||||
// Line is a new debug offset
|
||||
j=0; i++;
|
||||
if ( !isxdigit( line[i] ) )
|
||||
{
|
||||
printf("Error: Invalid Offset on Line %i of File %s\n", lineNum, fileName );
|
||||
}
|
||||
while ( isxdigit( line[i] ) )
|
||||
{
|
||||
stmp[j] = line[i]; i++; j++;
|
||||
}
|
||||
stmp[j] = 0;
|
||||
|
||||
ofs = strtol( stmp, NULL, 16 );
|
||||
|
||||
if ( line[i] != '#' )
|
||||
{
|
||||
printf("Error: Missing field delimiter following offset $%X on Line %i of File %s\n", ofs, lineNum, fileName );
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
|
||||
while ( isspace(line[i]) ) i++;
|
||||
|
||||
j = 0;
|
||||
while ( line[i] != 0 )
|
||||
{
|
||||
if ( line[i] == '\\' )
|
||||
{
|
||||
if ( literal )
|
||||
{
|
||||
switch ( line[i] )
|
||||
{
|
||||
case 'r':
|
||||
stmp[j] = '\r';
|
||||
break;
|
||||
case 'n':
|
||||
stmp[j] = '\n';
|
||||
break;
|
||||
case 't':
|
||||
stmp[j] = '\t';
|
||||
break;
|
||||
default:
|
||||
stmp[j] = line[i];
|
||||
break;
|
||||
}
|
||||
j++; i++;
|
||||
literal = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
literal = !literal;
|
||||
}
|
||||
}
|
||||
else if ( line[i] == '#' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
stmp[j] = line[i]; j++; i++;
|
||||
}
|
||||
}
|
||||
stmp[j] = 0;
|
||||
|
||||
j--;
|
||||
while ( j >= 0 )
|
||||
{
|
||||
if ( isspace( stmp[j] ) )
|
||||
{
|
||||
stmp[j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
j--;
|
||||
}
|
||||
|
||||
if ( line[i] != '#' )
|
||||
{
|
||||
printf("Error: Missing field delimiter following name '%s' on Line %i of File %s\n", stmp, lineNum, fileName );
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
|
||||
sym = new debugSymbol_t();
|
||||
|
||||
if ( sym == NULL )
|
||||
{
|
||||
printf("Error: Failed to allocate memory for offset $%04X Name '%s' on Line %i of File %s\n", ofs, stmp, lineNum, fileName );
|
||||
continue;
|
||||
}
|
||||
sym->ofs = ofs;
|
||||
sym->name.assign( stmp );
|
||||
|
||||
while ( isspace( line[i] ) ) i++;
|
||||
|
||||
j=0;
|
||||
while ( line[i] != 0 )
|
||||
{
|
||||
stmp[j] = line[i]; j++; i++;
|
||||
}
|
||||
stmp[j] = 0;
|
||||
|
||||
j--;
|
||||
while ( j >= 0 )
|
||||
{
|
||||
if ( isspace( stmp[j] ) )
|
||||
{
|
||||
stmp[j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
j--;
|
||||
}
|
||||
|
||||
sym->comment.assign( stmp );
|
||||
|
||||
if ( page->addSymbol( sym ) )
|
||||
{
|
||||
printf("Error: Failed to add symbol for offset $%04X Name '%s' on Line %i of File %s\n", ofs, stmp, lineNum, fileName );
|
||||
delete sym; sym = NULL; // Failed to add symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int debugSymbolTable_t::loadGameSymbols(void)
|
||||
{
|
||||
int nPages, pageSize, romSize = 0x10000;
|
||||
|
||||
this->save();
|
||||
this->clear();
|
||||
|
||||
if ( GameInfo != NULL )
|
||||
{
|
||||
romSize = 16 + CHRsize[0] + PRGsize[0];
|
||||
}
|
||||
|
||||
loadFileNL( -1 );
|
||||
|
||||
pageSize = (1<<debuggerPageSize);
|
||||
|
||||
//nPages = 1<<(15-debuggerPageSize);
|
||||
nPages = romSize / pageSize;
|
||||
|
||||
printf("RomSize: %i NumPages: %i \n", romSize, nPages );
|
||||
|
||||
for(int i=0;i<nPages;i++)
|
||||
{
|
||||
//printf("Loading Page Offset: $%06X\n", pageSize*i );
|
||||
|
||||
loadFileNL( i );
|
||||
}
|
||||
|
||||
print();
|
||||
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
int debugSymbolTable_t::addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym )
|
||||
{
|
||||
debugSymbolPage_t *page;
|
||||
std::map <int, debugSymbolPage_t*>::iterator it;
|
||||
|
||||
it = pageMap.find( bank );
|
||||
|
||||
if ( it == pageMap.end() )
|
||||
{
|
||||
page = new debugSymbolPage_t();
|
||||
page->pageNum = bank;
|
||||
pageMap[ bank ] = page;
|
||||
}
|
||||
else
|
||||
{
|
||||
page = it->second;
|
||||
}
|
||||
page->addSymbol( sym );
|
||||
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
debugSymbol_t *debugSymbolTable_t::getSymbolAtBankOffset( int bank, int ofs )
|
||||
{
|
||||
debugSymbol_t*sym = NULL;
|
||||
std::map <int, debugSymbolPage_t*>::iterator it;
|
||||
|
||||
it = pageMap.find( bank );
|
||||
|
||||
if ( it != pageMap.end() )
|
||||
{
|
||||
sym = (it->second)->getSymbolAtOffset( ofs );
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void debugSymbolTable_t::save(void)
|
||||
{
|
||||
debugSymbolPage_t *page;
|
||||
std::map <int, debugSymbolPage_t*>::iterator it;
|
||||
|
||||
for (it=pageMap.begin(); it!=pageMap.end(); it++)
|
||||
{
|
||||
page = it->second;
|
||||
|
||||
page->save();
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void debugSymbolTable_t::print(void)
|
||||
{
|
||||
debugSymbolPage_t *page;
|
||||
std::map <int, debugSymbolPage_t*>::iterator it;
|
||||
|
||||
for (it=pageMap.begin(); it!=pageMap.end(); it++)
|
||||
{
|
||||
page = it->second;
|
||||
|
||||
page->print();
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
|
@ -0,0 +1,76 @@
|
|||
// SymbolicDebug.h
|
||||
//
|
||||
#ifndef __SYMBOLIC_DEBUG_H__
|
||||
#define __SYMBOLIC_DEBUG_H__
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
struct debugSymbol_t
|
||||
{
|
||||
int ofs;
|
||||
std::string name;
|
||||
std::string comment;
|
||||
|
||||
debugSymbol_t(void)
|
||||
{
|
||||
ofs = 0;
|
||||
};
|
||||
};
|
||||
|
||||
struct debugSymbolPage_t
|
||||
{
|
||||
int pageNum;
|
||||
|
||||
debugSymbolPage_t(void);
|
||||
~debugSymbolPage_t(void);
|
||||
|
||||
int save(void);
|
||||
void print(void);
|
||||
int size(void){ return symMap.size(); }
|
||||
|
||||
int addSymbol( debugSymbol_t *sym );
|
||||
|
||||
debugSymbol_t *getSymbolAtOffset( int ofs );
|
||||
|
||||
std::map <int, debugSymbol_t*> symMap;
|
||||
};
|
||||
|
||||
class debugSymbolTable_t
|
||||
{
|
||||
|
||||
public:
|
||||
debugSymbolTable_t(void);
|
||||
~debugSymbolTable_t(void);
|
||||
|
||||
int loadFileNL( int addr );
|
||||
int loadGameSymbols(void);
|
||||
int numPages(void){ return pageMap.size(); }
|
||||
|
||||
void save(void);
|
||||
void clear(void);
|
||||
void print(void);
|
||||
|
||||
debugSymbol_t *getSymbolAtBankOffset( int bank, int ofs );
|
||||
|
||||
int addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym );
|
||||
|
||||
private:
|
||||
std::map <int, debugSymbolPage_t*> pageMap;
|
||||
|
||||
};
|
||||
|
||||
extern debugSymbolTable_t debugSymbolTable;
|
||||
|
||||
//struct MemoryMappedRegister
|
||||
//{
|
||||
// char* offset;
|
||||
// char* name;
|
||||
//};
|
||||
|
||||
|
||||
int generateNLFilenameForBank(int bank, char *NLfilename);
|
||||
int generateNLFilenameForAddress(int address, char *NLfilename);
|
||||
|
||||
#endif
|
|
@ -259,6 +259,10 @@ InitConfig()
|
|||
config->addOption("hexEditBgColor", "SDL.HexEditBgColor", "#000000");
|
||||
config->addOption("hexEditFgColor", "SDL.HexEditFgColor", "#FFFFFF");
|
||||
|
||||
// Debugger Options
|
||||
config->addOption("autoLoadDebugFiles", "SDL.AutoLoadDebugFiles", 1);
|
||||
config->addOption("autoOpenDebugger" , "SDL.AutoOpenDebugger" , 0);
|
||||
|
||||
// overwrite the config file?
|
||||
config->addOption("no-config", "SDL.NoConfig", 0);
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "Qt/nes_shm.h"
|
||||
#include "Qt/unix-netplay.h"
|
||||
#include "Qt/HexEditor.h"
|
||||
#include "Qt/SymbolicDebug.h"
|
||||
#include "Qt/ConsoleDebugger.h"
|
||||
#include "Qt/ConsoleWindow.h"
|
||||
#include "Qt/fceux_git_info.h"
|
||||
|
||||
|
@ -159,11 +161,6 @@ FCEUD_GetTimeFreq(void)
|
|||
return 1000;
|
||||
}
|
||||
|
||||
void FCEUD_DebugBreakpoint( int addr )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all of the subsystem drivers: video, audio, and joystick.
|
||||
*/
|
||||
|
@ -215,7 +212,7 @@ DriverKill()
|
|||
*/
|
||||
int LoadGame(const char *path)
|
||||
{
|
||||
int gg_enabled;
|
||||
int gg_enabled, autoLoadDebug, autoOpenDebugger;
|
||||
|
||||
if (isloaded){
|
||||
CloseGame();
|
||||
|
@ -232,8 +229,24 @@ int LoadGame(const char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
g_config->getOption( "SDL.AutoOpenDebugger", &autoOpenDebugger );
|
||||
|
||||
if ( autoOpenDebugger )
|
||||
{
|
||||
// TODO Auto Open Debugger
|
||||
}
|
||||
|
||||
hexEditorLoadBookmarks();
|
||||
|
||||
g_config->getOption( "SDL.AutoLoadDebugFiles", &autoLoadDebug );
|
||||
|
||||
if ( autoLoadDebug )
|
||||
{
|
||||
loadGameDebugBreakpoints();
|
||||
}
|
||||
|
||||
debugSymbolTable.loadGameSymbols();
|
||||
|
||||
int state_to_load;
|
||||
g_config->getOption("SDL.AutoLoadState", &state_to_load);
|
||||
if (state_to_load >= 0 && state_to_load < 10){
|
||||
|
@ -281,6 +294,11 @@ CloseGame(void)
|
|||
return(0);
|
||||
}
|
||||
hexEditorSaveBookmarks();
|
||||
saveGameDebugBreakpoints();
|
||||
debuggerClearAllBreakpoints();
|
||||
|
||||
debugSymbolTable.save();
|
||||
debugSymbolTable.clear();
|
||||
|
||||
int state_to_save;
|
||||
g_config->getOption("SDL.AutoSaveState", &state_to_save);
|
||||
|
|
|
@ -1002,7 +1002,7 @@ int iNesSaveAs(const char* name)
|
|||
}
|
||||
|
||||
//para edit: added function below
|
||||
char *iNesShortFName() {
|
||||
char *iNesShortFName(void) {
|
||||
char *ret;
|
||||
|
||||
if (!(ret = strrchr(LoadedRomFName, '\\')))
|
||||
|
|
|
@ -46,6 +46,7 @@ extern uint8 *ExtraNTARAM;
|
|||
extern int iNesSave(void); //bbit Edited: line added
|
||||
extern int iNesSaveAs(const char* name);
|
||||
extern char LoadedRomFName[2048]; //bbit Edited: line added
|
||||
extern char *iNesShortFName(void);
|
||||
extern const TMasterRomInfo* MasterRomInfo;
|
||||
extern TMasterRomInfoParams MasterRomInfoParams;
|
||||
|
||||
|
|
Loading…
Reference in New Issue