More setup of Qt Trace Logger window.
This commit is contained in:
parent
c288c60c68
commit
9da84e16ca
|
@ -10,9 +10,11 @@
|
|||
#include "../../cart.h"
|
||||
#include "../../x6502.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../asm.h"
|
||||
#include "../../ppu.h"
|
||||
#include "../../ines.h"
|
||||
#include "../../nsf.h"
|
||||
#include "../../movie.h"
|
||||
|
||||
#include "Qt/ConsoleUtilities.h"
|
||||
#include "Qt/TraceLogger.h"
|
||||
|
@ -22,6 +24,53 @@
|
|||
#include "Qt/config.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)
|
||||
: QDialog( parent )
|
||||
|
@ -36,7 +85,17 @@ TraceLoggerDialog_t::TraceLoggerDialog_t(QWidget *parent)
|
|||
|
||||
mainLayout = new QVBoxLayout();
|
||||
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 );
|
||||
|
||||
lbl = new QLabel( tr("Lines") );
|
||||
|
@ -127,5 +186,273 @@ void TraceLoggerDialog_t::closeWindow(void)
|
|||
printf("Trace Logger Close Window\n");
|
||||
done(0);
|
||||
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 <QTimer>
|
||||
#include <QGroupBox>
|
||||
#include <QScrollBar>
|
||||
#include <QCloseEvent>
|
||||
|
||||
class QTraceLogView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QTraceLogView(QWidget *parent = 0);
|
||||
~QTraceLogView(void);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
class TraceLoggerDialog_t : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -47,6 +59,10 @@ class TraceLoggerDialog_t : public QDialog
|
|||
QPushButton *selLogFileButton;
|
||||
QPushButton *startStopButton;
|
||||
|
||||
QTraceLogView *traceView;
|
||||
QScrollBar *hbar;
|
||||
QScrollBar *vbar;
|
||||
|
||||
void closeEvent(QCloseEvent *bar);
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue