1 #include "stdafx.h"
2 #include "CodeDataLogger.h"
3 #include "Debugger.h"
4 #include "LabelManager.h"
5
CodeDataLogger(Debugger * debugger,uint32_t prgSize,uint32_t chrSize)6 CodeDataLogger::CodeDataLogger(Debugger *debugger, uint32_t prgSize, uint32_t chrSize)
7 {
8 _debugger = debugger;
9 _prgSize = prgSize;
10 _chrSize = chrSize;
11 _cdlData = new uint8_t[prgSize+chrSize];
12 Reset();
13 }
14
~CodeDataLogger()15 CodeDataLogger::~CodeDataLogger()
16 {
17 delete[] _cdlData;
18 }
19
Reset()20 void CodeDataLogger::Reset()
21 {
22 _codeSize = 0;
23 _dataSize = 0;
24 _usedChrSize = 0;
25 _drawnChrSize = 0;
26 _readChrSize = 0;
27 memset(_cdlData, 0, _prgSize + _chrSize);
28 }
29
LoadCdlFile(string cdlFilepath)30 bool CodeDataLogger::LoadCdlFile(string cdlFilepath)
31 {
32 ifstream cdlFile(cdlFilepath, ios::in | ios::binary);
33 if(cdlFile) {
34 cdlFile.seekg(0, std::ios::end);
35 size_t fileSize = (size_t)cdlFile.tellg();
36 cdlFile.seekg(0, std::ios::beg);
37
38 if(fileSize == _prgSize + _chrSize) {
39 Reset();
40
41 cdlFile.read((char*)_cdlData, _prgSize + _chrSize);
42 cdlFile.close();
43
44 CalculateStats();
45
46 return true;
47 }
48 }
49 return false;
50 }
51
CalculateStats()52 void CodeDataLogger::CalculateStats()
53 {
54 _codeSize = 0;
55 _dataSize = 0;
56 _usedChrSize = 0;
57 _drawnChrSize = 0;
58 _readChrSize = 0;
59
60 for(int i = 0, len = _prgSize; i < len; i++) {
61 if(IsCode(i)) {
62 _codeSize++;
63 } else if(IsData(i)) {
64 _dataSize++;
65 }
66 }
67
68 for(int i = 0, len = _chrSize; i < len; i++) {
69 if(IsDrawn(i) || IsRead(i)) {
70 _usedChrSize++;
71 if(IsDrawn(i)) {
72 _drawnChrSize++;
73 } else if(IsRead(i)) {
74 _readChrSize++;
75 }
76 }
77 }
78 }
79
SaveCdlFile(string cdlFilepath)80 bool CodeDataLogger::SaveCdlFile(string cdlFilepath)
81 {
82 ofstream cdlFile(cdlFilepath, ios::out | ios::binary);
83 if(cdlFile) {
84 cdlFile.write((char*)_cdlData, _prgSize+_chrSize);
85 cdlFile.close();
86 return true;
87 }
88 return false;
89 }
90
SetFlag(int32_t absoluteAddr,CdlPrgFlags flag)91 void CodeDataLogger::SetFlag(int32_t absoluteAddr, CdlPrgFlags flag)
92 {
93 if(absoluteAddr >= 0 && absoluteAddr < (int32_t)_prgSize) {
94 if((_cdlData[absoluteAddr] & (uint8_t)flag) != (uint8_t)flag) {
95 if(flag == CdlPrgFlags::Code) {
96 if(IsData(absoluteAddr)) {
97 //Remove the data flag from bytes that we are flagging as code
98 _cdlData[absoluteAddr] &= ~(uint8_t)CdlPrgFlags::Data;
99 _dataSize--;
100 }
101 _cdlData[absoluteAddr] |= (uint8_t)flag;
102 _codeSize++;
103 } else if(flag == CdlPrgFlags::Data) {
104 if(!IsCode(absoluteAddr)) {
105 _cdlData[absoluteAddr] |= (uint8_t)flag;
106 _dataSize++;
107 }
108 } else {
109 _cdlData[absoluteAddr] |= (uint8_t)flag;
110 }
111 }
112 }
113 }
114
SetFlag(int32_t chrAbsoluteAddr,CdlChrFlags flag)115 void CodeDataLogger::SetFlag(int32_t chrAbsoluteAddr, CdlChrFlags flag)
116 {
117 if(chrAbsoluteAddr >= 0 && chrAbsoluteAddr < (int32_t)_chrSize) {
118 if((_cdlData[_prgSize + chrAbsoluteAddr] & (uint8_t)flag) != (uint8_t)flag) {
119 _usedChrSize++;
120 if(flag == CdlChrFlags::Read) {
121 _readChrSize++;
122 } else if(flag == CdlChrFlags::Drawn) {
123 _drawnChrSize++;
124 }
125 _cdlData[_prgSize + chrAbsoluteAddr] |= (uint8_t)flag;
126 }
127 }
128 }
129
GetRatios()130 CdlRatios CodeDataLogger::GetRatios()
131 {
132 CdlRatios ratios;
133 ratios.CodeRatio = (float)_codeSize / (float)_prgSize;
134 ratios.DataRatio = (float)_dataSize / (float)_prgSize;
135 ratios.PrgRatio = (float)(_codeSize + _dataSize) / (float)_prgSize;
136 if(_chrSize > 0) {
137 ratios.ChrRatio = (float)(_usedChrSize) / (float)_chrSize;
138 ratios.ChrReadRatio = (float)(_readChrSize) / (float)_chrSize;
139 ratios.ChrDrawnRatio = (float)(_drawnChrSize) / (float)_chrSize;
140 } else {
141 ratios.ChrRatio = -1;
142 ratios.ChrReadRatio = -1;
143 ratios.ChrDrawnRatio = -1;
144 }
145
146 return ratios;
147 }
148
IsCode(uint32_t absoluteAddr)149 bool CodeDataLogger::IsCode(uint32_t absoluteAddr)
150 {
151 return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::Code) == (uint8_t)CdlPrgFlags::Code;
152 }
153
IsJumpTarget(uint32_t absoluteAddr)154 bool CodeDataLogger::IsJumpTarget(uint32_t absoluteAddr)
155 {
156 return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::JumpTarget) == (uint8_t)CdlPrgFlags::JumpTarget;
157 }
158
IsSubEntryPoint(uint32_t absoluteAddr)159 bool CodeDataLogger::IsSubEntryPoint(uint32_t absoluteAddr)
160 {
161 return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::SubEntryPoint) == (uint8_t)CdlPrgFlags::SubEntryPoint;
162 }
163
IsData(uint32_t absoluteAddr)164 bool CodeDataLogger::IsData(uint32_t absoluteAddr)
165 {
166 return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::Data) == (uint8_t)CdlPrgFlags::Data;
167 }
168
IsRead(uint32_t absoluteAddr)169 bool CodeDataLogger::IsRead(uint32_t absoluteAddr)
170 {
171 return (_cdlData[absoluteAddr + _prgSize] & (uint8_t)CdlChrFlags::Read) == (uint8_t)CdlChrFlags::Read;
172 }
173
IsDrawn(uint32_t absoluteAddr)174 bool CodeDataLogger::IsDrawn(uint32_t absoluteAddr)
175 {
176 return (_cdlData[absoluteAddr + _prgSize] & (uint8_t)CdlChrFlags::Drawn) == (uint8_t)CdlChrFlags::Drawn;
177 }
178
SetCdlData(uint8_t * cdlData,uint32_t length)179 void CodeDataLogger::SetCdlData(uint8_t *cdlData, uint32_t length)
180 {
181 if(length <= _prgSize + _chrSize) {
182 memcpy(_cdlData, cdlData, length);
183 CalculateStats();
184 }
185 }
186
GetCdlData(uint32_t offset,uint32_t length,DebugMemoryType memoryType,uint8_t * cdlData)187 void CodeDataLogger::GetCdlData(uint32_t offset, uint32_t length, DebugMemoryType memoryType, uint8_t *cdlData)
188 {
189 if(memoryType == DebugMemoryType::PrgRom) {
190 memcpy(cdlData, _cdlData + offset, length);
191 } else if(memoryType == DebugMemoryType::ChrRom) {
192 memcpy(cdlData, _cdlData + _prgSize + offset, length);
193 } else if(memoryType == DebugMemoryType::CpuMemory) {
194 for(uint32_t i = 0; i < length; i++) {
195 int32_t absoluteAddress = _debugger->GetAbsoluteAddress(offset + i);
196 cdlData[i] = absoluteAddress >= 0 ? _cdlData[absoluteAddress] : 0;
197 }
198 } else if(memoryType == DebugMemoryType::PpuMemory) {
199 for(uint32_t i = 0; i < length; i++) {
200 int32_t absoluteAddress = _debugger->GetAbsoluteChrAddress(offset + i);
201 cdlData[i] = absoluteAddress >= 0 ? _cdlData[_prgSize + absoluteAddress] : 0;
202 }
203 }
204 }
205
StripData(uint8_t * romBuffer,CdlStripFlag flag)206 void CodeDataLogger::StripData(uint8_t *romBuffer, CdlStripFlag flag)
207 {
208 if(flag == CdlStripFlag::StripUnused) {
209 for(uint32_t i = 0; i < _prgSize + _chrSize; i++) {
210 if(_cdlData[i] == 0) {
211 romBuffer[i] = 0;
212 }
213 }
214 } else if(flag == CdlStripFlag::StripUsed) {
215 for(uint32_t i = 0; i < _prgSize + _chrSize; i++) {
216 if(_cdlData[i] != 0) {
217 romBuffer[i] = 0;
218 }
219 }
220 }
221 }
222
MarkPrgBytesAs(uint32_t start,uint32_t end,CdlPrgFlags type)223 void CodeDataLogger::MarkPrgBytesAs(uint32_t start, uint32_t end, CdlPrgFlags type)
224 {
225 for(uint32_t i = start; i <= end; i++) {
226 _cdlData[i] = (_cdlData[i] & 0xFC) | (int)type;
227 }
228 _debugger->UpdateCdlCache();
229 }
230