More setup of Qt Trace Logger window.
This commit is contained in:
parent
c288c60c68
commit
9da84e16ca
|
@ -10,9 +10,11 @@
|
||||||
#include "../../cart.h"
|
#include "../../cart.h"
|
||||||
#include "../../x6502.h"
|
#include "../../x6502.h"
|
||||||
#include "../../debug.h"
|
#include "../../debug.h"
|
||||||
|
#include "../../asm.h"
|
||||||
#include "../../ppu.h"
|
#include "../../ppu.h"
|
||||||
#include "../../ines.h"
|
#include "../../ines.h"
|
||||||
#include "../../nsf.h"
|
#include "../../nsf.h"
|
||||||
|
#include "../../movie.h"
|
||||||
|
|
||||||
#include "Qt/ConsoleUtilities.h"
|
#include "Qt/ConsoleUtilities.h"
|
||||||
#include "Qt/TraceLogger.h"
|
#include "Qt/TraceLogger.h"
|
||||||
|
@ -22,6 +24,53 @@
|
||||||
#include "Qt/config.h"
|
#include "Qt/config.h"
|
||||||
#include "Qt/fceuWrapper.h"
|
#include "Qt/fceuWrapper.h"
|
||||||
|
|
||||||
|
#define LOG_REGISTERS 0x00000001
|
||||||
|
#define LOG_PROCESSOR_STATUS 0x00000002
|
||||||
|
#define LOG_NEW_INSTRUCTIONS 0x00000004
|
||||||
|
#define LOG_NEW_DATA 0x00000008
|
||||||
|
#define LOG_TO_THE_LEFT 0x00000010
|
||||||
|
#define LOG_FRAMES_COUNT 0x00000020
|
||||||
|
#define LOG_MESSAGES 0x00000040
|
||||||
|
#define LOG_BREAKPOINTS 0x00000080
|
||||||
|
#define LOG_SYMBOLIC 0x00000100
|
||||||
|
#define LOG_CODE_TABBING 0x00000200
|
||||||
|
#define LOG_CYCLES_COUNT 0x00000400
|
||||||
|
#define LOG_INSTRUCTIONS_COUNT 0x00000800
|
||||||
|
#define LOG_BANK_NUMBER 0x00001000
|
||||||
|
|
||||||
|
#define LOG_LINE_MAX_LEN 160
|
||||||
|
// Frames count - 1+6+1 symbols
|
||||||
|
// Cycles count - 1+11+1 symbols
|
||||||
|
// Instructions count - 1+11+1 symbols
|
||||||
|
// AXYS state - 20
|
||||||
|
// Processor status - 11
|
||||||
|
// Tabs - 31
|
||||||
|
// Address - 6
|
||||||
|
// Data - 10
|
||||||
|
// Disassembly - 45
|
||||||
|
// EOL (/0) - 1
|
||||||
|
// ------------------------
|
||||||
|
// 148 symbols total
|
||||||
|
#define LOG_AXYSTATE_MAX_LEN 21
|
||||||
|
#define LOG_PROCSTATUS_MAX_LEN 12
|
||||||
|
#define LOG_TABS_MASK 31
|
||||||
|
#define LOG_ADDRESS_MAX_LEN 13
|
||||||
|
#define LOG_DATA_MAX_LEN 11
|
||||||
|
#define LOG_DISASSEMBLY_MAX_LEN 46
|
||||||
|
#define NL_MAX_MULTILINE_COMMENT_LEN 1000
|
||||||
|
|
||||||
|
static int logging = 0;
|
||||||
|
static int logging_options = LOG_REGISTERS | LOG_PROCESSOR_STATUS | LOG_TO_THE_LEFT | LOG_MESSAGES | LOG_BREAKPOINTS | LOG_CODE_TABBING;
|
||||||
|
static char str_axystate[LOG_AXYSTATE_MAX_LEN] = {0}, str_procstatus[LOG_PROCSTATUS_MAX_LEN] = {0};
|
||||||
|
static char str_tabs[LOG_TABS_MASK+1] = {0}, str_address[LOG_ADDRESS_MAX_LEN] = {0}, str_data[LOG_DATA_MAX_LEN] = {0}, str_disassembly[LOG_DISASSEMBLY_MAX_LEN] = {0};
|
||||||
|
static char str_result[LOG_LINE_MAX_LEN] = {0};
|
||||||
|
static char str_temp[LOG_LINE_MAX_LEN] = {0};
|
||||||
|
static char str_decoration[NL_MAX_MULTILINE_COMMENT_LEN + 10] = {0};
|
||||||
|
//static char str_decoration_comment[NL_MAX_MULTILINE_COMMENT_LEN + 10] = {0};
|
||||||
|
//static char* tracer_decoration_comment = 0;
|
||||||
|
//static char* tracer_decoration_comment_end_pos = 0;
|
||||||
|
static int oldcodecount = 0, olddatacount = 0;
|
||||||
|
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
TraceLoggerDialog_t::TraceLoggerDialog_t(QWidget *parent)
|
TraceLoggerDialog_t::TraceLoggerDialog_t(QWidget *parent)
|
||||||
: QDialog( parent )
|
: QDialog( parent )
|
||||||
|
@ -36,7 +85,17 @@ TraceLoggerDialog_t::TraceLoggerDialog_t(QWidget *parent)
|
||||||
|
|
||||||
mainLayout = new QVBoxLayout();
|
mainLayout = new QVBoxLayout();
|
||||||
grid = new QGridLayout();
|
grid = new QGridLayout();
|
||||||
|
mainLayout->addLayout( grid );
|
||||||
|
|
||||||
|
traceView = new QTraceLogView(this);
|
||||||
|
vbar = new QScrollBar( Qt::Vertical, this );
|
||||||
|
hbar = new QScrollBar( Qt::Horizontal, this );
|
||||||
|
|
||||||
|
grid->addWidget( traceView, 0, 0);
|
||||||
|
grid->addWidget( vbar , 0, 1 );
|
||||||
|
grid->addWidget( hbar , 1, 0 );
|
||||||
|
|
||||||
|
grid = new QGridLayout();
|
||||||
mainLayout->addLayout( grid );
|
mainLayout->addLayout( grid );
|
||||||
|
|
||||||
lbl = new QLabel( tr("Lines") );
|
lbl = new QLabel( tr("Lines") );
|
||||||
|
@ -127,5 +186,273 @@ void TraceLoggerDialog_t::closeWindow(void)
|
||||||
printf("Trace Logger Close Window\n");
|
printf("Trace Logger Close Window\n");
|
||||||
done(0);
|
done(0);
|
||||||
deleteLater();
|
deleteLater();
|
||||||
|
}
|
||||||
|
//todo: really speed this up
|
||||||
|
void FCEUD_TraceInstruction(uint8 *opcode, int size)
|
||||||
|
{
|
||||||
|
if (!logging)
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned int addr = X.PC;
|
||||||
|
uint8 tmp;
|
||||||
|
static int unloggedlines = 0;
|
||||||
|
|
||||||
|
// if instruction executed from the RAM, skip this, log all instead
|
||||||
|
// TODO: loops folding mame-lyke style
|
||||||
|
if (GetPRGAddress(addr) != -1)
|
||||||
|
{
|
||||||
|
if (((logging_options & LOG_NEW_INSTRUCTIONS) && (oldcodecount != codecount)) ||
|
||||||
|
((logging_options & LOG_NEW_DATA) && (olddatacount != datacount)))
|
||||||
|
{
|
||||||
|
//something new was logged
|
||||||
|
oldcodecount = codecount;
|
||||||
|
olddatacount = datacount;
|
||||||
|
if(unloggedlines > 0)
|
||||||
|
{
|
||||||
|
sprintf(str_result, "(%d lines skipped)", unloggedlines);
|
||||||
|
//OutputLogLine(str_result);
|
||||||
|
unloggedlines = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((logging_options & LOG_NEW_INSTRUCTIONS) ||
|
||||||
|
(logging_options & LOG_NEW_DATA))
|
||||||
|
{
|
||||||
|
if (FCEUI_GetLoggingCD())
|
||||||
|
{
|
||||||
|
unloggedlines++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((addr + size) > 0xFFFF)
|
||||||
|
{
|
||||||
|
sprintf(str_data, "%02X ", opcode[0]);
|
||||||
|
sprintf(str_disassembly, "OVERFLOW");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char* a = 0;
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sprintf(str_data, "%02X ", opcode[0]);
|
||||||
|
sprintf(str_disassembly,"UNDEFINED");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
sprintf(str_data, "%02X ", opcode[0]);
|
||||||
|
a = Disassemble(addr + 1, opcode);
|
||||||
|
// special case: an RTS opcode
|
||||||
|
if (opcode[0] == 0x60)
|
||||||
|
{
|
||||||
|
// add the beginning address of the subroutine that we exit from
|
||||||
|
unsigned int caller_addr = GetMem(((X.S) + 1)|0x0100) + (GetMem(((X.S) + 2)|0x0100) << 8) - 0x2;
|
||||||
|
if (GetMem(caller_addr) == 0x20)
|
||||||
|
{
|
||||||
|
// this was a JSR instruction - take the subroutine address from it
|
||||||
|
unsigned int call_addr = GetMem(caller_addr + 1) + (GetMem(caller_addr + 2) << 8);
|
||||||
|
sprintf(str_decoration, " (from $%04X)", call_addr);
|
||||||
|
strcat(a, str_decoration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
sprintf(str_data, "%02X %02X ", opcode[0],opcode[1]);
|
||||||
|
a = Disassemble(addr + 2, opcode);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
sprintf(str_data, "%02X %02X %02X ", opcode[0],opcode[1],opcode[2]);
|
||||||
|
a = Disassemble(addr + 3, opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a)
|
||||||
|
{
|
||||||
|
//if (logging_options & LOG_SYMBOLIC)
|
||||||
|
//{
|
||||||
|
// loadNameFiles();
|
||||||
|
// tempAddressesLog.resize(0);
|
||||||
|
// // Insert Name and Comment lines if needed
|
||||||
|
// Name* node = findNode(getNamesPointerForAddress(addr), addr);
|
||||||
|
// if (node)
|
||||||
|
// {
|
||||||
|
// if (node->name)
|
||||||
|
// {
|
||||||
|
// strcpy(str_decoration, node->name);
|
||||||
|
// strcat(str_decoration, ":");
|
||||||
|
// tempAddressesLog.push_back(addr);
|
||||||
|
// //OutputLogLine(str_decoration, &tempAddressesLog);
|
||||||
|
// }
|
||||||
|
// if (node->comment)
|
||||||
|
// {
|
||||||
|
// // make a copy
|
||||||
|
// strcpy(str_decoration_comment, node->comment);
|
||||||
|
// strcat(str_decoration_comment, "\r\n");
|
||||||
|
// tracer_decoration_comment = str_decoration_comment;
|
||||||
|
// // divide the str_decoration_comment into strings (Comment1, Comment2, ...)
|
||||||
|
// char* tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment, "\r\n");
|
||||||
|
// while (tracer_decoration_comment_end_pos)
|
||||||
|
// {
|
||||||
|
// tracer_decoration_comment_end_pos[0] = 0; // set \0 instead of \r
|
||||||
|
// strcpy(str_decoration, "; ");
|
||||||
|
// strcat(str_decoration, tracer_decoration_comment);
|
||||||
|
// //OutputLogLine(str_decoration, &tempAddressesLog);
|
||||||
|
// tracer_decoration_comment_end_pos += 2;
|
||||||
|
// tracer_decoration_comment = tracer_decoration_comment_end_pos;
|
||||||
|
// tracer_decoration_comment_end_pos = strstr(tracer_decoration_comment_end_pos, "\r\n");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //replaceNames(ramBankNames, a, &tempAddressesLog);
|
||||||
|
// //for(int i=0;i<ARRAY_SIZE(pageNames);i++)
|
||||||
|
// //{
|
||||||
|
// // replaceNames(pageNames[i], a, &tempAddressesLog);
|
||||||
|
// //}
|
||||||
|
//}
|
||||||
|
strncpy(str_disassembly, a, LOG_DISASSEMBLY_MAX_LEN);
|
||||||
|
str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 1 && GetMem(addr) == 0x60)
|
||||||
|
{
|
||||||
|
// special case: an RTS opcode
|
||||||
|
// add "----------" to emphasize the end of subroutine
|
||||||
|
static const char* emphasize = " -------------------------------------------------------------------------------------------------------------------------";
|
||||||
|
strncat(str_disassembly, emphasize, LOG_DISASSEMBLY_MAX_LEN - strlen(str_disassembly) - 1);
|
||||||
|
}
|
||||||
|
// stretch the disassembly string out if we have to output other stuff.
|
||||||
|
if ((logging_options & (LOG_REGISTERS|LOG_PROCESSOR_STATUS)) && !(logging_options & LOG_TO_THE_LEFT))
|
||||||
|
{
|
||||||
|
for (int i = strlen(str_disassembly); i < (LOG_DISASSEMBLY_MAX_LEN - 1); ++i)
|
||||||
|
str_disassembly[i] = ' ';
|
||||||
|
str_disassembly[LOG_DISASSEMBLY_MAX_LEN - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start filling the str_temp line: Frame count, Cycles count, Instructions count, AXYS state, Processor status, Tabs, Address, Data, Disassembly
|
||||||
|
if (logging_options & LOG_FRAMES_COUNT)
|
||||||
|
{
|
||||||
|
sprintf(str_result, "f%-6u ", currFrameCounter);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
str_result[0] = 0;
|
||||||
|
}
|
||||||
|
if (logging_options & LOG_CYCLES_COUNT)
|
||||||
|
{
|
||||||
|
int64 counter_value = timestampbase + (uint64)timestamp - total_cycles_base;
|
||||||
|
if (counter_value < 0) // sanity check
|
||||||
|
{
|
||||||
|
ResetDebugStatisticsCounters();
|
||||||
|
counter_value = 0;
|
||||||
|
}
|
||||||
|
sprintf(str_temp, "c%-11llu ", counter_value);
|
||||||
|
strcat(str_result, str_temp);
|
||||||
|
}
|
||||||
|
if (logging_options & LOG_INSTRUCTIONS_COUNT)
|
||||||
|
{
|
||||||
|
sprintf(str_temp, "i%-11llu ", total_instructions);
|
||||||
|
strcat(str_result, str_temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logging_options & LOG_REGISTERS)
|
||||||
|
{
|
||||||
|
sprintf(str_axystate,"A:%02X X:%02X Y:%02X S:%02X ",(X.A),(X.X),(X.Y),(X.S));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logging_options & LOG_PROCESSOR_STATUS)
|
||||||
|
{
|
||||||
|
tmp = X.P^0xFF;
|
||||||
|
sprintf(str_procstatus,"P:%c%c%c%c%c%c%c%c ",
|
||||||
|
'N'|(tmp&0x80)>>2,
|
||||||
|
'V'|(tmp&0x40)>>1,
|
||||||
|
'U'|(tmp&0x20),
|
||||||
|
'B'|(tmp&0x10)<<1,
|
||||||
|
'D'|(tmp&0x08)<<2,
|
||||||
|
'I'|(tmp&0x04)<<3,
|
||||||
|
'Z'|(tmp&0x02)<<4,
|
||||||
|
'C'|(tmp&0x01)<<5
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logging_options & LOG_TO_THE_LEFT)
|
||||||
|
{
|
||||||
|
if (logging_options & LOG_REGISTERS)
|
||||||
|
{
|
||||||
|
strcat(str_result, str_axystate);
|
||||||
|
}
|
||||||
|
if (logging_options & LOG_PROCESSOR_STATUS)
|
||||||
|
{
|
||||||
|
strcat(str_result, str_procstatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logging_options & LOG_CODE_TABBING)
|
||||||
|
{
|
||||||
|
// add spaces at the beginning of the line according to stack pointer
|
||||||
|
int spaces = (0xFF - X.S) & LOG_TABS_MASK;
|
||||||
|
for (int i = 0; i < spaces; i++)
|
||||||
|
{
|
||||||
|
str_tabs[i] = ' ';
|
||||||
|
}
|
||||||
|
str_tabs[spaces] = 0;
|
||||||
|
strcat(str_result, str_tabs);
|
||||||
|
}
|
||||||
|
else if (logging_options & LOG_TO_THE_LEFT)
|
||||||
|
{
|
||||||
|
strcat(str_result, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logging_options & LOG_BANK_NUMBER)
|
||||||
|
{
|
||||||
|
if (addr >= 0x8000)
|
||||||
|
{
|
||||||
|
sprintf(str_address, "$%02X:%04X: ", getBank(addr), addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(str_address, " $%04X: ", addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(str_address, "$%04X: ", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(str_result, str_address);
|
||||||
|
strcat(str_result, str_data);
|
||||||
|
strcat(str_result, str_disassembly);
|
||||||
|
|
||||||
|
if (!(logging_options & LOG_TO_THE_LEFT))
|
||||||
|
{
|
||||||
|
if (logging_options & LOG_REGISTERS)
|
||||||
|
{
|
||||||
|
strcat(str_result, str_axystate);
|
||||||
|
}
|
||||||
|
if (logging_options & LOG_PROCESSOR_STATUS)
|
||||||
|
{
|
||||||
|
strcat(str_result, str_procstatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//OutputLogLine(str_result, &tempAddressesLog);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
QTraceLogView::QTraceLogView(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
QTraceLogView::~QTraceLogView(void)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
|
|
@ -14,8 +14,20 @@
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
|
#include <QScrollBar>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
|
||||||
|
class QTraceLogView : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QTraceLogView(QWidget *parent = 0);
|
||||||
|
~QTraceLogView(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
class TraceLoggerDialog_t : public QDialog
|
class TraceLoggerDialog_t : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -47,6 +59,10 @@ class TraceLoggerDialog_t : public QDialog
|
||||||
QPushButton *selLogFileButton;
|
QPushButton *selLogFileButton;
|
||||||
QPushButton *startStopButton;
|
QPushButton *startStopButton;
|
||||||
|
|
||||||
|
QTraceLogView *traceView;
|
||||||
|
QScrollBar *hbar;
|
||||||
|
QScrollBar *vbar;
|
||||||
|
|
||||||
void closeEvent(QCloseEvent *bar);
|
void closeEvent(QCloseEvent *bar);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue