2016-01-10 19:56:40 -05:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "TraceLogger.h"
|
|
|
|
#include "DisassemblyInfo.h"
|
|
|
|
#include "DebugState.h"
|
2016-06-26 09:01:23 -04:00
|
|
|
#include "Console.h"
|
2016-11-19 19:21:28 -05:00
|
|
|
#include "MemoryManager.h"
|
2016-01-10 19:56:40 -05:00
|
|
|
|
2016-02-13 22:19:42 -05:00
|
|
|
TraceLogger *TraceLogger::_instance = nullptr;
|
|
|
|
|
2016-11-19 19:21:28 -05:00
|
|
|
TraceLogger::TraceLogger(string outputFilepath, shared_ptr<MemoryManager> memoryManager, TraceLoggerOptions options)
|
2016-01-10 19:56:40 -05:00
|
|
|
{
|
2016-11-19 19:21:28 -05:00
|
|
|
_memoryManager = memoryManager;
|
2016-01-10 19:56:40 -05:00
|
|
|
_outputFile.open(outputFilepath, ios::out | ios::binary);
|
|
|
|
_options = options;
|
2016-06-01 21:01:04 -04:00
|
|
|
_firstLine = true;
|
2016-02-13 22:19:42 -05:00
|
|
|
_instance = this;
|
2016-01-10 19:56:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
TraceLogger::~TraceLogger()
|
|
|
|
{
|
2016-06-26 09:01:23 -04:00
|
|
|
Console::Pause();
|
2016-02-13 22:19:42 -05:00
|
|
|
if(_instance == this) {
|
|
|
|
_instance = nullptr;
|
|
|
|
}
|
2016-06-26 09:01:23 -04:00
|
|
|
|
|
|
|
if(_outputFile) {
|
|
|
|
_outputFile.close();
|
|
|
|
}
|
|
|
|
Console::Resume();
|
2016-02-13 22:19:42 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void TraceLogger::LogStatic(string log)
|
|
|
|
{
|
2016-09-03 21:52:59 -04:00
|
|
|
if(_instance && _instance->_options.ShowExtraInfo) {
|
2016-06-01 21:01:04 -04:00
|
|
|
_instance->_outputFile << " - [" << log << " - Cycle: " << std::to_string(CPU::GetCycleCount()) << "]";
|
2016-02-13 22:19:42 -05:00
|
|
|
}
|
2016-01-10 19:56:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void TraceLogger::Log(DebugState &state, shared_ptr<DisassemblyInfo> disassemblyInfo)
|
|
|
|
{
|
2016-06-26 09:01:23 -04:00
|
|
|
if(disassemblyInfo) {
|
|
|
|
State &cpuState = state.CPU;
|
|
|
|
PPUDebugState &ppuState = state.PPU;
|
2016-01-10 19:56:40 -05:00
|
|
|
|
2016-06-26 09:01:23 -04:00
|
|
|
string disassembly = disassemblyInfo->ToString(cpuState.DebugPC);
|
|
|
|
auto separatorPosition = disassembly.begin() + disassembly.find_first_of(':', 0);
|
|
|
|
string byteCode(disassembly.begin(), separatorPosition);
|
|
|
|
byteCode.erase(std::remove(byteCode.begin(), byteCode.end(), '$'), byteCode.end());
|
|
|
|
string assemblyCode(separatorPosition + 1, disassembly.end());
|
2016-06-01 21:01:04 -04:00
|
|
|
|
2016-06-26 09:01:23 -04:00
|
|
|
//Roughly adjust PPU cycle & scanline to take into account the PPU already ran 3 cycles by the time we get here
|
|
|
|
short ppuCycle = (short)ppuState.Cycle - 3;
|
|
|
|
short scanline = (short)ppuState.Scanline;
|
|
|
|
if(ppuCycle < 0) {
|
|
|
|
ppuCycle = 341 + ppuCycle;
|
|
|
|
scanline--;
|
|
|
|
if(scanline < -1) {
|
|
|
|
scanline = EmulationSettings::GetNesModel() == NesModel::NTSC ? 260 : 310;
|
|
|
|
}
|
2016-06-01 21:01:04 -04:00
|
|
|
}
|
|
|
|
|
2016-06-26 09:01:23 -04:00
|
|
|
if(!_firstLine) {
|
|
|
|
_outputFile << std::endl;
|
|
|
|
}
|
2016-01-10 19:56:40 -05:00
|
|
|
|
2016-09-03 21:52:59 -04:00
|
|
|
_outputFile << std::uppercase << std::hex << std::setfill('0') << std::setw(4) << std::right << (short)cpuState.DebugPC << " ";
|
|
|
|
|
|
|
|
if(_options.ShowByteCode) {
|
|
|
|
_outputFile << std::setfill(' ') << std::setw(10) << std::left << byteCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
int indentLevel = 0;
|
|
|
|
if(_options.IndentCode) {
|
|
|
|
indentLevel = 0xFF - state.CPU.SP;
|
|
|
|
_outputFile << std::string(indentLevel, ' ');
|
|
|
|
}
|
|
|
|
|
2016-11-19 19:21:28 -05:00
|
|
|
string codeString = assemblyCode + (_options.ShowEffectiveAddresses ? disassemblyInfo->GetEffectiveAddress(state.CPU, _memoryManager) : "");
|
|
|
|
_outputFile << std::setfill(' ') << std::setw(32 - indentLevel) << std::left << codeString;
|
2016-09-03 21:52:59 -04:00
|
|
|
|
|
|
|
if(_options.ShowRegisters) {
|
|
|
|
_outputFile << std::setfill('0')
|
|
|
|
<< "A:" << std::right << std::setw(2) << (short)cpuState.A
|
|
|
|
<< " X:" << std::setw(2) << (short)cpuState.X
|
|
|
|
<< " Y:" << std::setw(2) << (short)cpuState.Y
|
|
|
|
<< " P:" << std::setw(2) << (short)cpuState.PS
|
|
|
|
<< " SP:" << std::setw(2) << (short)cpuState.SP;
|
|
|
|
}
|
|
|
|
|
|
|
|
_outputFile << std::dec << std::setfill(' ');
|
|
|
|
|
|
|
|
if(_options.ShowPpuCycles) {
|
|
|
|
_outputFile << std::right << " CYC:" << std::setw(3) << ppuCycle;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_options.ShowPpuScanline) {
|
|
|
|
_outputFile << std::left << " SL:" << std::setw(3) << scanline;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_options.ShowPpuFrames) {
|
|
|
|
_outputFile << " FC:" << ppuState.FrameCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_options.ShowCpuCycles) {
|
|
|
|
_outputFile << " CPU Cycle:" << cpuState.CycleCount;
|
|
|
|
}
|
2016-11-19 19:21:28 -05:00
|
|
|
|
2016-06-26 09:01:23 -04:00
|
|
|
_firstLine = false;
|
|
|
|
}
|
2016-01-10 19:56:40 -05:00
|
|
|
}
|