Initial port of ASM window code.
This commit is contained in:
parent
7001b55569
commit
ccbcab5e77
|
@ -4,18 +4,37 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
|
||||||
|
#include "../../types.h"
|
||||||
|
#include "../../fceu.h"
|
||||||
|
#include "../../cheat.h"
|
||||||
|
#include "../../debug.h"
|
||||||
|
#include "../../driver.h"
|
||||||
|
#include "../../version.h"
|
||||||
|
#include "../../video.h"
|
||||||
|
#include "../../movie.h"
|
||||||
|
#include "../../palette.h"
|
||||||
|
#include "../../fds.h"
|
||||||
|
#include "../../cart.h"
|
||||||
|
#include "../../ines.h"
|
||||||
|
#include "../../asm.h"
|
||||||
|
#include "../../ppu.h"
|
||||||
|
#include "../../x6502.h"
|
||||||
|
#include "common/configSys.h"
|
||||||
|
|
||||||
#include "Qt/main.h"
|
#include "Qt/main.h"
|
||||||
#include "Qt/dface.h"
|
#include "Qt/dface.h"
|
||||||
#include "Qt/config.h"
|
#include "Qt/config.h"
|
||||||
#include "Qt/fceuWrapper.h"
|
#include "Qt/fceuWrapper.h"
|
||||||
#include "Qt/ConsoleDebugger.h"
|
#include "Qt/ConsoleDebugger.h"
|
||||||
|
|
||||||
|
static std::list <ConsoleDebugger*> dbgWinList;
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ConsoleDebugger::ConsoleDebugger(QWidget *parent)
|
ConsoleDebugger::ConsoleDebugger(QWidget *parent)
|
||||||
: QDialog( parent )
|
: QDialog( parent )
|
||||||
|
@ -55,8 +74,8 @@ ConsoleDebugger::ConsoleDebugger(QWidget *parent)
|
||||||
hbox1->addLayout( vbox2 );
|
hbox1->addLayout( vbox2 );
|
||||||
vbox2->addLayout( grid );
|
vbox2->addLayout( grid );
|
||||||
|
|
||||||
mainLayout->addWidget( asmText );
|
mainLayout->addWidget( asmText, 10 );
|
||||||
mainLayout->addLayout( vbox1 );
|
mainLayout->addLayout( vbox1, 1 );
|
||||||
|
|
||||||
button = new QPushButton( tr("Run") );
|
button = new QPushButton( tr("Run") );
|
||||||
grid->addWidget( button, 0, 0, Qt::AlignLeft );
|
grid->addWidget( button, 0, 0, Qt::AlignLeft );
|
||||||
|
@ -140,7 +159,7 @@ ConsoleDebugger::ConsoleDebugger(QWidget *parent)
|
||||||
stackFrame->setLayout( hbox );
|
stackFrame->setLayout( hbox );
|
||||||
stackText->setFont(font);
|
stackText->setFont(font);
|
||||||
stackText->setReadOnly(true);
|
stackText->setReadOnly(true);
|
||||||
stackText->setMaximumWidth( 16 * fontCharWidth );
|
//stackText->setMaximumWidth( 16 * fontCharWidth );
|
||||||
|
|
||||||
bpFrame = new QGroupBox(tr("Breakpoints"));
|
bpFrame = new QGroupBox(tr("Breakpoints"));
|
||||||
vbox3 = new QVBoxLayout();
|
vbox3 = new QVBoxLayout();
|
||||||
|
@ -232,23 +251,31 @@ ConsoleDebugger::ConsoleDebugger(QWidget *parent)
|
||||||
hbox2->addLayout( vbox );
|
hbox2->addLayout( vbox );
|
||||||
|
|
||||||
cpuCycExdVal->setFont( font );
|
cpuCycExdVal->setFont( font );
|
||||||
cpuCycExdVal->setMaxLength( 10 );
|
cpuCycExdVal->setMaxLength( 16 );
|
||||||
cpuCycExdVal->setInputMask( ">DDDD;0" );
|
cpuCycExdVal->setInputMask( ">9000000000000000;" );
|
||||||
cpuCycExdVal->setAlignment(Qt::AlignCenter);
|
cpuCycExdVal->setAlignment(Qt::AlignLeft);
|
||||||
cpuCycExdVal->setMaximumWidth( 12 * fontCharWidth );
|
cpuCycExdVal->setMaximumWidth( 18 * fontCharWidth );
|
||||||
|
|
||||||
instrExdVal->setFont( font );
|
instrExdVal->setFont( font );
|
||||||
instrExdVal->setMaxLength( 10 );
|
instrExdVal->setMaxLength( 16 );
|
||||||
instrExdVal->setInputMask( ">DDDD;0" );
|
instrExdVal->setInputMask( ">9000000000000000;" );
|
||||||
instrExdVal->setAlignment(Qt::AlignCenter);
|
instrExdVal->setAlignment(Qt::AlignLeft);
|
||||||
instrExdVal->setMaximumWidth( 12 * fontCharWidth );
|
instrExdVal->setMaximumWidth( 18 * fontCharWidth );
|
||||||
|
|
||||||
setLayout( mainLayout );
|
setLayout( mainLayout );
|
||||||
|
|
||||||
|
displayROMoffsets = 0;
|
||||||
|
asmPC = NULL;
|
||||||
|
|
||||||
|
dbgWinList.push_back( this );
|
||||||
|
|
||||||
|
updateWindowData();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ConsoleDebugger::~ConsoleDebugger(void)
|
ConsoleDebugger::~ConsoleDebugger(void)
|
||||||
{
|
{
|
||||||
printf("Destroy Debugger Window\n");
|
printf("Destroy Debugger Window\n");
|
||||||
|
asmClear();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void ConsoleDebugger::closeEvent(QCloseEvent *event)
|
void ConsoleDebugger::closeEvent(QCloseEvent *event)
|
||||||
|
@ -266,3 +293,315 @@ void ConsoleDebugger::closeWindow(void)
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
void ConsoleDebugger::asmClear(void)
|
||||||
|
{
|
||||||
|
for (size_t i=0; i<asmEntry.size(); i++)
|
||||||
|
{
|
||||||
|
delete asmEntry[i];
|
||||||
|
}
|
||||||
|
asmEntry.clear();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
int ConsoleDebugger::getAsmLineFromAddr(int addr)
|
||||||
|
{
|
||||||
|
int line = -1;
|
||||||
|
int incr, nextLine;
|
||||||
|
int run = 1;
|
||||||
|
|
||||||
|
if ( asmEntry.size() <= 0 )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
incr = asmEntry.size() / 2;
|
||||||
|
|
||||||
|
if ( addr < asmEntry[0]->addr )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if ( addr > asmEntry[ asmEntry.size() - 1 ]->addr )
|
||||||
|
{
|
||||||
|
return asmEntry.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( incr < 1 ) incr = 1;
|
||||||
|
|
||||||
|
nextLine = line = incr;
|
||||||
|
|
||||||
|
// algorithm to efficiently find line from address. Starts in middle of list and
|
||||||
|
// keeps dividing the list in 2 until it arrives at an answer.
|
||||||
|
while ( run )
|
||||||
|
{
|
||||||
|
//printf("incr:%i line:%i addr:%04X delta:%i\n", incr, line, asmEntry[line]->addr, addr - asmEntry[line]->addr);
|
||||||
|
|
||||||
|
if ( incr == 1 )
|
||||||
|
{
|
||||||
|
if ( asmEntry[line]->addr < addr )
|
||||||
|
{
|
||||||
|
nextLine = line + 1;
|
||||||
|
if ( asmEntry[line]->addr > nextLine )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line = nextLine;
|
||||||
|
}
|
||||||
|
else if ( asmEntry[line]->addr > addr )
|
||||||
|
{
|
||||||
|
nextLine = line - 1;
|
||||||
|
if ( asmEntry[line]->addr < nextLine )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line = nextLine;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
run = 0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
incr = incr / 2;
|
||||||
|
if ( incr < 1 ) incr = 1;
|
||||||
|
|
||||||
|
if ( asmEntry[line]->addr < addr )
|
||||||
|
{
|
||||||
|
nextLine = line + incr;
|
||||||
|
}
|
||||||
|
else if ( asmEntry[line]->addr > addr )
|
||||||
|
{
|
||||||
|
nextLine = line - incr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
run = 0; break;
|
||||||
|
}
|
||||||
|
line = nextLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//for (size_t i=0; i<asmEntry.size(); i++)
|
||||||
|
//{
|
||||||
|
// if ( asmEntry[i]->addr >= addr )
|
||||||
|
// {
|
||||||
|
// line = i; break;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// This function is for "smart" scrolling...
|
||||||
|
// it attempts to scroll up one line by a whole instruction
|
||||||
|
static int InstructionUp(int from)
|
||||||
|
{
|
||||||
|
int i = std::min(16, from), j;
|
||||||
|
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
j = i;
|
||||||
|
while (j > 0)
|
||||||
|
{
|
||||||
|
if (GetMem(from - j) == 0x00)
|
||||||
|
break; // BRK usually signifies data
|
||||||
|
if (opsize[GetMem(from - j)] == 0)
|
||||||
|
break; // invalid instruction!
|
||||||
|
if (opsize[GetMem(from - j)] > j)
|
||||||
|
break; // instruction is too long!
|
||||||
|
if (opsize[GetMem(from - j)] == j)
|
||||||
|
return (from - j); // instruction is just right! :D
|
||||||
|
j -= opsize[GetMem(from - j)];
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we get here, no suitable instruction was found
|
||||||
|
if ((from >= 2) && (GetMem(from - 2) == 0x00))
|
||||||
|
return (from - 2); // if a BRK instruction is possible, use that
|
||||||
|
if (from)
|
||||||
|
return (from - 1); // else, scroll up one byte
|
||||||
|
return 0; // of course, if we can't scroll up, just return 0!
|
||||||
|
}
|
||||||
|
//static int InstructionDown(int from)
|
||||||
|
//{
|
||||||
|
// int tmp = opsize[GetMem(from)];
|
||||||
|
// if ((tmp))
|
||||||
|
// return from + tmp;
|
||||||
|
// else
|
||||||
|
// return from + 1; // this is data or undefined instruction
|
||||||
|
//}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void ConsoleDebugger::updateAssemblyView(void)
|
||||||
|
{
|
||||||
|
int starting_address, start_address_lp, addr, size;
|
||||||
|
int instruction_addr;
|
||||||
|
std::string line;
|
||||||
|
char chr[64];
|
||||||
|
uint8 opcode[3];
|
||||||
|
const char *disassemblyText = NULL;
|
||||||
|
dbg_asm_entry_t *a;
|
||||||
|
//GtkTextIter iter, next_iter;
|
||||||
|
char pc_found = 0;
|
||||||
|
|
||||||
|
start_address_lp = starting_address = X.PC;
|
||||||
|
|
||||||
|
for (int i=0; i < 0xFFFF; i++)
|
||||||
|
{
|
||||||
|
//printf("%i: Start Address: 0x%04X \n", i, start_address_lp );
|
||||||
|
|
||||||
|
starting_address = InstructionUp( start_address_lp );
|
||||||
|
|
||||||
|
if ( starting_address == start_address_lp )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( starting_address < 0 )
|
||||||
|
{
|
||||||
|
starting_address = start_address_lp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start_address_lp = starting_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
asmClear();
|
||||||
|
|
||||||
|
addr = starting_address;
|
||||||
|
asmPC = NULL;
|
||||||
|
|
||||||
|
//gtk_text_buffer_get_start_iter( textbuf, &iter );
|
||||||
|
|
||||||
|
//textview_lines_allocated = gtk_text_buffer_get_line_count( textbuf ) - 1;
|
||||||
|
|
||||||
|
//printf("Num Lines: %i\n", textview_lines_allocated );
|
||||||
|
|
||||||
|
for (int i=0; i < 0xFFFF; i++)
|
||||||
|
{
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
// PC pointer
|
||||||
|
if (addr > 0xFFFF) break;
|
||||||
|
|
||||||
|
a = new dbg_asm_entry_t;
|
||||||
|
|
||||||
|
instruction_addr = addr;
|
||||||
|
|
||||||
|
if ( !pc_found )
|
||||||
|
{
|
||||||
|
if (addr > X.PC)
|
||||||
|
{
|
||||||
|
asmPC = a;
|
||||||
|
line.assign(">");
|
||||||
|
pc_found = 1;
|
||||||
|
}
|
||||||
|
else if (addr == X.PC)
|
||||||
|
{
|
||||||
|
asmPC = a;
|
||||||
|
line.assign(">");
|
||||||
|
pc_found = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line.assign(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line.assign(" ");
|
||||||
|
}
|
||||||
|
a->addr = addr;
|
||||||
|
|
||||||
|
if (addr >= 0x8000)
|
||||||
|
{
|
||||||
|
a->bank = getBank(addr);
|
||||||
|
a->rom = GetNesFileAddress(addr);
|
||||||
|
|
||||||
|
if (displayROMoffsets && (a->rom != -1) )
|
||||||
|
{
|
||||||
|
sprintf(chr, " %06X: ", a->rom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(chr, "%02X:%04X: ", a->bank, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(chr, " :%04X: ", addr);
|
||||||
|
}
|
||||||
|
line.append(chr);
|
||||||
|
|
||||||
|
size = opsize[GetMem(addr)];
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
sprintf(chr, "%02X UNDEFINED", GetMem(addr++));
|
||||||
|
line.append(chr);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if ((addr + size) > 0xFFFF)
|
||||||
|
{
|
||||||
|
while (addr < 0xFFFF)
|
||||||
|
{
|
||||||
|
sprintf(chr, "%02X OVERFLOW\n", GetMem(addr++));
|
||||||
|
line.append(chr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < size; j++)
|
||||||
|
{
|
||||||
|
sprintf(chr, "%02X ", opcode[j] = GetMem(addr++));
|
||||||
|
line.append(chr);
|
||||||
|
}
|
||||||
|
while (size < 3)
|
||||||
|
{
|
||||||
|
line.append(" "); //pad output to align ASM
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
disassemblyText = Disassemble(addr, opcode);
|
||||||
|
|
||||||
|
if ( disassemblyText )
|
||||||
|
{
|
||||||
|
line.append( disassemblyText );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j=0; j<size; j++)
|
||||||
|
{
|
||||||
|
a->opcode[j] = opcode[j];
|
||||||
|
}
|
||||||
|
a->size = size;
|
||||||
|
|
||||||
|
// special case: an RTS opcode
|
||||||
|
if (GetMem(instruction_addr) == 0x60)
|
||||||
|
{
|
||||||
|
line.append("-------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
a->text.assign( line );
|
||||||
|
|
||||||
|
a->line = asmEntry.size();
|
||||||
|
|
||||||
|
line.append("\n");
|
||||||
|
|
||||||
|
asmText->insertPlainText( tr(line.c_str()) );
|
||||||
|
|
||||||
|
asmEntry.push_back(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void ConsoleDebugger::updateWindowData(void)
|
||||||
|
{
|
||||||
|
updateAssemblyView();
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void FCEUD_DebugBreakpoint( int addr )
|
||||||
|
{
|
||||||
|
std::list <ConsoleDebugger*>::iterator it;
|
||||||
|
printf("Breakpoint Hit: 0x%04X \n", addr );
|
||||||
|
|
||||||
|
for (it=dbgWinList.begin(); it!=dbgWinList.end(); it++)
|
||||||
|
{
|
||||||
|
(*it)->updateWindowData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
|
@ -22,6 +22,29 @@
|
||||||
|
|
||||||
#include "Qt/main.h"
|
#include "Qt/main.h"
|
||||||
|
|
||||||
|
struct dbg_asm_entry_t
|
||||||
|
{
|
||||||
|
int addr;
|
||||||
|
int bank;
|
||||||
|
int rom;
|
||||||
|
int size;
|
||||||
|
int line;
|
||||||
|
uint8 opcode[3];
|
||||||
|
std::string text;
|
||||||
|
|
||||||
|
|
||||||
|
dbg_asm_entry_t(void)
|
||||||
|
{
|
||||||
|
addr = 0; bank = 0; rom = -1;
|
||||||
|
size = 0; line = 0;
|
||||||
|
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
opcode[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ConsoleDebugger : public QDialog
|
class ConsoleDebugger : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -30,6 +53,11 @@ class ConsoleDebugger : public QDialog
|
||||||
ConsoleDebugger(QWidget *parent = 0);
|
ConsoleDebugger(QWidget *parent = 0);
|
||||||
~ConsoleDebugger(void);
|
~ConsoleDebugger(void);
|
||||||
|
|
||||||
|
void updateWindowData(void);
|
||||||
|
void updateAssemblyView(void);
|
||||||
|
void asmClear(void);
|
||||||
|
int getAsmLineFromAddr(int addr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
//void keyPressEvent(QKeyEvent *event);
|
//void keyPressEvent(QKeyEvent *event);
|
||||||
|
@ -68,6 +96,11 @@ class ConsoleDebugger : public QDialog
|
||||||
QLabel *cpuInstrsLbl;
|
QLabel *cpuInstrsLbl;
|
||||||
QFont font;
|
QFont font;
|
||||||
|
|
||||||
|
dbg_asm_entry_t *asmPC;
|
||||||
|
std::vector <dbg_asm_entry_t*> asmEntry;
|
||||||
|
|
||||||
|
char displayROMoffsets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -159,11 +159,6 @@ FCEUD_GetTimeFreq(void)
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUD_DebugBreakpoint( int addr )
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize all of the subsystem drivers: video, audio, and joystick.
|
* Initialize all of the subsystem drivers: video, audio, and joystick.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue