/[pcsx2_0.9.7]/trunk/pcsx2/IopMem.cpp
ViewVC logotype

Contents of /trunk/pcsx2/IopMem.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 5 months ago) by william
File size: 10627 byte(s)
re-commit (had local access denied errors when committing)
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16
17 #include "PrecompiledHeader.h"
18 #include "IopCommon.h"
19
20 uptr *psxMemWLUT = NULL;
21 const uptr *psxMemRLUT = NULL;
22
23 IopVM_MemoryAllocMess* iopMem = NULL;
24
25 __pagealigned u8 iopHw[Ps2MemSize::IopHardware];
26
27 // --------------------------------------------------------------------------------------
28 // iopMemoryReserve
29 // --------------------------------------------------------------------------------------
30 iopMemoryReserve::iopMemoryReserve()
31 : _parent( L"IOP Main Memory (2mb)", sizeof(*iopMem) )
32 {
33 }
34
35 void iopMemoryReserve::Reserve()
36 {
37 _parent::Reserve(HostMemoryMap::IOPmem);
38 //_parent::Reserve(EmuConfig.HostMap.IOP);
39 }
40
41 void iopMemoryReserve::Commit()
42 {
43 _parent::Commit();
44 iopMem = (IopVM_MemoryAllocMess*)m_reserve.GetPtr();
45 }
46
47 // Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated,
48 // which is performed by MemInit and PsxMemInit()
49 void iopMemoryReserve::Reset()
50 {
51 _parent::Reset();
52
53 pxAssume( iopMem );
54
55 if (!psxMemWLUT)
56 {
57 psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 16);
58 psxMemRLUT = psxMemWLUT + 0x2000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16);
59 }
60
61 DbgCon.WriteLn("IOP resetting main memory...");
62
63 memzero_ptr<0x2000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT
64
65 // Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer.
66 // So the ones with a 0x2000 prefixed are RLUT tables.
67
68 // Map IOP main memory, which is Read/Write, and mirrored three times
69 // at 0x0, 0x8000, and 0xa000:
70 for (int i=0; i<0x0080; i++)
71 {
72 psxMemWLUT[i + 0x0000] = (uptr)&iopMem->Main[(i & 0x1f) << 16];
73
74 // RLUTs, accessed through WLUT.
75 psxMemWLUT[i + 0x2000] = (uptr)&iopMem->Main[(i & 0x1f) << 16];
76 }
77
78 // A few single-page allocations for things we store in special locations.
79 psxMemWLUT[0x2000 + 0x1f00] = (uptr)iopMem->P;
80 psxMemWLUT[0x2000 + 0x1f80] = (uptr)iopHw;
81 //psxMemWLUT[0x1bf80] = (uptr)iopHw;
82
83 psxMemWLUT[0x1f00] = (uptr)iopMem->P;
84 psxMemWLUT[0x1f80] = (uptr)iopHw;
85 //psxMemWLUT[0xbf80] = (uptr)iopHw;
86
87 // Read-only memory areas, so don't map WLUT for these...
88 for (int i=0; i<0x0040; i++)
89 {
90 psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&eeMem->ROM[i << 16];
91 }
92
93 for (int i=0; i<0x0004; i++)
94 {
95 psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&eeMem->ROM1[i << 16];
96 }
97
98 // sif!! (which is read only? (air))
99 psxMemWLUT[0x2000 + 0x1d00] = (uptr)iopMem->Sif;
100 //psxMemWLUT[0x1bd00] = (uptr)iopMem->Sif;
101
102 // this one looks like an old hack for some special write-only memory area,
103 // but leaving it in for reference (air)
104 //for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16];
105 }
106
107 void iopMemoryReserve::Decommit()
108 {
109 _parent::Decommit();
110
111 safe_aligned_free(psxMemWLUT);
112 psxMemRLUT = NULL;
113 iopMem = NULL;
114 }
115
116 void iopMemoryReserve::Release()
117 {
118 _parent::Release();
119 iopMem = NULL;
120 }
121
122
123 u8 __fastcall iopMemRead8(u32 mem)
124 {
125 mem &= 0x1fffffff;
126 u32 t = mem >> 16;
127
128 if (t == 0x1f80)
129 {
130 switch( mem & 0xf000 )
131 {
132 case 0x1000: return IopMemory::iopHwRead8_Page1(mem);
133 case 0x3000: return IopMemory::iopHwRead8_Page3(mem);
134 case 0x8000: return IopMemory::iopHwRead8_Page8(mem);
135
136 default:
137 return psxHu8(mem);
138 }
139 }
140 else if (t == 0x1f40)
141 {
142 return psxHw4Read8(mem);
143 }
144 else
145 {
146 const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
147 if (p != NULL)
148 {
149 return *(const u8 *)(p + (mem & 0xffff));
150 }
151 else
152 {
153 if (t == 0x1000)
154 return DEV9read8(mem);
155 PSXMEM_LOG("err lb %8.8lx", mem);
156 return 0;
157 }
158 }
159 }
160
161 u16 __fastcall iopMemRead16(u32 mem)
162 {
163 mem &= 0x1fffffff;
164 u32 t = mem >> 16;
165
166 if (t == 0x1f80)
167 {
168 switch( mem & 0xf000 )
169 {
170 case 0x1000: return IopMemory::iopHwRead16_Page1(mem);
171 case 0x3000: return IopMemory::iopHwRead16_Page3(mem);
172 case 0x8000: return IopMemory::iopHwRead16_Page8(mem);
173
174 default:
175 return psxHu16(mem);
176 }
177 }
178 else
179 {
180 const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
181 if (p != NULL)
182 {
183 if (t == 0x1d00)
184 {
185 u16 ret;
186 switch(mem & 0xF0)
187 {
188 case 0x00:
189 ret= psHu16(SBUS_F200);
190 break;
191 case 0x10:
192 ret= psHu16(SBUS_F210);
193 break;
194 case 0x40:
195 ret= psHu16(SBUS_F240) | 0x0002;
196 break;
197 case 0x60:
198 ret = 0;
199 break;
200 default:
201 ret = psxHu16(mem);
202 break;
203 }
204 //SIF_LOG("Sif reg read %x value %x", mem, ret);
205 return ret;
206 }
207 return *(const u16 *)(p + (mem & 0xffff));
208 }
209 else
210 {
211 if (t == 0x1F90)
212 return SPU2read(mem);
213 if (t == 0x1000)
214 return DEV9read16(mem);
215 PSXMEM_LOG("err lh %8.8lx", mem);
216 return 0;
217 }
218 }
219 }
220
221 u32 __fastcall iopMemRead32(u32 mem)
222 {
223 mem &= 0x1fffffff;
224 u32 t = mem >> 16;
225
226 if (t == 0x1f80)
227 {
228 switch( mem & 0xf000 )
229 {
230 case 0x1000: return IopMemory::iopHwRead32_Page1(mem);
231 case 0x3000: return IopMemory::iopHwRead32_Page3(mem);
232 case 0x8000: return IopMemory::iopHwRead32_Page8(mem);
233
234 default:
235 return psxHu32(mem);
236 }
237 } else
238 {
239 //see also Hw.c
240 const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
241 if (p != NULL)
242 {
243 if (t == 0x1d00)
244 {
245 u32 ret;
246 switch(mem & 0x8F0)
247 {
248 case 0x00:
249 ret= psHu32(SBUS_F200);
250 break;
251 case 0x10:
252 ret= psHu32(SBUS_F210);
253 break;
254 case 0x20:
255 ret= psHu32(SBUS_F220);
256 break;
257 case 0x30: // EE Side
258 ret= psHu32(SBUS_F230);
259 break;
260 case 0x40:
261 ret= psHu32(SBUS_F240) | 0xF0000002;
262 break;
263 case 0x60:
264 ret = 0;
265 break;
266
267 default:
268 ret = psxHu32(mem);
269 break;
270 }
271 //SIF_LOG("Sif reg read %x value %x", mem, ret);
272 return ret;
273 }
274 return *(const u32 *)(p + (mem & 0xffff));
275 }
276 else
277 {
278 if (t == 0x1000)
279 return DEV9read32(mem);
280 return 0;
281 }
282 }
283 }
284
285 void __fastcall iopMemWrite8(u32 mem, u8 value)
286 {
287 mem &= 0x1fffffff;
288 u32 t = mem >> 16;
289
290 if (t == 0x1f80)
291 {
292 switch( mem & 0xf000 )
293 {
294 case 0x1000: IopMemory::iopHwWrite8_Page1(mem,value); break;
295 case 0x3000: IopMemory::iopHwWrite8_Page3(mem,value); break;
296 case 0x8000: IopMemory::iopHwWrite8_Page8(mem,value); break;
297
298 default:
299 psxHu8(mem) = value;
300 break;
301 }
302 }
303 else if (t == 0x1f40)
304 {
305 psxHw4Write8(mem, value);
306 }
307 else
308 {
309 u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
310 if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
311 {
312 *(u8 *)(p + (mem & 0xffff)) = value;
313 psxCpu->Clear(mem&~3, 1);
314 }
315 else
316 {
317 if (t == 0x1d00)
318 {
319 Console.WriteLn("sw8 [0x%08X]=0x%08X", mem, value);
320 psxSu8(mem) = value;
321 return;
322 }
323 if (t == 0x1000)
324 {
325 DEV9write8(mem, value); return;
326 }
327 PSXMEM_LOG("err sb %8.8lx = %x", mem, value);
328 }
329 }
330 }
331
332 void __fastcall iopMemWrite16(u32 mem, u16 value)
333 {
334 mem &= 0x1fffffff;
335 u32 t = mem >> 16;
336
337 if (t == 0x1f80)
338 {
339 switch( mem & 0xf000 )
340 {
341 case 0x1000: IopMemory::iopHwWrite16_Page1(mem,value); break;
342 case 0x3000: IopMemory::iopHwWrite16_Page3(mem,value); break;
343 case 0x8000: IopMemory::iopHwWrite16_Page8(mem,value); break;
344
345 default:
346 psxHu16(mem) = value;
347 break;
348 }
349 } else
350 {
351 u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
352 if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
353 {
354 if( t==0x1D00 ) Console.WriteLn("sw16 [0x%08X]=0x%08X", mem, value);
355 *(u16 *)(p + (mem & 0xffff)) = value;
356 psxCpu->Clear(mem&~3, 1);
357 }
358 else
359 {
360 if (t == 0x1d00)
361 {
362 switch (mem & 0x8f0)
363 {
364 case 0x10:
365 // write to ps2 mem
366 psHu16(SBUS_F210) = value;
367 return;
368 case 0x40:
369 {
370 u32 temp = value & 0xF0;
371 // write to ps2 mem
372 if(value & 0x20 || value & 0x80)
373 {
374 psHu16(SBUS_F240) &= ~0xF000;
375 psHu16(SBUS_F240) |= 0x2000;
376 }
377
378
379 if(psHu16(SBUS_F240) & temp)
380 psHu16(SBUS_F240) &= ~temp;
381 else
382 psHu16(SBUS_F240) |= temp;
383 return;
384 }
385 case 0x60:
386 psHu32(SBUS_F260) = 0;
387 return;
388 }
389 psxSu16(mem) = value; return;
390 }
391 if (t == 0x1F90) {
392 SPU2write(mem, value); return;
393 }
394 if (t == 0x1000) {
395 DEV9write16(mem, value); return;
396 }
397 PSXMEM_LOG("err sh %8.8lx = %x", mem, value);
398 }
399 }
400 }
401
402 void __fastcall iopMemWrite32(u32 mem, u32 value)
403 {
404 mem &= 0x1fffffff;
405 u32 t = mem >> 16;
406
407 if (t == 0x1f80)
408 {
409 switch( mem & 0xf000 )
410 {
411 case 0x1000: IopMemory::iopHwWrite32_Page1(mem,value); break;
412 case 0x3000: IopMemory::iopHwWrite32_Page3(mem,value); break;
413 case 0x8000: IopMemory::iopHwWrite32_Page8(mem,value); break;
414
415 default:
416 psxHu32(mem) = value;
417 break;
418 }
419 } else
420 {
421 //see also Hw.c
422 u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
423 if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
424 {
425 *(u32 *)(p + (mem & 0xffff)) = value;
426 psxCpu->Clear(mem&~3, 1);
427 }
428 else
429 {
430 if (t == 0x1d00)
431 {
432 MEM_LOG("iop Sif reg write %x value %x", mem, value);
433 switch (mem & 0x8f0)
434 {
435 case 0x00: // EE write path (EE/IOP readable)
436 return; // this is the IOP, so read-only (do nothing)
437
438 case 0x10: // IOP write path (EE/IOP readable)
439 psHu32(SBUS_F210) = value;
440 return;
441
442 case 0x20: // Bits cleared when written from IOP.
443 psHu32(SBUS_F220) &= ~value;
444 return;
445
446 case 0x30: // bits set when written from IOP
447 psHu32(SBUS_F230) |= value;
448 return;
449
450 case 0x40: // Control Register
451 {
452 u32 temp = value & 0xF0;
453 if (value & 0x20 || value & 0x80)
454 {
455 psHu32(SBUS_F240) &= ~0xF000;
456 psHu32(SBUS_F240) |= 0x2000;
457 }
458
459
460 if (psHu32(SBUS_F240) & temp)
461 psHu32(SBUS_F240) &= ~temp;
462 else
463 psHu32(SBUS_F240) |= temp;
464 return;
465 }
466
467 case 0x60:
468 psHu32(SBUS_F260) = 0;
469 return;
470
471 }
472 psxSu32(mem) = value;
473
474 // wtf? why were we writing to the EE's sif space? Commenting this out doesn't
475 // break any of my games, and should be more correct, but I guess we'll see. --air
476 //*(u32*)(eeHw+0xf200+(mem&0xf0)) = value;
477 return;
478 }
479 else if (t == 0x1000)
480 {
481 DEV9write32(mem, value); return;
482 }
483 }
484 }
485 }

  ViewVC Help
Powered by ViewVC 1.1.22