Merge pull request #90 from gizmo98/patch-2
[libretro-ppsspp.git] / Core / MemMap.h
blobab61e5e53308e8de62d182ccfc150e2d23ec2634
1 // Copyright (C) 2003 Dolphin Project / 2012 PPSSPP Project.
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.
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.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #pragma once
20 #include <cstring>
21 #ifdef __SYMBIAN32__
22 #include <e32std.h>
23 #endif
24 #ifndef offsetof
25 #include <stddef.h>
26 #endif
28 // Includes
29 #include "Common/Common.h"
30 #include "Common/CommonTypes.h"
31 #include "Core/Opcode.h"
33 // PPSSPP is very aggressive about trying to do memory accesses directly, for speed.
34 // This can be a problem when debugging though, as stray memory reads and writes will
35 // crash the whole emulator.
36 // If safe memory is enabled and JIT is disabled, all memory access will go through the proper
37 // memory access functions, and thus won't crash the emu when they go out of bounds.
38 #if defined(_DEBUG)
39 //#define SAFE_MEMORY
40 #endif
42 // Global declarations
43 class PointerWrap;
45 typedef void (*writeFn8 )(const u8, const u32);
46 typedef void (*writeFn16)(const u16,const u32);
47 typedef void (*writeFn32)(const u32,const u32);
48 typedef void (*writeFn64)(const u64,const u32);
50 typedef void (*readFn8 )(u8&, const u32);
51 typedef void (*readFn16)(u16&, const u32);
52 typedef void (*readFn32)(u32&, const u32);
53 typedef void (*readFn64)(u64&, const u32);
55 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.
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;
66 // These are guaranteed to point to "low memory" addresses (sub-32-bit).
67 // 64-bit: Pointers to low-mem (sub-0x10000000) mirror
68 // 32-bit: Same as the corresponding physical/virtual pointers.
69 // Broken into three chunks to workaround 32-bit mmap() limits.
70 extern u8 *m_pRAM;
71 extern u8 *m_pRAM2;
72 extern u8 *m_pRAM3;
73 extern u8 *m_pScratchPad;
74 extern u8 *m_pVRAM;
76 // 64-bit: Pointers to high-mem mirrors
77 // 32-bit: Same as above
78 extern u8 *m_pPhysicalRAM;
79 extern u8 *m_pUncachedRAM;
81 // This replaces RAM_NORMAL_SIZE at runtime.
82 extern u32 g_MemorySize;
83 extern u32 g_PSPModel;
85 enum
87 // This may be adjusted by remaster games.
88 RAM_NORMAL_SIZE = 0x02000000,
89 // Used if the PSP model is PSP-2000 (Slim).
90 RAM_DOUBLE_SIZE = RAM_NORMAL_SIZE * 2,
92 VRAM_SIZE = 0x00200000,
94 SCRATCHPAD_SIZE = 0x00004000,
96 #ifdef _ARCH_32
97 // This wraparound should work for PSP too.
98 MEMVIEW32_MASK = 0x3FFFFFFF,
99 #endif
102 enum {
103 MV_MIRROR_PREVIOUS = 1,
104 // MV_FAKE_VMEM = 2,
105 // MV_WII_ONLY = 4,
106 MV_IS_PRIMARY_RAM = 0x100,
107 MV_IS_EXTRA1_RAM = 0x200,
108 MV_IS_EXTRA2_RAM = 0x400,
111 struct MemoryView
113 u8 **out_ptr_low;
114 u8 **out_ptr;
115 u32 virtual_address;
116 u32 size;
117 u32 flags;
120 // Uses a memory arena to set up an emulator-friendly memory map
121 void MemoryMap_Setup(u32 flags);
122 void MemoryMap_Shutdown(u32 flags);
124 // Init and Shutdown
125 void Init();
126 void Shutdown();
127 void DoState(PointerWrap &p);
128 void Clear();
130 class MemoryInitedLock
132 public:
133 MemoryInitedLock();
134 ~MemoryInitedLock();
137 // This doesn't lock memory access or anything, it just makes sure memory isn't freed.
138 // Use it when accessing PSP memory from external threads.
139 MemoryInitedLock Lock();
141 // used by JIT to read instructions. Does not resolve replacements.
142 Opcode Read_Opcode_JIT(const u32 _Address);
143 // used by JIT. Reads in the "Locked cache" mode
144 void Write_Opcode_JIT(const u32 _Address, const Opcode& _Value);
146 // Should be used by analyzers, disassemblers etc. Does resolve replacements.
147 Opcode Read_Instruction(const u32 _Address, bool resolveReplacements = false);
148 Opcode ReadUnchecked_Instruction(const u32 _Address, bool resolveReplacements = false);
150 u8 Read_U8(const u32 _Address);
151 u16 Read_U16(const u32 _Address);
152 u32 Read_U32(const u32 _Address);
153 u64 Read_U64(const u32 _Address);
155 #if (defined(ARM) || defined(_ARM)) && !defined(_M_ARM)
156 #define _M_ARM
157 #endif
159 inline u8* GetPointerUnchecked(const u32 address) {
160 #ifdef _ARCH_32
161 return (u8 *)(base + (address & MEMVIEW32_MASK));
162 #else
163 return (u8 *)(base + address);
164 #endif
167 #ifdef SAFE_MEMORY
168 u32 ReadUnchecked_U32(const u32 _Address);
169 // ONLY for use by GUI and fast interpreter
170 u8 ReadUnchecked_U8(const u32 _Address);
171 u16 ReadUnchecked_U16(const u32 _Address);
172 void WriteUnchecked_U8(const u8 _Data, const u32 _Address);
173 void WriteUnchecked_U16(const u16 _Data, const u32 _Address);
174 void WriteUnchecked_U32(const u32 _Data, const u32 _Address);
175 #else
177 inline u32 ReadUnchecked_U32(const u32 address) {
178 #ifdef _ARCH_32
179 return *(u32_le *)(base + (address & MEMVIEW32_MASK));
180 #else
181 return *(u32_le *)(base + address);
182 #endif
185 inline u16 ReadUnchecked_U16(const u32 address) {
186 #ifdef _ARCH_32
187 return *(u16_le *)(base + (address & MEMVIEW32_MASK));
188 #else
189 return *(u16_le *)(base + address);
190 #endif
193 inline u8 ReadUnchecked_U8(const u32 address) {
194 #ifdef _ARCH_32
195 return (*(u8 *)(base + (address & MEMVIEW32_MASK)));
196 #else
197 return (*(u8 *)(base + address));
198 #endif
201 inline void WriteUnchecked_U32(u32 data, u32 address) {
202 #ifdef _ARCH_32
203 *(u32_le *)(base + (address & MEMVIEW32_MASK)) = data;
204 #else
205 *(u32_le *)(base + address) = data;
206 #endif
209 inline void WriteUnchecked_U16(u16 data, u32 address) {
210 #ifdef _ARCH_32
211 *(u16_le *)(base + (address & MEMVIEW32_MASK)) = data;
212 #else
213 *(u16_le *)(base + address) = data;
214 #endif
217 inline void WriteUnchecked_U8(u8 data, u32 address) {
218 #ifdef _ARCH_32
219 (*(u8 *)(base + (address & MEMVIEW32_MASK))) = data;
220 #else
221 (*(u8 *)(base + address)) = data;
222 #endif
225 #endif
227 inline float Read_Float(u32 address)
229 u32 ifloat = Read_U32(address);
230 float f;
231 memcpy(&f, &ifloat, sizeof(float));
232 return f;
235 // used by JIT. Return zero-extended 32bit values
236 u32 Read_U8_ZX(const u32 address);
237 u32 Read_U16_ZX(const u32 address);
239 void Write_U8(const u8 data, const u32 address);
240 void Write_U16(const u16 data, const u32 address);
241 void Write_U32(const u32 data, const u32 address);
242 void Write_U64(const u64 data, const u32 address);
244 inline void Write_Float(float f, u32 address)
246 u32 u;
247 memcpy(&u, &f, sizeof(float));
248 Write_U32(u, address);
251 u8* GetPointer(const u32 address);
252 bool IsRAMAddress(const u32 address);
253 bool IsVRAMAddress(const u32 address);
254 bool IsScratchpadAddress(const u32 address);
256 inline const char* GetCharPointer(const u32 address) {
257 return (const char *)GetPointer(address);
260 inline void MemcpyUnchecked(void *to_data, const u32 from_address, const u32 len)
262 memcpy(to_data, GetPointerUnchecked(from_address), len);
265 inline void MemcpyUnchecked(const u32 to_address, const void *from_data, const u32 len)
267 memcpy(GetPointerUnchecked(to_address), from_data, len);
270 inline void MemcpyUnchecked(const u32 to_address, const u32 from_address, const u32 len)
272 MemcpyUnchecked(GetPointer(to_address), from_address, len);
275 inline bool IsValidAddress(const u32 address) {
276 if ((address & 0x3E000000) == 0x08000000) {
277 return true;
278 } else if ((address & 0x3F800000) == 0x04000000) {
279 return true;
280 } else if ((address & 0xBFFF0000) == 0x00010000) {
281 return true;
282 } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
283 return true;
284 } else {
285 return false;
289 inline u32 ValidSize(const u32 address, const u32 requested_size) {
290 u32 max_size;
291 if ((address & 0x3E000000) == 0x08000000) {
292 max_size = 0x08000000 + g_MemorySize - address;
294 else if ((address & 0x3F800000) == 0x04000000) {
295 max_size = 0x04800000 - address;
297 else if ((address & 0xBFFF0000) == 0x00010000) {
298 max_size = 0x00014000 - address;
300 else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
301 max_size = 0x08000000 + g_MemorySize - address;
302 } else {
303 max_size = 0;
306 if (requested_size > max_size) {
307 return max_size;
309 return requested_size;
312 inline bool IsValidRange(const u32 address, const u32 size) {
313 return IsValidAddress(address) && ValidSize(address, size) == size;
318 template <typename T>
319 struct PSPPointer
321 u32_le ptr;
323 inline T &operator*() const
325 #ifdef _ARCH_32
326 return *(T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
327 #else
328 return *(T *)(Memory::base + ptr);
329 #endif
332 inline T &operator[](int i) const
334 #ifdef _ARCH_32
335 return *((T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK)) + i);
336 #else
337 return *((T *)(Memory::base + ptr) + i);
338 #endif
341 inline T *operator->() const
343 #ifdef _ARCH_32
344 return (T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
345 #else
346 return (T *)(Memory::base + ptr);
347 #endif
350 inline PSPPointer<T> operator+(int i) const
352 PSPPointer other;
353 other.ptr = ptr + i * sizeof(T);
354 return other;
357 inline PSPPointer<T> &operator=(u32 p)
359 ptr = p;
360 return *this;
363 inline PSPPointer<T> &operator+=(int i)
365 ptr = ptr + i * sizeof(T);
366 return *this;
369 inline PSPPointer<T> operator-(int i) const
371 PSPPointer other;
372 other.ptr = ptr - i * sizeof(T);
373 return other;
376 inline PSPPointer<T> &operator-=(int i)
378 ptr = ptr - i * sizeof(T);
379 return *this;
382 inline PSPPointer<T> &operator++()
384 ptr += sizeof(T);
385 return *this;
388 inline PSPPointer<T> operator++(int i)
390 PSPPointer<T> other;
391 other.ptr = ptr;
392 ptr += sizeof(T);
393 return other;
396 inline PSPPointer<T> &operator--()
398 ptr -= sizeof(T);
399 return *this;
402 inline PSPPointer<T> operator--(int i)
404 PSPPointer<T> other;
405 other.ptr = ptr;
406 ptr -= sizeof(T);
407 return other;
410 inline operator T*()
412 #ifdef _ARCH_32
413 return (T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
414 #else
415 return (T *)(Memory::base + ptr);
416 #endif
419 inline operator const T*() const
421 #ifdef _ARCH_32
422 return (const T *)(Memory::base + (ptr & Memory::MEMVIEW32_MASK));
423 #else
424 return (const T *)(Memory::base + ptr);
425 #endif
428 bool IsValid() const
430 return Memory::IsValidAddress(ptr);
433 static PSPPointer<T> Create(u32 ptr) {
434 PSPPointer<T> p;
435 p = ptr;
436 return p;
441 inline u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;}
442 inline u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;}
444 inline u32 PSP_GetKernelMemoryBase() { return 0x08000000;}
445 inline u32 PSP_GetUserMemoryEnd() { return PSP_GetKernelMemoryBase() + Memory::g_MemorySize;}
446 inline u32 PSP_GetKernelMemoryEnd() { return 0x08400000;}
447 // "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the
448 // game through sceKernelVolatileMemTryLock.
450 inline u32 PSP_GetUserMemoryBase() { return 0x08800000;}
452 inline u32 PSP_GetDefaultLoadAddress() { return 0;}
453 //inline u32 PSP_GetDefaultLoadAddress() { return 0x0898dab0;}
454 inline u32 PSP_GetVidMemBase() { return 0x04000000;}
455 inline u32 PSP_GetVidMemEnd() { return 0x04800000;}
457 template <typename T>
458 inline bool operator==(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
460 return lhs.ptr == rhs.ptr;
463 template <typename T>
464 inline bool operator!=(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
466 return lhs.ptr != rhs.ptr;
469 template <typename T>
470 inline bool operator<(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
472 return lhs.ptr < rhs.ptr;
475 template <typename T>
476 inline bool operator>(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
478 return lhs.ptr > rhs.ptr;
481 template <typename T>
482 inline bool operator<=(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
484 return lhs.ptr <= rhs.ptr;
487 template <typename T>
488 inline bool operator>=(const PSPPointer<T> &lhs, const PSPPointer<T> &rhs)
490 return lhs.ptr >= rhs.ptr;