diff --git a/src/debug.cpp b/src/debug.cpp index fad9c6f6..eef528e5 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -19,6 +19,14 @@ unsigned int debuggerPageSize = 14; int vblankScanLines = 0; //Used to calculate scanlines 240-261 (vblank) int vblankPixel = 0; //Used to calculate the pixels in vblank + +struct TraceInstructionCallback +{ + void (*func)(uint8 *opcode, int size) = nullptr; + TraceInstructionCallback* next = nullptr; +}; +static TraceInstructionCallback* traceInstructionCB = nullptr; + int offsetStringToInt(unsigned int type, const char* offsetBuffer, bool *conversionOk) { int offset = -1; @@ -989,5 +997,82 @@ void DebugCycle() if(debug_loggingCD) LogCDData(opcode, A, size); +#ifdef __WIN_DRIVER__ FCEUD_TraceInstruction(opcode, size); +#else + // Use callback pointer that can be null checked, this saves on the overhead + // of calling a function for every instruction when we aren't tracing. + if (traceInstructionCB != nullptr) + { + auto* cb = traceInstructionCB; + while (cb != nullptr) + { + cb->func(opcode, size); + cb = cb->next; + } + } +#endif } + +void* FCEUI_TraceInstructionRegister( void (*func)(uint8*,int) ) +{ + TraceInstructionCallback* cb = nullptr; + + if (traceInstructionCB == nullptr) + { + cb = traceInstructionCB = new TraceInstructionCallback(); + cb->func = func; + } + else + { + cb = traceInstructionCB; + + while (cb != nullptr) + { + if (cb->func == func) + { + // This function has already been registered, don't double add. + return nullptr; + } + if (cb->next == nullptr) + { + auto* newCB = new TraceInstructionCallback(); + newCB->func = func; + cb->next = newCB; + return newCB; + } + cb = cb->next; + } + } + return cb; +} + +bool FCEUI_TraceInstructionUnregisterHandle( void* handle ) +{ + TraceInstructionCallback* cb, *cb_prev, *cb_handle; + + cb_handle = static_cast(handle); + cb_prev = nullptr; + cb = traceInstructionCB; + + while (cb != nullptr) + { + if (cb == cb_handle) + { // Match we are going to remove from list and delete + if (cb_prev != nullptr) + { + cb_prev = cb->next; + } + else + { + traceInstructionCB = cb->next; + } + delete cb; + return true; + } + cb_prev = cb; + cb = cb->next; + } + return false; +} + diff --git a/src/debug.h b/src/debug.h index 708c12ef..f8805a32 100644 --- a/src/debug.h +++ b/src/debug.h @@ -175,4 +175,7 @@ DebuggerState &FCEUI_Debugger(); int offsetStringToInt(unsigned int type, const char* offsetBuffer, bool *conversionOk = nullptr); unsigned int NewBreak(const char* name, int start, int end, unsigned int type, const char* condition, unsigned int num, bool enable); +void* FCEUI_TraceInstructionRegister( void (*func)(uint8*,int) ); +bool FCEUI_TraceInstructionUnregisterHandle( void* handle ); + #endif diff --git a/src/drivers/Qt/NetPlay.cpp b/src/drivers/Qt/NetPlay.cpp index fb0eff0d..e98db8eb 100644 --- a/src/drivers/Qt/NetPlay.cpp +++ b/src/drivers/Qt/NetPlay.cpp @@ -41,6 +41,7 @@ //--- NetPlay State Monitoring Metrics //----------------------------------------------------------------------------- static uint32_t opsCrc32 = 0; +static void *traceRegistrationHandle = nullptr; struct NetPlayFrameData { @@ -202,6 +203,12 @@ int NetPlayServer::Create(QObject *parent) printf("Error Creating Netplay Server!!!\n"); } } + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle == nullptr) + { + traceRegistrationHandle = FCEUI_TraceInstructionRegister( NetPlayTraceInstruction ); + } + FCEU_WRAPPER_UNLOCK(); return 0; } @@ -213,6 +220,16 @@ int NetPlayServer::Destroy() delete server; server = nullptr; } + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle != nullptr) + { + if ( !FCEUI_TraceInstructionUnregisterHandle( traceRegistrationHandle ) ) + { + printf("Unregister Trace Callback Error\n"); + } + traceRegistrationHandle = nullptr; + } + FCEU_WRAPPER_UNLOCK(); return 0; } @@ -890,6 +907,12 @@ int NetPlayClient::Create(QObject *parent) printf("Error Creating Netplay Client!!!\n"); } } + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle == nullptr) + { + traceRegistrationHandle = FCEUI_TraceInstructionRegister( NetPlayTraceInstruction ); + } + FCEU_WRAPPER_UNLOCK(); return 0; } @@ -901,6 +924,16 @@ int NetPlayClient::Destroy() delete client; client = nullptr; } + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle != nullptr) + { + if ( !FCEUI_TraceInstructionUnregisterHandle( traceRegistrationHandle ) ) + { + printf("Unregister Trace Callback Error\n"); + } + traceRegistrationHandle = nullptr; + } + FCEU_WRAPPER_UNLOCK(); return 0; } //----------------------------------------------------------------------------- @@ -2181,6 +2214,6 @@ void NetPlayOnFrameBegin() netPlayFrameData.push( data ); - //printf("Frame: %u Ops:%08X \n", data.frameNum, data.opsCrc32 ); + //printf("Frame: %u Ops:%08X Ram:%08X\n", data.frameNum, data.opsCrc32, data.ramCrc32 ); } //---------------------------------------------------------------------------- diff --git a/src/drivers/Qt/TraceLogger.cpp b/src/drivers/Qt/TraceLogger.cpp index 55a01fe7..cea818c7 100644 --- a/src/drivers/Qt/TraceLogger.cpp +++ b/src/drivers/Qt/TraceLogger.cpp @@ -131,6 +131,7 @@ static HANDLE logFile = INVALID_HANDLE_VALUE; static int logFile = -1; #endif static std::string logFilePath; +static void* traceRegistrationHandle = nullptr; //---------------------------------------------------- static void initLogOption( const char *name, int bitmask ) { @@ -524,6 +525,16 @@ void TraceLoggerDialog_t::toggleLoggingOnOff(void) diskThread->quit(); diskThread->wait(1000); + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle != nullptr) + { + if ( !FCEUI_TraceInstructionUnregisterHandle( traceRegistrationHandle ) ) + { + printf("Unregister Trace Callback Error\n"); + } + traceRegistrationHandle = nullptr; + } + FCEU_WRAPPER_UNLOCK(); traceView->update(); } else @@ -540,7 +551,14 @@ void TraceLoggerDialog_t::toggleLoggingOnOff(void) pushMsgToLogBuffer("Log Start"); startStopButton->setText(tr("Stop Logging")); startStopButton->setIcon( style()->standardIcon( QStyle::SP_MediaStop ) ); + + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle == nullptr) + { + traceRegistrationHandle = FCEUI_TraceInstructionRegister( FCEUD_TraceInstruction ); + } logging = 1; + FCEU_WRAPPER_UNLOCK(); } } //---------------------------------------------------- @@ -1153,7 +1171,13 @@ int FCEUD_TraceLoggerStart(void) { initTraceLogBuffer(1000000); } + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle == nullptr) + { + traceRegistrationHandle = FCEUI_TraceInstructionRegister( FCEUD_TraceInstruction ); + } logging = 1; + FCEU_WRAPPER_UNLOCK(); } return logging; } @@ -1174,6 +1198,17 @@ int FCEUD_TraceLoggerStop(void) msleep(1); pushMsgToLogBuffer("Logging Finished"); } + FCEU_WRAPPER_LOCK(); + if (traceRegistrationHandle != nullptr) + { + if ( !FCEUI_TraceInstructionUnregisterHandle( traceRegistrationHandle ) ) + { + printf("Unregister Trace Callback Error\n"); + } + traceRegistrationHandle = nullptr; + + } + FCEU_WRAPPER_UNLOCK(); return logging; } //----------------------------------------------------