1 #include <cassert>
2 #include "MemoryMap.h"
3 #include "Log.h"
4 
5 #define LOG_NAME "MemoryMap"
6 
InsertReadMap(uint32 start,uint32 end,void * pointer,unsigned char key)7 void CMemoryMap::InsertReadMap(uint32 start, uint32 end, void* pointer, unsigned char key)
8 {
9 	assert(GetReadMap(start) == nullptr);
10 	InsertMap(m_readMap, start, end, pointer, key);
11 }
12 
InsertReadMap(uint32 start,uint32 end,const MemoryMapHandlerType & handler,unsigned char key)13 void CMemoryMap::InsertReadMap(uint32 start, uint32 end, const MemoryMapHandlerType& handler, unsigned char key)
14 {
15 	assert(GetReadMap(start) == nullptr);
16 	InsertMap(m_readMap, start, end, handler, key);
17 }
18 
InsertWriteMap(uint32 start,uint32 end,void * pointer,unsigned char key)19 void CMemoryMap::InsertWriteMap(uint32 start, uint32 end, void* pointer, unsigned char key)
20 {
21 	assert(GetWriteMap(start) == nullptr);
22 	InsertMap(m_writeMap, start, end, pointer, key);
23 }
24 
InsertWriteMap(uint32 start,uint32 end,const MemoryMapHandlerType & handler,unsigned char key)25 void CMemoryMap::InsertWriteMap(uint32 start, uint32 end, const MemoryMapHandlerType& handler, unsigned char key)
26 {
27 	assert(GetWriteMap(start) == nullptr);
28 	InsertMap(m_writeMap, start, end, handler, key);
29 }
30 
InsertInstructionMap(uint32 start,uint32 end,void * pointer,unsigned char key)31 void CMemoryMap::InsertInstructionMap(uint32 start, uint32 end, void* pointer, unsigned char key)
32 {
33 	assert(GetMap(m_instructionMap, start) == nullptr);
34 	InsertMap(m_instructionMap, start, end, pointer, key);
35 }
36 
GetInstructionMaps()37 const CMemoryMap::MemoryMapListType& CMemoryMap::GetInstructionMaps()
38 {
39 	return m_instructionMap;
40 }
41 
GetReadMap(uint32 address) const42 const CMemoryMap::MEMORYMAPELEMENT* CMemoryMap::GetReadMap(uint32 address) const
43 {
44 	return GetMap(m_readMap, address);
45 }
46 
GetWriteMap(uint32 address) const47 const CMemoryMap::MEMORYMAPELEMENT* CMemoryMap::GetWriteMap(uint32 address) const
48 {
49 	return GetMap(m_writeMap, address);
50 }
51 
InsertMap(MemoryMapListType & memoryMap,uint32 start,uint32 end,void * pointer,unsigned char key)52 void CMemoryMap::InsertMap(MemoryMapListType& memoryMap, uint32 start, uint32 end, void* pointer, unsigned char key)
53 {
54 	MEMORYMAPELEMENT element;
55 	element.nStart = start;
56 	element.nEnd = end;
57 	element.pPointer = pointer;
58 	element.nType = MEMORYMAP_TYPE_MEMORY;
59 	memoryMap.push_back(element);
60 }
61 
InsertMap(MemoryMapListType & memoryMap,uint32 start,uint32 end,const MemoryMapHandlerType & handler,unsigned char key)62 void CMemoryMap::InsertMap(MemoryMapListType& memoryMap, uint32 start, uint32 end, const MemoryMapHandlerType& handler, unsigned char key)
63 {
64 	MEMORYMAPELEMENT element;
65 	element.nStart = start;
66 	element.nEnd = end;
67 	element.handler = handler;
68 	element.pPointer = nullptr;
69 	element.nType = MEMORYMAP_TYPE_FUNCTION;
70 	memoryMap.push_back(element);
71 }
72 
GetMap(const MemoryMapListType & memoryMap,uint32 nAddress)73 const CMemoryMap::MEMORYMAPELEMENT* CMemoryMap::GetMap(const MemoryMapListType& memoryMap, uint32 nAddress)
74 {
75 	for(const auto& mapElement : memoryMap)
76 	{
77 		if(nAddress <= mapElement.nEnd)
78 		{
79 			if(!(nAddress >= mapElement.nStart)) return nullptr;
80 			return &mapElement;
81 		}
82 	}
83 	return nullptr;
84 }
85 
GetByte(uint32 nAddress)86 uint8 CMemoryMap::GetByte(uint32 nAddress)
87 {
88 	const auto e = GetMap(m_readMap, nAddress);
89 	if(!e)
90 	{
91 		CLog::GetInstance().Print(LOG_NAME, "Read byte from unmapped memory (0x%08X).\r\n", nAddress);
92 		return 0xCC;
93 	}
94 	switch(e->nType)
95 	{
96 	case MEMORYMAP_TYPE_MEMORY:
97 		return *(uint8*)&((uint8*)e->pPointer)[nAddress - e->nStart];
98 		break;
99 	case MEMORYMAP_TYPE_FUNCTION:
100 		return static_cast<uint8>(e->handler(nAddress, 0));
101 		break;
102 	default:
103 		assert(0);
104 		return 0xCC;
105 		break;
106 	}
107 }
108 
SetByte(uint32 nAddress,uint8 nValue)109 void CMemoryMap::SetByte(uint32 nAddress, uint8 nValue)
110 {
111 	const auto e = GetMap(m_writeMap, nAddress);
112 	if(!e)
113 	{
114 		CLog::GetInstance().Print(LOG_NAME, "Wrote byte to unmapped memory (0x%08X, 0x%02X).\r\n", nAddress, nValue);
115 		return;
116 	}
117 	switch(e->nType)
118 	{
119 	case MEMORYMAP_TYPE_MEMORY:
120 		*(uint8*)&((uint8*)e->pPointer)[nAddress - e->nStart] = nValue;
121 		break;
122 	case MEMORYMAP_TYPE_FUNCTION:
123 		e->handler(nAddress, nValue);
124 		break;
125 	default:
126 		assert(0);
127 		break;
128 	}
129 }
130 
131 //////////////////////////////////////////////////////////////////
132 //LSB First Memory Map Implementation
133 //////////////////////////////////////////////////////////////////
134 
GetHalf(uint32 nAddress)135 uint16 CMemoryMap_LSBF::GetHalf(uint32 nAddress)
136 {
137 	assert((nAddress & 0x01) == 0);
138 	const auto e = GetMap(m_readMap, nAddress);
139 	if(!e)
140 	{
141 		CLog::GetInstance().Print(LOG_NAME, "Read half from unmapped memory (0x%08X).\r\n", nAddress);
142 		return 0xCCCC;
143 	}
144 	switch(e->nType)
145 	{
146 	case MEMORYMAP_TYPE_MEMORY:
147 		return *(uint16*)&((uint8*)e->pPointer)[nAddress - e->nStart];
148 		break;
149 	default:
150 		return static_cast<uint16>(e->handler(nAddress, 0));
151 		break;
152 	}
153 }
154 
GetWord(uint32 nAddress)155 uint32 CMemoryMap_LSBF::GetWord(uint32 nAddress)
156 {
157 	assert((nAddress & 0x03) == 0);
158 	const auto e = GetMap(m_readMap, nAddress);
159 	if(!e)
160 	{
161 		CLog::GetInstance().Print(LOG_NAME, "Read word from unmapped memory (0x%08X).\r\n", nAddress);
162 		return 0xCCCCCCCC;
163 	}
164 	switch(e->nType)
165 	{
166 	case MEMORYMAP_TYPE_MEMORY:
167 		return *(uint32*)&((uint8*)e->pPointer)[nAddress - e->nStart];
168 		break;
169 	case MEMORYMAP_TYPE_FUNCTION:
170 		return e->handler(nAddress, 0);
171 		break;
172 	default:
173 		assert(0);
174 		return 0xCCCCCCCC;
175 		break;
176 	}
177 }
178 
GetInstruction(uint32 address)179 uint32 CMemoryMap_LSBF::GetInstruction(uint32 address)
180 {
181 	assert((address & 0x03) == 0);
182 	const auto e = GetMap(m_instructionMap, address);
183 	if(!e) return 0xCCCCCCCC;
184 	switch(e->nType)
185 	{
186 	case MEMORYMAP_TYPE_MEMORY:
187 		return *reinterpret_cast<uint32*>(&reinterpret_cast<uint8*>(e->pPointer)[address - e->nStart]);
188 		break;
189 	default:
190 		assert(0);
191 		return 0xCCCCCCCC;
192 		break;
193 	}
194 }
195 
SetHalf(uint32 nAddress,uint16 nValue)196 void CMemoryMap_LSBF::SetHalf(uint32 nAddress, uint16 nValue)
197 {
198 	assert((nAddress & 0x01) == 0);
199 	const auto e = GetMap(m_writeMap, nAddress);
200 	if(!e)
201 	{
202 		CLog::GetInstance().Print(LOG_NAME, "Wrote half to unmapped memory (0x%08X, 0x%04X).\r\n", nAddress, nValue);
203 		return;
204 	}
205 	switch(e->nType)
206 	{
207 	case MEMORYMAP_TYPE_MEMORY:
208 		*reinterpret_cast<uint16*>(&reinterpret_cast<uint8*>(e->pPointer)[nAddress - e->nStart]) = nValue;
209 		break;
210 	case MEMORYMAP_TYPE_FUNCTION:
211 		e->handler(nAddress, nValue);
212 		break;
213 	default:
214 		assert(0);
215 		break;
216 	}
217 }
218 
SetWord(uint32 nAddress,uint32 nValue)219 void CMemoryMap_LSBF::SetWord(uint32 nAddress, uint32 nValue)
220 {
221 	assert((nAddress & 0x03) == 0);
222 	const auto e = GetMap(m_writeMap, nAddress);
223 	if(!e)
224 	{
225 		CLog::GetInstance().Print(LOG_NAME, "Wrote word to unmapped memory (0x%08X, 0x%08X).\r\n", nAddress, nValue);
226 		return;
227 	}
228 	switch(e->nType)
229 	{
230 	case MEMORYMAP_TYPE_MEMORY:
231 		*(uint32*)&((uint8*)e->pPointer)[nAddress - e->nStart] = nValue;
232 		break;
233 	case MEMORYMAP_TYPE_FUNCTION:
234 		e->handler(nAddress, nValue);
235 		break;
236 	default:
237 		assert(0);
238 		break;
239 	}
240 }
241