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