1 #include "stdafx.h"
2 #include "LabelManager.h"
3 #include "Debugger.h"
4 #include "BaseMapper.h"
5 
LabelManager(shared_ptr<BaseMapper> mapper)6 LabelManager::LabelManager(shared_ptr<BaseMapper> mapper)
7 {
8 	_mapper = mapper;
9 }
10 
DeleteLabels()11 void LabelManager::DeleteLabels()
12 {
13 	_codeComments.clear();
14 	_codeLabels.clear();
15 	_codeLabelReverseLookup.clear();
16 }
17 
SetLabel(uint32_t address,AddressType addressType,string label,string comment)18 void LabelManager::SetLabel(uint32_t address, AddressType addressType, string label, string comment)
19 {
20 	address = GetLabelAddress(address, addressType);
21 
22 	auto existingLabel = _codeLabels.find(address);
23 	if(existingLabel != _codeLabels.end()) {
24 		_codeLabelReverseLookup.erase(existingLabel->second);
25 	}
26 
27 	_codeLabels.erase(address);
28 	if(!label.empty()) {
29 		if(label.size() > 400) {
30 			//Restrict labels to 400 bytes
31 			label = label.substr(0, 400);
32 		}
33 		_codeLabels.emplace(address, label);
34 		_codeLabelReverseLookup.emplace(label, address);
35 	}
36 
37 	_codeComments.erase(address);
38 	if(!comment.empty()) {
39 		_codeComments.emplace(address, comment);
40 	}
41 }
42 
GetLabelAddress(uint32_t absoluteAddr,AddressType addressType)43 int32_t LabelManager::GetLabelAddress(uint32_t absoluteAddr, AddressType addressType)
44 {
45 	switch(addressType) {
46 		case AddressType::InternalRam: absoluteAddr |= 0x70000000; break;
47 		case AddressType::PrgRom: absoluteAddr |= 0x60000000; break;
48 		case AddressType::WorkRam: absoluteAddr |= 0x50000000; break;
49 		case AddressType::SaveRam: absoluteAddr |= 0x40000000; break;
50 		case AddressType::Register: absoluteAddr |= 0x30000000; break;
51 	}
52 	return absoluteAddr;
53 }
54 
GetLabelAddress(uint16_t relativeAddr)55 int32_t LabelManager::GetLabelAddress(uint16_t relativeAddr)
56 {
57 	if(relativeAddr < 0x2000) {
58 		return relativeAddr | 0x70000000;
59 	} else {
60 		int32_t addr = _mapper->ToAbsoluteAddress(relativeAddr);
61 		if(addr >= 0) {
62 			//PRG ROM
63 			return addr | 0x60000000;
64 		}
65 
66 		addr = _mapper->ToAbsoluteWorkRamAddress(relativeAddr);
67 		if(addr >= 0) {
68 			//Work RAM
69 			return addr | 0x50000000;
70 		}
71 
72 		addr = _mapper->ToAbsoluteSaveRamAddress(relativeAddr);
73 		if(addr >= 0) {
74 			//Save RAM
75 			return addr | 0x40000000;
76 		}
77 	}
78 
79 	return -1;
80 }
81 
GetLabel(uint16_t relativeAddr,bool checkRegisters)82 string LabelManager::GetLabel(uint16_t relativeAddr, bool checkRegisters)
83 {
84 	int32_t labelAddr = GetLabelAddress(relativeAddr);
85 
86 	if(labelAddr >= 0) {
87 		auto result = _codeLabels.find(labelAddr);
88 		if(result != _codeLabels.end()) {
89 			return result->second;
90 		}
91 	}
92 
93 	if(checkRegisters) {
94 		labelAddr = relativeAddr | 0x30000000;
95 
96 		auto result = _codeLabels.find(labelAddr);
97 		if(result != _codeLabels.end()) {
98 			return result->second;
99 		}
100 	}
101 
102 	return "";
103 }
104 
GetComment(uint16_t relativeAddr)105 string LabelManager::GetComment(uint16_t relativeAddr)
106 {
107 	int32_t labelAddr = GetLabelAddress(relativeAddr);
108 
109 	if(labelAddr >= 0) {
110 		auto result = _codeComments.find(labelAddr);
111 		if(result != _codeComments.end()) {
112 			return result->second;
113 		}
114 	}
115 
116 	return "";
117 }
118 
GetLabelAndComment(uint16_t relativeAddr,string & label,string & comment)119 void LabelManager::GetLabelAndComment(uint16_t relativeAddr, string &label, string &comment)
120 {
121 	int32_t labelAddr = GetLabelAddress(relativeAddr);
122 
123 	if(labelAddr >= 0) {
124 		auto result = _codeLabels.find(labelAddr);
125 		if(result != _codeLabels.end()) {
126 			label = result->second;
127 		} else {
128 			label.clear();
129 		}
130 
131 		auto commentResult = _codeComments.find(labelAddr);
132 		if(commentResult != _codeComments.end()) {
133 			comment = commentResult->second;
134 		} else {
135 			comment.clear();
136 		}
137 	}
138 }
139 
ContainsLabel(string & label)140 bool LabelManager::ContainsLabel(string &label)
141 {
142 	return _codeLabelReverseLookup.find(label) != _codeLabelReverseLookup.end();
143 }
144 
GetLabelRelativeAddress(string & label)145 int32_t LabelManager::GetLabelRelativeAddress(string &label)
146 {
147 	auto result = _codeLabelReverseLookup.find(label);
148 	if(result != _codeLabelReverseLookup.end()) {
149 		uint32_t address = result->second;
150 		AddressType type = AddressType::InternalRam;
151 		if((address & 0x70000000) == 0x70000000) {
152 			type = AddressType::InternalRam;
153 		} else if((address & 0x60000000) == 0x60000000) {
154 			type = AddressType::PrgRom;
155 		} else if((address & 0x50000000) == 0x50000000) {
156 			type = AddressType::WorkRam;
157 		} else if((address & 0x40000000) == 0x40000000) {
158 			type = AddressType::SaveRam;
159 		} else if((address & 0x30000000) == 0x30000000) {
160 			type = AddressType::Register;
161 		} else {
162 			//Label is out of scope
163 			return -1;
164 		}
165 		return _mapper->FromAbsoluteAddress(address & 0x0FFFFFFF, type);
166 	}
167 	//Label doesn't exist
168 	return -2;
169 }
170 
HasLabelOrComment(uint16_t relativeAddr)171 bool LabelManager::HasLabelOrComment(uint16_t relativeAddr)
172 {
173 	int32_t labelAddr = GetLabelAddress(relativeAddr);
174 
175 	if(labelAddr >= 0) {
176 		return
177 			_codeLabels.find(labelAddr) != _codeLabels.end() ||
178 			_codeComments.find(labelAddr) != _codeComments.end();
179 	}
180 
181 	return false;
182 }
183 
HasLabelOrComment(uint32_t absoluteAddr,AddressType addressType)184 bool LabelManager::HasLabelOrComment(uint32_t absoluteAddr, AddressType addressType)
185 {
186 	int32_t labelAddr = GetLabelAddress(absoluteAddr, addressType);
187 
188 	if(labelAddr >= 0) {
189 		return
190 			_codeLabels.find(labelAddr) != _codeLabels.end() ||
191 			_codeComments.find(labelAddr) != _codeComments.end();
192 	}
193 
194 	return false;
195 }
196