Commit | Line | Data |
---|---|---|
ef79bbde P |
1 | /*************************************************************************** |
2 | * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * | |
3 | * * | |
4 | * This program is free software; you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation; either version 2 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program; if not, write to the * | |
16 | * Free Software Foundation, Inc., * | |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * | |
18 | ***************************************************************************/ | |
19 | ||
20 | /* | |
21 | * PSX memory functions. | |
22 | */ | |
23 | ||
24 | // TODO: Implement caches & cycle penalty. | |
25 | ||
26 | #include "psxmem.h" | |
87e5b45f | 27 | #include "psxmem_map.h" |
ef79bbde P |
28 | #include "r3000a.h" |
29 | #include "psxhw.h" | |
7d7672a5 | 30 | //#include "debug.h" |
31 | #define DebugCheckBP(...) | |
ce0e7ac9 | 32 | |
7a8d521f | 33 | #include "lightrec/mem.h" |
ce0e7ac9 | 34 | #include "memmap.h" |
ef79bbde | 35 | |
7a8d521f | 36 | #ifdef USE_LIBRETRO_VFS |
37 | #include <streams/file_stream_transforms.h> | |
38 | #endif | |
39 | ||
ef79bbde P |
40 | #ifndef MAP_ANONYMOUS |
41 | #define MAP_ANONYMOUS MAP_ANON | |
42 | #endif | |
43 | ||
826ba56b | 44 | static void * psxMapDefault(unsigned long addr, size_t size, |
4284a818 | 45 | enum psxMapTag tag, int *can_retry_addr) |
826ba56b | 46 | { |
5e282df8 | 47 | void *ptr; |
d3f0cb2b | 48 | #if !P_HAVE_MMAP |
4284a818 | 49 | *can_retry_addr = 0; |
d3f0cb2b | 50 | ptr = calloc(1, size); |
5e282df8 PC |
51 | return ptr ? ptr : MAP_FAILED; |
52 | #else | |
826ba56b PC |
53 | int flags = MAP_PRIVATE | MAP_ANONYMOUS; |
54 | ||
4284a818 | 55 | *can_retry_addr = 1; |
d3f0cb2b | 56 | ptr = mmap((void *)(uintptr_t)addr, size, |
826ba56b | 57 | PROT_READ | PROT_WRITE, flags, -1, 0); |
d3f0cb2b | 58 | #ifdef MADV_HUGEPAGE |
59 | if (size >= 2*1024*1024) { | |
60 | if (ptr != MAP_FAILED && ((uintptr_t)ptr & (2*1024*1024 - 1))) { | |
4284a818 | 61 | // try to manually realign assuming decreasing addr alloc |
d3f0cb2b | 62 | munmap(ptr, size); |
63 | addr = (uintptr_t)ptr & ~(2*1024*1024 - 1); | |
64 | ptr = mmap((void *)(uintptr_t)addr, size, | |
65 | PROT_READ | PROT_WRITE, flags, -1, 0); | |
66 | } | |
67 | if (ptr != MAP_FAILED) | |
68 | madvise(ptr, size, MADV_HUGEPAGE); | |
69 | } | |
70 | #endif | |
71 | return ptr; | |
5e282df8 | 72 | #endif |
826ba56b PC |
73 | } |
74 | ||
75 | static void psxUnmapDefault(void *ptr, size_t size, enum psxMapTag tag) | |
76 | { | |
9165d434 | 77 | #if !P_HAVE_MMAP |
5e282df8 PC |
78 | free(ptr); |
79 | #else | |
826ba56b | 80 | munmap(ptr, size); |
5e282df8 | 81 | #endif |
826ba56b PC |
82 | } |
83 | ||
4284a818 | 84 | void *(*psxMapHook)(unsigned long addr, size_t size, |
85 | enum psxMapTag tag, int *can_retry_addr) = psxMapDefault; | |
826ba56b PC |
86 | void (*psxUnmapHook)(void *ptr, size_t size, |
87 | enum psxMapTag tag) = psxUnmapDefault; | |
87e5b45f | 88 | |
89 | void *psxMap(unsigned long addr, size_t size, int is_fixed, | |
90 | enum psxMapTag tag) | |
91 | { | |
4284a818 | 92 | int try_, can_retry_addr = 0; |
0b2c3926 | 93 | void *ret = MAP_FAILED; |
87e5b45f | 94 | |
4284a818 | 95 | for (try_ = 0; try_ < 3; try_++) |
96 | { | |
0b2c3926 | 97 | if (ret != MAP_FAILED) |
98 | psxUnmap(ret, size, tag); | |
4284a818 | 99 | ret = psxMapHook(addr, size, tag, &can_retry_addr); |
7e9c3060 | 100 | if (ret == MAP_FAILED) |
7a8d521f | 101 | return MAP_FAILED; |
b0dd9956 | 102 | |
4284a818 | 103 | if (addr != 0 && ret != (void *)(uintptr_t)addr) { |
5612f82e | 104 | SysMessage("psxMap: tried to map @%08lx, got %p\n", |
4284a818 | 105 | addr, ret); |
106 | if (is_fixed) { | |
107 | psxUnmap(ret, size, tag); | |
108 | return MAP_FAILED; | |
109 | } | |
110 | ||
111 | if (can_retry_addr && ((addr ^ (uintptr_t)ret) & ~0xff000000l)) { | |
112 | unsigned long mask; | |
113 | ||
4284a818 | 114 | // try to use similarly aligned memory instead |
115 | // (recompiler prefers this) | |
116 | mask = try_ ? 0xffff : 0xffffff; | |
117 | addr = ((uintptr_t)ret + mask) & ~mask; | |
118 | continue; | |
119 | } | |
b0dd9956 | 120 | } |
4284a818 | 121 | break; |
b0dd9956 | 122 | } |
87e5b45f | 123 | |
124 | return ret; | |
125 | } | |
126 | ||
127 | void psxUnmap(void *ptr, size_t size, enum psxMapTag tag) | |
128 | { | |
826ba56b | 129 | psxUnmapHook(ptr, size, tag); |
87e5b45f | 130 | } |
131 | ||
ef79bbde P |
132 | s8 *psxM = NULL; // Kernel & User Memory (2 Meg) |
133 | s8 *psxP = NULL; // Parallel Port (64K) | |
134 | s8 *psxR = NULL; // BIOS ROM (512K) | |
135 | s8 *psxH = NULL; // Scratch Pad (1K) & Hardware Registers (8K) | |
136 | ||
137 | u8 **psxMemWLUT = NULL; | |
138 | u8 **psxMemRLUT = NULL; | |
139 | ||
140 | /* Playstation Memory Map (from Playstation doc by Joshua Walker) | |
141 | 0x0000_0000-0x0000_ffff Kernel (64K) | |
142 | 0x0001_0000-0x001f_ffff User Memory (1.9 Meg) | |
143 | ||
144 | 0x1f00_0000-0x1f00_ffff Parallel Port (64K) | |
145 | ||
146 | 0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes) | |
147 | ||
148 | 0x1f80_1000-0x1f80_2fff Hardware Registers (8K) | |
149 | ||
150 | 0x1fc0_0000-0x1fc7_ffff BIOS (512K) | |
151 | ||
152 | 0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached | |
153 | 0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached | |
154 | ||
155 | 0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached | |
156 | 0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached | |
157 | */ | |
158 | ||
7a8d521f | 159 | static int psxMemInitMap(void) |
160 | { | |
87e5b45f | 161 | psxM = psxMap(0x80000000, 0x00210000, 1, MAP_TAG_RAM); |
7a8d521f | 162 | if (psxM == MAP_FAILED) |
f23d3386 | 163 | psxM = psxMap(0x77000000, 0x00210000, 0, MAP_TAG_RAM); |
7a8d521f | 164 | if (psxM == MAP_FAILED) { |
5dd884df | 165 | SysMessage("mapping main RAM failed"); |
7a8d521f | 166 | psxM = NULL; |
a327ad27 | 167 | return -1; |
168 | } | |
ef79bbde | 169 | psxP = &psxM[0x200000]; |
7a8d521f | 170 | |
6d760c92 | 171 | psxH = psxMap(0x1f800000, 0x10000, 0, MAP_TAG_OTHER); |
7a8d521f | 172 | if (psxH == MAP_FAILED) { |
5dd884df | 173 | SysMessage("Error allocating psxH"); |
174 | psxH = NULL; | |
7a8d521f | 175 | return -1; |
176 | } | |
177 | ||
87e5b45f | 178 | psxR = psxMap(0x1fc00000, 0x80000, 0, MAP_TAG_OTHER); |
7a8d521f | 179 | if (psxR == MAP_FAILED) { |
5dd884df | 180 | SysMessage("Error allocating psxR"); |
181 | psxR = NULL; | |
7a8d521f | 182 | return -1; |
183 | } | |
ef79bbde | 184 | |
7a8d521f | 185 | return 0; |
186 | } | |
187 | ||
188 | static void psxMemFreeMap(void) | |
189 | { | |
190 | if (psxM) psxUnmap(psxM, 0x00210000, MAP_TAG_RAM); | |
191 | if (psxH) psxUnmap(psxH, 0x10000, MAP_TAG_OTHER); | |
192 | if (psxR) psxUnmap(psxR, 0x80000, MAP_TAG_OTHER); | |
193 | psxM = psxH = psxR = NULL; | |
194 | psxP = NULL; | |
195 | } | |
196 | ||
197 | int psxMemInit(void) | |
198 | { | |
199 | unsigned int i; | |
200 | int ret; | |
201 | ||
202 | if (LIGHTREC_CUSTOM_MAP) | |
203 | ret = lightrec_init_mmap(); | |
204 | else | |
205 | ret = psxMemInitMap(); | |
206 | if (ret) { | |
5dd884df | 207 | if (LIGHTREC_CUSTOM_MAP) |
208 | SysMessage("lightrec_init_mmap failed"); | |
7a8d521f | 209 | psxMemShutdown(); |
210 | return -1; | |
211 | } | |
212 | ||
4bb8d7e1 PC |
213 | if (DISABLE_MEM_LUTS) |
214 | return 0; | |
215 | ||
7a8d521f | 216 | psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *)); |
217 | psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *)); | |
218 | ||
219 | if (psxMemRLUT == NULL || psxMemWLUT == NULL) { | |
5dd884df | 220 | SysMessage("Error allocating psxMem LUTs"); |
88901dd2 | 221 | psxMemShutdown(); |
ef79bbde P |
222 | return -1; |
223 | } | |
224 | ||
679d5ee3 | 225 | memset(psxMemRLUT, (int)(uintptr_t)INVALID_PTR, 0x10000 * sizeof(void *)); |
226 | memset(psxMemWLUT, (int)(uintptr_t)INVALID_PTR, 0x10000 * sizeof(void *)); | |
7a8d521f | 227 | |
ef79bbde P |
228 | // MemR |
229 | for (i = 0; i < 0x80; i++) psxMemRLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16]; | |
230 | ||
231 | memcpy(psxMemRLUT + 0x8000, psxMemRLUT, 0x80 * sizeof(void *)); | |
232 | memcpy(psxMemRLUT + 0xa000, psxMemRLUT, 0x80 * sizeof(void *)); | |
233 | ||
234 | psxMemRLUT[0x1f00] = (u8 *)psxP; | |
235 | psxMemRLUT[0x1f80] = (u8 *)psxH; | |
236 | ||
237 | for (i = 0; i < 0x08; i++) psxMemRLUT[i + 0x1fc0] = (u8 *)&psxR[i << 16]; | |
238 | ||
239 | memcpy(psxMemRLUT + 0x9fc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *)); | |
240 | memcpy(psxMemRLUT + 0xbfc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *)); | |
241 | ||
242 | // MemW | |
243 | for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16]; | |
244 | ||
245 | memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); | |
246 | memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); | |
247 | ||
fa18abb2 | 248 | // Don't allow writes to PIO Expansion region (psxP) to take effect. |
249 | // NOTE: Not sure if this is needed to fix any games but seems wise, | |
250 | // seeing as some games do read from PIO as part of copy-protection | |
251 | // check. (See fix in psxMemReset() regarding psxP region reads). | |
7a8d521f | 252 | psxMemWLUT[0x1f00] = INVALID_PTR; |
ef79bbde P |
253 | psxMemWLUT[0x1f80] = (u8 *)psxH; |
254 | ||
255 | return 0; | |
256 | } | |
257 | ||
258 | void psxMemReset() { | |
259 | FILE *f = NULL; | |
260 | char bios[1024]; | |
261 | ||
262 | memset(psxM, 0, 0x00200000); | |
23643ee7 | 263 | memset(psxP, 0xff, 0x00010000); |
ef79bbde | 264 | |
7a8d521f | 265 | Config.HLE = TRUE; |
266 | ||
ef79bbde P |
267 | if (strcmp(Config.Bios, "HLE") != 0) { |
268 | sprintf(bios, "%s/%s", Config.BiosDir, Config.Bios); | |
269 | f = fopen(bios, "rb"); | |
270 | ||
271 | if (f == NULL) { | |
272 | SysMessage(_("Could not open BIOS:\"%s\". Enabling HLE Bios!\n"), bios); | |
ef79bbde | 273 | } else { |
7a8d521f | 274 | if (fread(psxR, 1, 0x80000, f) == 0x80000) { |
275 | Config.HLE = FALSE; | |
276 | } else { | |
277 | SysMessage(_("The selected BIOS:\"%s\" is of wrong size. Enabling HLE Bios!\n"), bios); | |
278 | } | |
ef79bbde | 279 | fclose(f); |
ef79bbde | 280 | } |
7a8d521f | 281 | } |
60afad47 | 282 | if (Config.HLE) |
283 | memset(psxR, 0, 0x80000); | |
ef79bbde P |
284 | } |
285 | ||
286 | void psxMemShutdown() { | |
7a8d521f | 287 | if (LIGHTREC_CUSTOM_MAP) |
288 | lightrec_free_mmap(); | |
289 | else | |
290 | psxMemFreeMap(); | |
ef79bbde | 291 | |
88901dd2 | 292 | free(psxMemRLUT); psxMemRLUT = NULL; |
293 | free(psxMemWLUT); psxMemWLUT = NULL; | |
ef79bbde P |
294 | } |
295 | ||
4bb8d7e1 PC |
296 | int cache_isolated; |
297 | ||
679d5ee3 | 298 | void psxMemOnIsolate(int enable) |
299 | { | |
4bb8d7e1 PC |
300 | if (!DISABLE_MEM_LUTS) { |
301 | if (enable) { | |
302 | memset(psxMemWLUT + 0x0000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *)); | |
303 | memset(psxMemWLUT + 0x8000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *)); | |
304 | //memset(psxMemWLUT + 0xa000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *)); | |
305 | } else { | |
306 | int i; | |
307 | for (i = 0; i < 0x80; i++) | |
308 | psxMemWLUT[i + 0x0000] = (void *)&psxM[(i & 0x1f) << 16]; | |
309 | memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); | |
310 | memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); | |
311 | } | |
679d5ee3 | 312 | } |
4bb8d7e1 PC |
313 | |
314 | cache_isolated = enable; | |
679d5ee3 | 315 | psxCpu->Notify(enable ? R3000ACPU_NOTIFY_CACHE_ISOLATED |
316 | : R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL); | |
317 | } | |
ef79bbde P |
318 | |
319 | u8 psxMemRead8(u32 mem) { | |
320 | char *p; | |
321 | u32 t; | |
322 | ||
323 | t = mem >> 16; | |
9dd7d179 | 324 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
325 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
326 | return psxHu8(mem); |
327 | else | |
328 | return psxHwRead8(mem); | |
329 | } else { | |
4bb8d7e1 | 330 | p = psxm(mem, 0); |
7a8d521f | 331 | if (p != INVALID_PTR) { |
ef79bbde P |
332 | if (Config.Debug) |
333 | DebugCheckBP((mem & 0xffffff) | 0x80000000, R1); | |
4bb8d7e1 | 334 | return *(u8 *)p; |
ef79bbde P |
335 | } else { |
336 | #ifdef PSXMEM_LOG | |
337 | PSXMEM_LOG("err lb %8.8lx\n", mem); | |
338 | #endif | |
943a507a | 339 | return 0xFF; |
ef79bbde P |
340 | } |
341 | } | |
342 | } | |
343 | ||
344 | u16 psxMemRead16(u32 mem) { | |
345 | char *p; | |
346 | u32 t; | |
347 | ||
348 | t = mem >> 16; | |
9dd7d179 | 349 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
350 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
351 | return psxHu16(mem); |
352 | else | |
353 | return psxHwRead16(mem); | |
354 | } else { | |
4bb8d7e1 | 355 | p = psxm(mem, 0); |
7a8d521f | 356 | if (p != INVALID_PTR) { |
ef79bbde P |
357 | if (Config.Debug) |
358 | DebugCheckBP((mem & 0xffffff) | 0x80000000, R2); | |
4bb8d7e1 | 359 | return SWAPu16(*(u16 *)p); |
ef79bbde P |
360 | } else { |
361 | #ifdef PSXMEM_LOG | |
362 | PSXMEM_LOG("err lh %8.8lx\n", mem); | |
363 | #endif | |
943a507a | 364 | return 0xFFFF; |
ef79bbde P |
365 | } |
366 | } | |
367 | } | |
368 | ||
369 | u32 psxMemRead32(u32 mem) { | |
370 | char *p; | |
371 | u32 t; | |
372 | ||
373 | t = mem >> 16; | |
9dd7d179 | 374 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
375 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
376 | return psxHu32(mem); |
377 | else | |
378 | return psxHwRead32(mem); | |
379 | } else { | |
4bb8d7e1 | 380 | p = psxm(mem, 0); |
7a8d521f | 381 | if (p != INVALID_PTR) { |
ef79bbde P |
382 | if (Config.Debug) |
383 | DebugCheckBP((mem & 0xffffff) | 0x80000000, R4); | |
4bb8d7e1 | 384 | return SWAPu32(*(u32 *)p); |
ef79bbde | 385 | } else { |
679d5ee3 | 386 | if (mem == 0xfffe0130) |
387 | return psxRegs.biuReg; | |
ef79bbde | 388 | #ifdef PSXMEM_LOG |
679d5ee3 | 389 | PSXMEM_LOG("err lw %8.8lx\n", mem); |
ef79bbde | 390 | #endif |
943a507a | 391 | return 0xFFFFFFFF; |
ef79bbde P |
392 | } |
393 | } | |
394 | } | |
395 | ||
20bfbac0 | 396 | void psxMemWrite8(u32 mem, u32 value) { |
ef79bbde P |
397 | char *p; |
398 | u32 t; | |
399 | ||
400 | t = mem >> 16; | |
9dd7d179 | 401 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
402 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
403 | psxHu8(mem) = value; |
404 | else | |
405 | psxHwWrite8(mem, value); | |
406 | } else { | |
4bb8d7e1 | 407 | p = psxm(mem, 1); |
7a8d521f | 408 | if (p != INVALID_PTR) { |
ef79bbde P |
409 | if (Config.Debug) |
410 | DebugCheckBP((mem & 0xffffff) | 0x80000000, W1); | |
4bb8d7e1 | 411 | *(u8 *)p = value; |
41e82ad4 | 412 | #ifndef DRC_DISABLE |
ef79bbde P |
413 | psxCpu->Clear((mem & (~3)), 1); |
414 | #endif | |
415 | } else { | |
416 | #ifdef PSXMEM_LOG | |
417 | PSXMEM_LOG("err sb %8.8lx\n", mem); | |
418 | #endif | |
419 | } | |
420 | } | |
421 | } | |
422 | ||
20bfbac0 | 423 | void psxMemWrite16(u32 mem, u32 value) { |
ef79bbde P |
424 | char *p; |
425 | u32 t; | |
426 | ||
427 | t = mem >> 16; | |
9dd7d179 | 428 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
429 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
430 | psxHu16ref(mem) = SWAPu16(value); |
431 | else | |
432 | psxHwWrite16(mem, value); | |
433 | } else { | |
4bb8d7e1 | 434 | p = psxm(mem, 1); |
7a8d521f | 435 | if (p != INVALID_PTR) { |
ef79bbde P |
436 | if (Config.Debug) |
437 | DebugCheckBP((mem & 0xffffff) | 0x80000000, W2); | |
4bb8d7e1 | 438 | *(u16 *)p = SWAPu16(value); |
41e82ad4 | 439 | #ifndef DRC_DISABLE |
3e31e934 | 440 | psxCpu->Clear((mem & (~3)), 1); |
ef79bbde P |
441 | #endif |
442 | } else { | |
443 | #ifdef PSXMEM_LOG | |
444 | PSXMEM_LOG("err sh %8.8lx\n", mem); | |
445 | #endif | |
446 | } | |
447 | } | |
448 | } | |
449 | ||
450 | void psxMemWrite32(u32 mem, u32 value) { | |
451 | char *p; | |
452 | u32 t; | |
453 | ||
454 | // if ((mem&0x1fffff) == 0x71E18 || value == 0x48088800) SysPrintf("t2fix!!\n"); | |
455 | t = mem >> 16; | |
9dd7d179 | 456 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
457 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
458 | psxHu32ref(mem) = SWAPu32(value); |
459 | else | |
460 | psxHwWrite32(mem, value); | |
461 | } else { | |
4bb8d7e1 | 462 | p = psxm(mem, 1); |
7a8d521f | 463 | if (p != INVALID_PTR) { |
ef79bbde P |
464 | if (Config.Debug) |
465 | DebugCheckBP((mem & 0xffffff) | 0x80000000, W4); | |
4bb8d7e1 | 466 | *(u32 *)p = SWAPu32(value); |
41e82ad4 | 467 | #ifndef DRC_DISABLE |
ef79bbde P |
468 | psxCpu->Clear(mem, 1); |
469 | #endif | |
470 | } else { | |
679d5ee3 | 471 | if (mem == 0xfffe0130) { |
472 | psxRegs.biuReg = value; | |
473 | return; | |
474 | } | |
ef79bbde | 475 | #ifdef PSXMEM_LOG |
679d5ee3 | 476 | PSXMEM_LOG("err sw %8.8lx\n", mem); |
ef79bbde | 477 | #endif |
ef79bbde P |
478 | } |
479 | } | |
480 | } | |
481 | ||
482 | void *psxMemPointer(u32 mem) { | |
483 | char *p; | |
484 | u32 t; | |
485 | ||
486 | t = mem >> 16; | |
9dd7d179 | 487 | if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { |
488 | if ((mem & 0xffff) < 0x400) | |
ef79bbde P |
489 | return (void *)&psxH[mem]; |
490 | else | |
491 | return NULL; | |
492 | } else { | |
4bb8d7e1 | 493 | p = psxm(mem, 1); |
7a8d521f | 494 | if (p != INVALID_PTR) { |
4bb8d7e1 | 495 | return (void *)p; |
ef79bbde P |
496 | } |
497 | return NULL; | |
498 | } | |
499 | } |