Mesen-SX/Core/CodeDataLogger.cpp

237 lines
4.7 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "CodeDataLogger.h"
#include "../Utilities/VirtualFile.h"
2020-06-06 16:13:02 -04:00
CodeDataLogger::CodeDataLogger(uint32_t prgSize, CpuType cpuType)
{
2020-06-06 16:13:02 -04:00
_cpuType = cpuType;
_prgSize = prgSize;
_cdlData = new uint8_t[prgSize];
Reset();
}
CodeDataLogger::~CodeDataLogger()
{
delete[] _cdlData;
}
void CodeDataLogger::Reset()
{
_codeSize = 0;
_dataSize = 0;
memset(_cdlData, 0, _prgSize);
}
2020-06-06 16:13:02 -04:00
uint32_t CodeDataLogger::GetPrgSize()
{
return _prgSize;
}
bool CodeDataLogger::LoadCdlFile(string cdlFilepath, bool autoResetCdl, uint32_t romCrc)
{
VirtualFile cdlFile = cdlFilepath;
2020-12-19 23:30:09 +03:00
if (cdlFile.IsValid())
{
uint32_t fileSize = (uint32_t)cdlFile.GetSize();
vector<uint8_t> cdlData;
cdlFile.ReadFile(cdlData);
2020-12-19 23:30:09 +03:00
if (fileSize >= _prgSize)
{
Reset();
constexpr int headerSize = 9; //"CDLv2" + 4-byte CRC32 value
2020-12-19 23:30:09 +03:00
if (memcmp(cdlData.data(), "CDLv2", 5) == 0)
{
uint32_t savedCrc = cdlData[5] | (cdlData[6] << 8) | (cdlData[7] << 16) | (cdlData[8] << 24);
2020-12-19 23:30:09 +03:00
if ((autoResetCdl && savedCrc != romCrc) || fileSize < _prgSize + headerSize)
{
memset(_cdlData, 0, _prgSize);
2020-12-19 23:30:09 +03:00
}
else
{
memcpy(_cdlData, cdlData.data() + headerSize, _prgSize);
}
2020-12-19 23:30:09 +03:00
}
else
{
//Older CRC-less CDL file, use as-is without checking CRC to avoid data loss
memcpy(_cdlData, cdlData.data(), _prgSize);
}
CalculateStats();
2020-12-19 23:30:09 +03:00
return true;
}
}
return false;
}
bool CodeDataLogger::SaveCdlFile(string cdlFilepath, uint32_t romCrc)
{
ofstream cdlFile(cdlFilepath, ios::out | ios::binary);
2020-12-19 23:30:09 +03:00
if (cdlFile)
{
cdlFile.write("CDLv2", 5);
cdlFile.put(romCrc & 0xFF);
cdlFile.put((romCrc >> 8) & 0xFF);
cdlFile.put((romCrc >> 16) & 0xFF);
cdlFile.put((romCrc >> 24) & 0xFF);
cdlFile.write((char*)_cdlData, _prgSize);
cdlFile.close();
return true;
}
return false;
}
void CodeDataLogger::CalculateStats()
{
uint32_t codeSize = 0;
uint32_t dataSize = 0;
2020-12-19 23:30:09 +03:00
for (int i = 0, len = _prgSize; i < len; i++)
{
if (IsCode(i))
{
codeSize++;
2020-12-19 23:30:09 +03:00
}
else if (IsData(i))
{
dataSize++;
}
}
_codeSize = codeSize;
_dataSize = dataSize;
}
void CodeDataLogger::SetFlags(int32_t absoluteAddr, uint8_t flags)
{
2020-12-19 23:30:09 +03:00
if (absoluteAddr >= 0 && absoluteAddr < (int32_t)_prgSize)
{
if ((_cdlData[absoluteAddr] & flags) != flags)
{
if (flags & CdlFlags::Code)
{
_cdlData[absoluteAddr] = flags | (_cdlData[absoluteAddr] & ~(CdlFlags::Data | CdlFlags::IndexMode8 |
CdlFlags::MemoryMode8));
}
else if (flags & CdlFlags::Data)
{
if (!IsCode(absoluteAddr))
{
_cdlData[absoluteAddr] |= flags;
}
2020-12-19 23:30:09 +03:00
}
else
{
_cdlData[absoluteAddr] |= flags;
}
}
}
}
CdlRatios CodeDataLogger::GetRatios()
{
CalculateStats();
CdlRatios ratios;
ratios.CodeRatio = (float)_codeSize / (float)_prgSize;
ratios.DataRatio = (float)_dataSize / (float)_prgSize;
ratios.PrgRatio = (float)(_codeSize + _dataSize) / (float)_prgSize;
return ratios;
}
bool CodeDataLogger::IsCode(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & CdlFlags::Code) != 0;
}
bool CodeDataLogger::IsJumpTarget(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & CdlFlags::JumpTarget) != 0;
}
bool CodeDataLogger::IsSubEntryPoint(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & CdlFlags::SubEntryPoint) != 0;
}
bool CodeDataLogger::IsData(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & CdlFlags::Data) != 0;
}
uint8_t CodeDataLogger::GetCpuFlags(uint32_t absoluteAddr)
{
return _cdlData[absoluteAddr] & (CdlFlags::MemoryMode8 | CdlFlags::IndexMode8);
}
2020-02-25 23:56:55 -05:00
CpuType CodeDataLogger::GetCpuType(uint32_t absoluteAddr)
{
2020-12-19 23:30:09 +03:00
if (_cpuType == CpuType::Gameboy)
{
2020-06-06 16:13:02 -04:00
return _cpuType;
2020-12-19 23:30:09 +03:00
}
else if (_cdlData[absoluteAddr] & CdlFlags::Gsu)
{
2020-02-25 23:56:55 -05:00
return CpuType::Gsu;
2020-12-19 23:30:09 +03:00
}
else if (_cdlData[absoluteAddr] & CdlFlags::Cx4)
{
2020-02-25 23:56:55 -05:00
return CpuType::Cx4;
}
return CpuType::Cpu;
}
2020-12-19 23:30:09 +03:00
void CodeDataLogger::SetCdlData(uint8_t* cdlData, uint32_t length)
{
2020-12-19 23:30:09 +03:00
if (length <= _prgSize)
{
memcpy(_cdlData, cdlData, length);
}
}
2020-12-19 23:30:09 +03:00
void CodeDataLogger::GetCdlData(uint32_t offset, uint32_t length, uint8_t* cdlData)
{
2020-02-25 23:56:55 -05:00
memcpy(cdlData, _cdlData + offset, length);
}
uint8_t CodeDataLogger::GetFlags(uint32_t addr)
{
return _cdlData[addr];
}
void CodeDataLogger::MarkBytesAs(uint32_t start, uint32_t end, uint8_t flags)
{
2020-12-19 23:30:09 +03:00
for (uint32_t i = start; i <= end; i++)
{
_cdlData[i] = (_cdlData[i] & 0xFC) | (int)flags;
}
}
void CodeDataLogger::StripData(uint8_t* romBuffer, CdlStripOption flag)
{
2020-12-19 23:30:09 +03:00
if (flag == CdlStripOption::StripUnused)
{
for (uint32_t i = 0; i < _prgSize; i++)
{
if (_cdlData[i] == 0)
{
romBuffer[i] = 0;
}
}
2020-12-19 23:30:09 +03:00
}
else if (flag == CdlStripOption::StripUsed)
{
for (uint32_t i = 0; i < _prgSize; i++)
{
if (_cdlData[i] != 0)
{
romBuffer[i] = 0;
}
}
}
2020-12-19 23:30:09 +03:00
}