Merge pull request #90 from gizmo98/patch-2
[libretro-ppsspp.git] / Core / MemMapFunctions.cpp
blobbb04c3899ebe5c1b1aef09a8952e25ec2c1656c9
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 git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18 #include "Common/Common.h"
19 #include "Common/Atomics.h"
21 #include "Core/Core.h"
22 #include "Core/MemMap.h"
23 #include "Core/Config.h"
24 #include "Core/Host.h"
25 #include "Core/Reporting.h"
27 #include "Core/MIPS/MIPS.h"
29 namespace Memory
32 // =================================
33 // From Memmap.cpp
34 // ----------------
36 // Read and write shortcuts
38 // GetPointer must always return an address in the bottom 32 bits of address space, so that 64-bit
39 // programs don't have problems directly addressing any part of memory.
41 u8 *GetPointer(const u32 address)
43 if ((address & 0x3E000000) == 0x08000000) {
44 // RAM
45 return GetPointerUnchecked(address);
46 } else if ((address & 0x3F800000) == 0x04000000) {
47 // VRAM
48 return GetPointerUnchecked(address);
49 } else if ((address & 0xBFFF0000) == 0x00010000) {
50 // Scratchpad
51 return GetPointerUnchecked(address);
52 } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
53 // More RAM (remasters, etc.)
54 return GetPointerUnchecked(address);
55 } else {
56 ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
57 static bool reported = false;
58 if (!reported) {
59 Reporting::ReportMessage("Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
60 reported = true;
62 if (!g_Config.bIgnoreBadMemAccess) {
63 Core_EnableStepping(true);
64 host->SetDebugMode(true);
66 return 0;
70 template <typename T>
71 inline void ReadFromHardware(T &var, const u32 address)
73 // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
74 // TODO: Make sure this represents the mirrors in a correct way.
76 // Could just do a base-relative read, too.... TODO
78 if ((address & 0x3E000000) == 0x08000000) {
79 // RAM
80 var = *((const T*)GetPointerUnchecked(address));
81 } else if ((address & 0x3F800000) == 0x04000000) {
82 // VRAM
83 var = *((const T*)GetPointerUnchecked(address));
84 } else if ((address & 0xBFFF0000) == 0x00010000) {
85 // Scratchpad
86 var = *((const T*)GetPointerUnchecked(address));
87 } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
88 // More RAM (remasters, etc.)
89 var = *((const T*)GetPointerUnchecked(address));
90 } else {
91 // In jit, we only flush PC when bIgnoreBadMemAccess is off.
92 if (g_Config.bJit && g_Config.bIgnoreBadMemAccess) {
93 WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x", address);
94 } else {
95 WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
97 static bool reported = false;
98 if (!reported) {
99 Reporting::ReportMessage("ReadFromHardware: Invalid address %08x near PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
100 reported = true;
102 if (!g_Config.bIgnoreBadMemAccess) {
103 Core_EnableStepping(true);
104 host->SetDebugMode(true);
106 var = 0;
110 template <typename T>
111 inline void WriteToHardware(u32 address, const T data)
113 // Could just do a base-relative write, too.... TODO
115 if ((address & 0x3E000000) == 0x08000000) {
116 // RAM
117 *(T*)GetPointerUnchecked(address) = data;
118 } else if ((address & 0x3F800000) == 0x04000000) {
119 // VRAM
120 *(T*)GetPointerUnchecked(address) = data;
121 } else if ((address & 0xBFFF0000) == 0x00010000) {
122 // Scratchpad
123 *(T*)GetPointerUnchecked(address) = data;
124 } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
125 // More RAM (remasters, etc.)
126 *(T*)GetPointerUnchecked(address) = data;
127 } else {
128 // In jit, we only flush PC when bIgnoreBadMemAccess is off.
129 if (g_Config.bJit && g_Config.bIgnoreBadMemAccess) {
130 WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x", address);
131 } else {
132 WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
134 static bool reported = false;
135 if (!reported) {
136 Reporting::ReportMessage("WriteToHardware: Invalid address %08x near PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
137 reported = true;
139 if (!g_Config.bIgnoreBadMemAccess) {
140 Core_EnableStepping(true);
141 host->SetDebugMode(true);
146 // =====================
148 bool IsRAMAddress(const u32 address) {
149 if ((address & 0x3E000000) == 0x08000000) {
150 return true;
151 } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
152 return true;
153 } else {
154 return false;
158 bool IsVRAMAddress(const u32 address) {
159 return ((address & 0x3F800000) == 0x04000000);
162 bool IsScratchpadAddress(const u32 address) {
163 return (address & 0xBFFF0000) == 0x00010000;
166 u8 Read_U8(const u32 _Address)
168 u8 _var = 0;
169 ReadFromHardware<u8>(_var, _Address);
170 return (u8)_var;
173 u16 Read_U16(const u32 _Address)
175 u16_le _var = 0;
176 ReadFromHardware<u16_le>(_var, _Address);
177 return (u16)_var;
180 u32 Read_U32(const u32 _Address)
182 u32_le _var = 0;
183 ReadFromHardware<u32_le>(_var, _Address);
184 return _var;
187 u64 Read_U64(const u32 _Address)
189 u64_le _var = 0;
190 ReadFromHardware<u64_le>(_var, _Address);
191 return _var;
194 u32 Read_U8_ZX(const u32 _Address)
196 return (u32)Read_U8(_Address);
199 u32 Read_U16_ZX(const u32 _Address)
201 return (u32)Read_U16(_Address);
204 void Write_U8(const u8 _Data, const u32 _Address)
206 WriteToHardware<u8>(_Address, _Data);
209 void Write_U16(const u16 _Data, const u32 _Address)
211 WriteToHardware<u16_le>(_Address, _Data);
214 void Write_U32(const u32 _Data, const u32 _Address)
216 WriteToHardware<u32_le>(_Address, _Data);
219 void Write_U64(const u64 _Data, const u32 _Address)
221 WriteToHardware<u64_le>(_Address, _Data);
224 #ifdef SAFE_MEMORY
226 u8 ReadUnchecked_U8(const u32 _Address)
228 u8 _var = 0;
229 ReadFromHardware<u8>(_var, _Address);
230 return _var;
233 u16 ReadUnchecked_U16(const u32 _Address)
235 u16_le _var = 0;
236 ReadFromHardware<u16_le>(_var, _Address);
237 return _var;
240 u32 ReadUnchecked_U32(const u32 _Address)
242 u32_le _var = 0;
243 ReadFromHardware<u32_le>(_var, _Address);
244 return _var;
247 void WriteUnchecked_U8(const u8 _iValue, const u32 _Address)
249 WriteToHardware<u8>(_Address, _iValue);
252 void WriteUnchecked_U16(const u16 _iValue, const u32 _Address)
254 WriteToHardware<u16_le>(_Address, _iValue);
257 void WriteUnchecked_U32(const u32 _iValue, const u32 _Address)
259 WriteToHardware<u32_le>(_Address, _iValue);
262 #endif
264 } // namespace Memory