From 9da84e16caf0955d71901731912555ee110cc3b8 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Wed, 30 Sep 2020 22:21:18 -0400 Subject: [PATCH] More setup of Qt Trace Logger window. --- src/drivers/Qt/TraceLogger.cpp | 327 +++++++++++++++++++++++++++++++++ src/drivers/Qt/TraceLogger.h | 16 ++ 2 files changed, 343 insertions(+) diff --git a/src/drivers/Qt/TraceLogger.cpp b/src/drivers/Qt/TraceLogger.cpp index 4c921e3f..fe2b75b5 100644 --- a/src/drivers/Qt/TraceLogger.cpp +++ b/src/drivers/Qt/TraceLogger.cpp @@ -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>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) +{ + } //---------------------------------------------------- diff --git a/src/drivers/Qt/TraceLogger.h b/src/drivers/Qt/TraceLogger.h index f27ea065..bda8c91f 100644 --- a/src/drivers/Qt/TraceLogger.h +++ b/src/drivers/Qt/TraceLogger.h @@ -14,8 +14,20 @@ #include #include #include +#include #include +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: