2019-02-27 19:49:26 -05:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "CodeDataLogger.h"
|
2020-02-26 21:45:49 -05:00
|
|
|
#include "../Utilities/VirtualFile.h"
|
2019-02-27 19:49:26 -05:00
|
|
|
|
2020-06-06 16:13:02 -04:00
|
|
|
CodeDataLogger::CodeDataLogger(uint32_t prgSize, CpuType cpuType)
|
2019-02-27 19:49:26 -05:00
|
|
|
{
|
2020-06-06 16:13:02 -04:00
|
|
|
_cpuType = cpuType;
|
2019-02-27 19:49:26 -05:00
|
|
|
_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;
|
|
|
|
}
|
|
|
|
|
2020-02-26 21:45:49 -05:00
|
|
|
bool CodeDataLogger::LoadCdlFile(string cdlFilepath, bool autoResetCdl, uint32_t romCrc)
|
2019-02-27 19:49:26 -05:00
|
|
|
{
|
2020-02-26 21:45:49 -05:00
|
|
|
VirtualFile cdlFile = cdlFilepath;
|
|
|
|
if(cdlFile.IsValid()) {
|
|
|
|
uint32_t fileSize = (uint32_t)cdlFile.GetSize();
|
|
|
|
vector<uint8_t> cdlData;
|
|
|
|
cdlFile.ReadFile(cdlData);
|
2019-02-27 19:49:26 -05:00
|
|
|
|
2020-02-26 21:45:49 -05:00
|
|
|
if(fileSize >= _prgSize) {
|
2019-02-27 19:49:26 -05:00
|
|
|
Reset();
|
|
|
|
|
2020-02-26 21:45:49 -05:00
|
|
|
constexpr int headerSize = 9; //"CDLv2" + 4-byte CRC32 value
|
|
|
|
if(memcmp(cdlData.data(), "CDLv2", 5) == 0) {
|
|
|
|
uint32_t savedCrc = cdlData[5] | (cdlData[6] << 8) | (cdlData[7] << 16) | (cdlData[8] << 24);
|
2020-02-27 21:31:12 -05:00
|
|
|
if((autoResetCdl && savedCrc != romCrc) || fileSize < _prgSize + headerSize) {
|
2020-02-26 21:45:49 -05:00
|
|
|
memset(_cdlData, 0, _prgSize);
|
|
|
|
} else {
|
|
|
|
memcpy(_cdlData, cdlData.data() + headerSize, _prgSize);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//Older CRC-less CDL file, use as-is without checking CRC to avoid data loss
|
|
|
|
memcpy(_cdlData, cdlData.data(), _prgSize);
|
|
|
|
}
|
2019-02-27 19:49:26 -05:00
|
|
|
|
|
|
|
CalculateStats();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-02-26 21:45:49 -05:00
|
|
|
bool CodeDataLogger::SaveCdlFile(string cdlFilepath, uint32_t romCrc)
|
|
|
|
{
|
|
|
|
ofstream cdlFile(cdlFilepath, ios::out | ios::binary);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-02-27 19:49:26 -05:00
|
|
|
void CodeDataLogger::CalculateStats()
|
|
|
|
{
|
2020-02-08 22:30:54 -05:00
|
|
|
uint32_t codeSize = 0;
|
|
|
|
uint32_t dataSize = 0;
|
2019-02-27 19:49:26 -05:00
|
|
|
|
|
|
|
for(int i = 0, len = _prgSize; i < len; i++) {
|
|
|
|
if(IsCode(i)) {
|
2020-02-08 22:30:54 -05:00
|
|
|
codeSize++;
|
2019-02-27 19:49:26 -05:00
|
|
|
} else if(IsData(i)) {
|
2020-02-08 22:30:54 -05:00
|
|
|
dataSize++;
|
2019-02-27 19:49:26 -05:00
|
|
|
}
|
|
|
|
}
|
2020-02-08 22:30:54 -05:00
|
|
|
|
|
|
|
_codeSize = codeSize;
|
|
|
|
_dataSize = dataSize;
|
2019-02-27 19:49:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void CodeDataLogger::SetFlags(int32_t absoluteAddr, uint8_t flags)
|
|
|
|
{
|
|
|
|
if(absoluteAddr >= 0 && absoluteAddr < (int32_t)_prgSize) {
|
|
|
|
if((_cdlData[absoluteAddr] & flags) != flags) {
|
|
|
|
if(flags & CdlFlags::Code) {
|
2019-05-14 19:11:00 -04:00
|
|
|
_cdlData[absoluteAddr] = flags | (_cdlData[absoluteAddr] & ~(CdlFlags::Data | CdlFlags::IndexMode8 | CdlFlags::MemoryMode8));
|
2019-02-27 19:49:26 -05:00
|
|
|
} else if(flags & CdlFlags::Data) {
|
|
|
|
if(!IsCode(absoluteAddr)) {
|
|
|
|
_cdlData[absoluteAddr] |= flags;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_cdlData[absoluteAddr] |= flags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CdlRatios CodeDataLogger::GetRatios()
|
|
|
|
{
|
2019-05-14 19:11:00 -04:00
|
|
|
CalculateStats();
|
|
|
|
|
2019-02-27 19:49:26 -05:00
|
|
|
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-06-06 16:13:02 -04:00
|
|
|
if(_cpuType == CpuType::Gameboy) {
|
|
|
|
return _cpuType;
|
|
|
|
} else if(_cdlData[absoluteAddr] & CdlFlags::Gsu) {
|
2020-02-25 23:56:55 -05:00
|
|
|
return CpuType::Gsu;
|
|
|
|
} else if(_cdlData[absoluteAddr] & CdlFlags::Cx4) {
|
|
|
|
return CpuType::Cx4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CpuType::Cpu;
|
|
|
|
}
|
|
|
|
|
2019-02-27 19:49:26 -05:00
|
|
|
void CodeDataLogger::SetCdlData(uint8_t *cdlData, uint32_t length)
|
|
|
|
{
|
|
|
|
if(length <= _prgSize) {
|
|
|
|
memcpy(_cdlData, cdlData, length);
|
|
|
|
}
|
|
|
|
}
|
2019-03-28 17:47:43 -04:00
|
|
|
|
2020-02-25 23:56:55 -05:00
|
|
|
void CodeDataLogger::GetCdlData(uint32_t offset, uint32_t length, uint8_t *cdlData)
|
2019-03-28 17:47:43 -04:00
|
|
|
{
|
2020-02-25 23:56:55 -05:00
|
|
|
memcpy(cdlData, _cdlData + offset, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t CodeDataLogger::GetFlags(uint32_t addr)
|
|
|
|
{
|
|
|
|
return _cdlData[addr];
|
2020-02-08 22:30:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void CodeDataLogger::MarkBytesAs(uint32_t start, uint32_t end, uint8_t flags)
|
|
|
|
{
|
|
|
|
for(uint32_t i = start; i <= end; i++) {
|
|
|
|
_cdlData[i] = (_cdlData[i] & 0xFC) | (int)flags;
|
|
|
|
}
|
|
|
|
}
|
2020-02-12 19:36:47 -05:00
|
|
|
|
|
|
|
void CodeDataLogger::StripData(uint8_t* romBuffer, CdlStripOption flag)
|
|
|
|
{
|
|
|
|
if(flag == CdlStripOption::StripUnused) {
|
|
|
|
for(uint32_t i = 0; i < _prgSize; i++) {
|
|
|
|
if(_cdlData[i] == 0) {
|
|
|
|
romBuffer[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if(flag == CdlStripOption::StripUsed) {
|
|
|
|
for(uint32_t i = 0; i < _prgSize; i++) {
|
|
|
|
if(_cdlData[i] != 0) {
|
|
|
|
romBuffer[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|