1 // Copyright (C) 2003 Dolphin Project / 2012 PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
17 
18 #pragma once
19 
20 #include "ppsspp_config.h"
21 
22 #include <cstring>
23 #include <cstdint>
24 #ifndef offsetof
25 #include <stddef.h>
26 #endif
27 
28 // Includes
29 #include "Common/Common.h"
30 #include "Common/CommonTypes.h"
31 #include "Common/Swap.h"
32 #include "Core/Opcode.h"
33 
34 // PPSSPP is very aggressive about trying to do memory accesses directly, for speed.
35 // This can be a problem when debugging though, as stray memory reads and writes will
36 // crash the whole emulator.
37 // If safe memory is enabled and JIT is disabled, all memory access will go through the proper
38 // memory access functions, and thus won't crash the emu when they go out of bounds.
39 #if defined(_DEBUG)
40 //#define SAFE_MEMORY
41 #endif
42 
43 // Global declarations
44 class PointerWrap;
45 
46 typedef void (*writeFn8 )(const u8, const u32);
47 typedef void (*writeFn16)(const u16,const u32);
48 typedef void (*writeFn32)(const u32,const u32);
49 typedef void (*writeFn64)(const u64,const u32);
50 
51 typedef void (*readFn8 )(u8&,  const u32);
52 typedef void (*readFn16)(u16&, const u32);
53 typedef void (*readFn32)(u32&, const u32);
54 typedef void (*readFn64)(u64&, const u32);
55 
56 namespace Memory {
57 // Base is a pointer to the base of the memory map. Yes, some MMU tricks
58 // are used to set up a full GC or Wii memory map in process memory.	on
59 // 32-bit, you have to mask your offsets with 0x3FFFFFFF. This means that
60 // some things are mirrored too many times, but eh... it works.
61 
62 // In 64-bit, this might point to "high memory" (above the 32-bit limit),
63 // so be sure to load it into a 64-bit register.
64 extern u8 *base;
65 
66 // This replaces RAM_NORMAL_SIZE at runtime.
67 extern u32 g_MemorySize;
68 extern u32 g_PSPModel;
69 
70 // UWP has such limited memory management that we need to mask
71 // even in 64-bit mode. Also, when using the sanitizer, we need to mask as well.
72 #if PPSSPP_ARCH(32BIT) || PPSSPP_PLATFORM(UWP) || USE_ASAN || PPSSPP_PLATFORM(IOS)
73 #define MASKED_PSP_MEMORY
74 #endif
75 
76 enum
77 {
78 	// This may be adjusted by remaster games.
79 	RAM_NORMAL_SIZE = 0x02000000,
80 	// Used if the PSP model is PSP-2000 (Slim).
81 	RAM_DOUBLE_SIZE = RAM_NORMAL_SIZE * 2,
82 
83 	VRAM_SIZE       = 0x00200000,
84 
85 	SCRATCHPAD_SIZE = 0x00004000,
86 
87 #ifdef MASKED_PSP_MEMORY
88 	// This wraparound should work for PSP too.
89 	MEMVIEW32_MASK  = 0x3FFFFFFF,
90 #endif
91 };
92 
93 enum {
94 	MV_MIRROR_PREVIOUS = 1,
95 	MV_IS_PRIMARY_RAM = 0x100,
96 	MV_IS_EXTRA1_RAM = 0x200,
97 	MV_IS_EXTRA2_RAM = 0x400,
98 	MV_KERNEL = 0x800  // Can be skipped on platforms where memory is tight.
99 };
100 
101 struct MemoryView
102 {
103 	u8 **out_ptr;
104 	u32 virtual_address;
105 	u32 size;
106 	u32 flags;
107 };
108 
109 // Uses a memory arena to set up an emulator-friendly memory map
110 bool MemoryMap_Setup(u32 flags);
111 void MemoryMap_Shutdown(u32 flags);
112 
113 // Init and Shutdown
114 bool Init();
115 void Shutdown();
116 void DoState(PointerWrap &p);
117 void Clear();
118 // False when shutdown has already been called.
119 bool IsActive();
120 
121 class MemoryInitedLock {
122 public:
123 	MemoryInitedLock();
124 	~MemoryInitedLock();
125 };
126 
127 // This doesn't lock memory access or anything, it just makes sure memory isn't freed.
128 // Use it when accessing PSP memory from external threads.
129 MemoryInitedLock Lock();
130 
131 // used by JIT to read instructions. Does not resolve replacements.
132 Opcode Read_Opcode_JIT(const u32 _Address);
133 // used by JIT. Reads in the "Locked cache" mode
134 void Write_Opcode_JIT(const u32 _Address, const Opcode& _Value);
135 
136 // Should be used by analyzers, disassemblers etc. Does resolve replacements.
137 Opcode Read_Instruction(const u32 _Address, bool resolveReplacements = false);
138 Opcode ReadUnchecked_Instruction(const u32 _Address, bool resolveReplacements = false);
139 
140 u8  Read_U8(const u32 _Address);
141 u16 Read_U16(const u32 _Address);
142 u32 Read_U32(const u32 _Address);
143 u64 Read_U64(const u32 _Address);
144 
GetPointerUnchecked(const u32 address)145 inline u8* GetPointerUnchecked(const u32 address) {
146 #ifdef MASKED_PSP_MEMORY
147 	return (u8 *)(base + (address & MEMVIEW32_MASK));
148 #else
149 	return (u8 *)(base + address);
150 #endif
151 }
152 
ReadUnchecked_U32(const u32 address)153 inline u32 ReadUnchecked_U32(const u32 address) {
154 #ifdef MASKED_PSP_MEMORY
155 	return *(u32_le *)(base + (address & MEMVIEW32_MASK));
156 #else
157 	return *(u32_le *)(base + address);
158 #endif
159 }
160 
ReadUnchecked_Float(const u32 address)161 inline float ReadUnchecked_Float(const u32 address) {
162 #ifdef MASKED_PSP_MEMORY
163 	return *(float_le *)(base + (address & MEMVIEW32_MASK));
164 #else
165 	return *(float_le *)(base + address);
166 #endif
167 }
168 
ReadUnchecked_U16(const u32 address)169 inline u16 ReadUnchecked_U16(const u32 address) {
170 #ifdef MASKED_PSP_MEMORY
171 	return *(u16_le *)(base + (address & MEMVIEW32_MASK));
172 #else
173 	return *(u16_le *)(base + address);
174 #endif
175 }
176 
ReadUnchecked_U8(const u32 address)177 inline u8 ReadUnchecked_U8(const u32 address) {
178 #ifdef MASKED_PSP_MEMORY
179 	return (*(u8 *)(base + (address & MEMVIEW32_MASK)));
180 #else
181 	return (*(u8 *)(base + address));
182 #endif
183 }
184 
WriteUnchecked_U32(u32 data,u32 address)185 inline void WriteUnchecked_U32(u32 data, u32 address) {
186 #ifdef MASKED_PSP_MEMORY
187 	*(u32_le *)(base + (address & MEMVIEW32_MASK)) = data;
188 #else
189 	*(u32_le *)(base + address) = data;
190 #endif
191 }
192 
WriteUnchecked_Float(float data,u32 address)193 inline void WriteUnchecked_Float(float data, u32 address) {
194 #ifdef MASKED_PSP_MEMORY
195 	*(float_le *)(base + (address & MEMVIEW32_MASK)) = data;
196 #else
197 	*(float_le *)(base + address) = data;
198 #endif
199 }
200 
WriteUnchecked_U16(u16 data,u32 address)201 inline void WriteUnchecked_U16(u16 data, u32 address) {
202 #ifdef MASKED_PSP_MEMORY
203 	*(u16_le *)(base + (address & MEMVIEW32_MASK)) = data;
204 #else
205 	*(u16_le *)(base + address) = data;
206 #endif
207 }
208 
WriteUnchecked_U8(u8 data,u32 address)209 inline void WriteUnchecked_U8(u8 data, u32 address) {
210 #ifdef MASKED_PSP_MEMORY
211 	(*(u8 *)(base + (address & MEMVIEW32_MASK))) = data;
212 #else
213 	(*(u8 *)(base + address)) = data;
214 #endif
215 }
216 
Read_Float(u32 address)217 inline float Read_Float(u32 address)
218 {
219 	u32 ifloat = Read_U32(address);
220 	float f;
221 	memcpy(&f, &ifloat, sizeof(float));
222 	return f;
223 }
224 
225 // used by JIT. Return zero-extended 32bit values
226 u32 Read_U8_ZX(const u32 address);
227 u32 Read_U16_ZX(const u32 address);
228 
229 void Write_U8(const u8 data, const u32 address);
230 void Write_U16(const u16 data, const u32 address);
231 void Write_U32(const u32 data, const u32 address);
232 void Write_U64(const u64 data, const u32 address);
233 
Write_Float(float f,u32 address)234 inline void Write_Float(float f, u32 address)
235 {
236 	u32 u;
237 	memcpy(&u, &f, sizeof(float));
238 	Write_U32(u, address);
239 }
240 
241 u8* GetPointer(const u32 address);
242 bool IsRAMAddress(const u32 address);
IsVRAMAddress(const u32 address)243 inline bool IsVRAMAddress(const u32 address) {
244 	return ((address & 0x3F800000) == 0x04000000);
245 }
IsDepthTexVRAMAddress(const u32 address)246 inline bool IsDepthTexVRAMAddress(const u32 address) {
247 	return ((address & 0x3FE00000) == 0x04200000) || ((address & 0x3FE00000) == 0x04600000);
248 }
249 
250 // 0x08000000 -> 0x08800000
IsKernelAddress(const u32 address)251 inline bool IsKernelAddress(const u32 address) {
252 	return ((address & 0x3F800000) == 0x08000000);
253 }
254 
255 // 0x08000000 -> 0x08400000
IsKernelAndNotVolatileAddress(const u32 address)256 inline bool IsKernelAndNotVolatileAddress(const u32 address) {
257 	return ((address & 0x3FC00000) == 0x08000000);
258 }
259 
260 bool IsScratchpadAddress(const u32 address);
261 
262 // Used for auto-converted char * parameters, which can sometimes legitimately be null -
263 // so we don't want to get caught in GetPointer's crash reporting.
GetCharPointer(const u32 address)264 inline const char* GetCharPointer(const u32 address) {
265 	if (address) {
266 		return (const char *)GetPointer(address);
267 	} else {
268 		return nullptr;
269 	}
270 }
271 
MemcpyUnchecked(void * to_data,const u32 from_address,const u32 len)272 inline void MemcpyUnchecked(void *to_data, const u32 from_address, const u32 len) {
273 	memcpy(to_data, GetPointerUnchecked(from_address), len);
274 }
275 
MemcpyUnchecked(const u32 to_address,const void * from_data,const u32 len)276 inline void MemcpyUnchecked(const u32 to_address, const void *from_data, const u32 len) {
277 	memcpy(GetPointerUnchecked(to_address), from_data, len);
278 }
279 
MemcpyUnchecked(const u32 to_address,const u32 from_address,const u32 len)280 inline void MemcpyUnchecked(const u32 to_address, const u32 from_address, const u32 len) {
281 	MemcpyUnchecked(GetPointer(to_address), from_address, len);
282 }
283 
IsValidAddress(const u32 address)284 inline bool IsValidAddress(const u32 address) {
285 	if ((address & 0x3E000000) == 0x08000000) {
286 		return true;
287 	} else if ((address & 0x3F800000) == 0x04000000) {
288 		return true;
289 	} else if ((address & 0xBFFFC000) == 0x00010000) {
290 		return true;
291 	} else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
292 		return true;
293 	} else {
294 		return false;
295 	}
296 }
297 
ValidSize(const u32 address,const u32 requested_size)298 inline u32 ValidSize(const u32 address, const u32 requested_size) {
299 	u32 max_size;
300 	if ((address & 0x3E000000) == 0x08000000) {
301 		max_size = 0x08000000 + g_MemorySize - (address & 0x3FFFFFFF);
302 	} else if ((address & 0x3F800000) == 0x04000000) {
303 		max_size = 0x04800000 - (address & 0x3FFFFFFF);
304 	} else if ((address & 0xBFFFC000) == 0x00010000) {
305 		max_size = 0x00014000 - (address & 0x3FFFFFFF);
306 	} else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
307 		max_size = 0x08000000 + g_MemorySize - (address & 0x3FFFFFFF);
308 	} else {
309 		max_size = 0;
310 	}
311 
312 	if (requested_size > max_size) {
313 		return max_size;
314 	}
315 	return requested_size;
316 }
317 
IsValidRange(const u32 address,const u32 size)318 inline bool IsValidRange(const u32 address, const u32 size) {
319 	return IsValidAddress(address) && ValidSize(address, size) == size;
320 }
321 
322 }  // namespace Memory
323 
324 template <typename T>
325 struct PSPPointer
326 {
327 	u32_le ptr;
328 
329 	inline T &operator*() const
330 	{
331 #ifdef MASKED_PSP_MEMORY
332 		return *(T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
333 #else
334 		return *(T *)(Memory::base + ptr);
335 #endif
336 	}
337 
338 	inline T &operator[](int i) const
339 	{
340 #ifdef MASKED_PSP_MEMORY
341 		return *((T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK)) + i);
342 #else
343 		return *((T *)(Memory::base + ptr) + i);
344 #endif
345 	}
346 
347 	inline T *operator->() const
348 	{
349 #ifdef MASKED_PSP_MEMORY
350 		return (T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
351 #else
352 		return (T *)(Memory::base + ptr);
353 #endif
354 	}
355 
356 	inline PSPPointer<T> operator+(int i) const
357 	{
358 		PSPPointer other;
359 		other.ptr = ptr + i * sizeof(T);
360 		return other;
361 	}
362 
363 	inline PSPPointer<T> &operator=(u32 p)
364 	{
365 		ptr = p;
366 		return *this;
367 	}
368 
369 	inline PSPPointer<T> &operator+=(int i)
370 	{
371 		ptr = ptr + i * sizeof(T);
372 		return *this;
373 	}
374 
375 	inline PSPPointer<T> operator-(int i) const
376 	{
377 		PSPPointer other;
378 		other.ptr = ptr - i * sizeof(T);
379 		return other;
380 	}
381 
382 	inline PSPPointer<T> &operator-=(int i)
383 	{
384 		ptr = ptr - i * sizeof(T);
385 		return *this;
386 	}
387 
388 	inline PSPPointer<T> &operator++()
389 	{
390 		ptr += sizeof(T);
391 		return *this;
392 	}
393 
394 	inline PSPPointer<T> operator++(int i)
395 	{
396 		PSPPointer<T> other;
397 		other.ptr = ptr;
398 		ptr += sizeof(T);
399 		return other;
400 	}
401 
402 	inline PSPPointer<T> &operator--()
403 	{
404 		ptr -= sizeof(T);
405 		return *this;
406 	}
407 
408 	inline PSPPointer<T> operator--(int i)
409 	{
410 		PSPPointer<T> other;
411 		other.ptr = ptr;
412 		ptr -= sizeof(T);
413 		return other;
414 	}
415 
416 	inline operator T*()
417 	{
418 #ifdef MASKED_PSP_MEMORY
419 		return (T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
420 #else
421 		return (T *)(Memory::base + ptr);
422 #endif
423 	}
424 
425 	inline operator const T*() const
426 	{
427 #ifdef MASKED_PSP_MEMORY
428 		return (const T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
429 #else
430 		return (const T *)(Memory::base + ptr);
431 #endif
432 	}
433 
IsValidPSPPointer434 	bool IsValid() const
435 	{
436 		return Memory::IsValidAddress(ptr);
437 	}
438 
CreatePSPPointer439 	static PSPPointer<T> Create(u32 ptr) {
440 		PSPPointer<T> p;
441 		p = ptr;
442 		return p;
443 	}
444 };
445 
446 
PSP_GetScratchpadMemoryBase()447 constexpr u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;}
PSP_GetScratchpadMemoryEnd()448 constexpr u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;}
449 
PSP_GetKernelMemoryBase()450 constexpr u32 PSP_GetKernelMemoryBase() { return 0x08000000;}
PSP_GetUserMemoryEnd()451 inline u32 PSP_GetUserMemoryEnd() { return PSP_GetKernelMemoryBase() + Memory::g_MemorySize;}
PSP_GetKernelMemoryEnd()452 constexpr u32 PSP_GetKernelMemoryEnd() { return 0x08400000;}
453 
454 // "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the
455 // game through sceKernelVolatileMemTryLock.
PSP_GetVolatileMemoryStart()456 constexpr u32 PSP_GetVolatileMemoryStart() { return 0x08400000; }
PSP_GetVolatileMemoryEnd()457 constexpr u32 PSP_GetVolatileMemoryEnd() { return 0x08800000; }
458 
PSP_GetUserMemoryBase()459 constexpr u32 PSP_GetUserMemoryBase() { return 0x08800000; }
PSP_GetDefaultLoadAddress()460 constexpr u32 PSP_GetDefaultLoadAddress() { return 0; }
PSP_GetVidMemBase()461 constexpr u32 PSP_GetVidMemBase() { return 0x04000000; }
PSP_GetVidMemEnd()462 constexpr u32 PSP_GetVidMemEnd() { return 0x04800000; }
463 
464 template <typename T>
465 inline bool operator==(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs) {
466 	return lhs.ptr == rhs.ptr;
467 }
468 
469 template <typename T>
470 inline bool operator!=(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs) {
471 	return lhs.ptr != rhs.ptr;
472 }
473 
474 template <typename T>
475 inline bool operator<(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs) {
476 	return lhs.ptr < rhs.ptr;
477 }
478 
479 template <typename T>
480 inline bool operator>(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs) {
481 	return lhs.ptr > rhs.ptr;
482 }
483 
484 template <typename T>
485 inline bool operator<=(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs) {
486 	return lhs.ptr <= rhs.ptr;
487 }
488 
489 template <typename T>
490 inline bool operator>=(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs) {
491 	return lhs.ptr >= rhs.ptr;
492 }
493