/[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 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 11 months ago) by william
File size: 10701 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
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 u8 *psxM = NULL;
21 u8 *psxP = NULL;
22 u8 *psxH = NULL; // standard hardware registers (0x000->0x3ff is the scratchpad)
23 u8 *psxS = NULL; // 'undocumented' SIF communication registers
24
25 uptr *psxMemWLUT = NULL;
26 const uptr *psxMemRLUT = NULL;
27
28 static u8* m_psxAllMem = NULL;
29 static const uint m_psxMemSize =
30 Ps2MemSize::IopRam +
31 Ps2MemSize::IopHardware +
32 0x00010000 + // psxP
33 0x00000100 ; // psxS
34
35 void psxMemAlloc()
36 {
37 if( m_psxAllMem == NULL )
38 m_psxAllMem = vtlb_malloc( m_psxMemSize, 4096 );
39
40 if( m_psxAllMem == NULL)
41 throw Exception::OutOfMemory( L"IOP system ram (and roms)" );
42
43 u8* curpos = m_psxAllMem;
44 psxM = curpos; curpos += Ps2MemSize::IopRam;
45 psxP = curpos; curpos += 0x00010000;
46 psxH = curpos; curpos += Ps2MemSize::IopHardware;
47 psxS = curpos; //curpos += 0x00010000;
48
49 psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 16);
50 psxMemRLUT = psxMemWLUT + 0x2000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16);
51 }
52
53 // Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated,
54 // which is performed by MemInit and PsxMemInit()
55 void psxMemReset()
56 {
57 pxAssume( psxMemWLUT != NULL );
58 pxAssume( m_psxAllMem != NULL );
59
60 DbgCon.WriteLn( "IOP Resetting physical ram..." );
61
62 memzero_ptr<0x2000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT
63 memzero_ptr<m_psxMemSize>( m_psxAllMem );
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)&psxM[(i & 0x1f) << 16];
73
74 // RLUTs, accessed through WLUT.
75 psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16];
76 }
77
78 // A few single-page allocations for things we store in special locations.
79 psxMemWLUT[0x2000 + 0x1f00] = (uptr)psxP;
80 psxMemWLUT[0x2000 + 0x1f80] = (uptr)psxH;
81 //psxMemWLUT[0x1bf80] = (uptr)psxH;
82
83 psxMemWLUT[0x1f00] = (uptr)psxP;
84 psxMemWLUT[0x1f80] = (uptr)psxH;
85 //psxMemWLUT[0xbf80] = (uptr)psxH;
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)psxS;
100 //psxMemWLUT[0x1bd00] = (uptr)psxS;
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 psxMemShutdown()
108 {
109 vtlb_free( m_psxAllMem, m_psxMemSize );
110 m_psxAllMem = NULL;
111
112 psxM = psxP = psxH = psxS = NULL;
113
114 safe_aligned_free(psxMemWLUT);
115 psxMemRLUT = NULL;
116 }
117
118 u8 __fastcall iopMemRead8(u32 mem)
119 {
120 mem &= 0x1fffffff;
121 u32 t = mem >> 16;
122
123 if (t == 0x1f80)
124 {
125 switch( mem & 0xf000 )
126 {
127 case 0x1000: return IopMemory::iopHwRead8_Page1(mem);
128 case 0x3000: return IopMemory::iopHwRead8_Page3(mem);
129 case 0x8000: return IopMemory::iopHwRead8_Page8(mem);
130
131 default:
132 return psxHu8(mem);
133 }
134 }
135 else if (t == 0x1f40)
136 {
137 return psxHw4Read8(mem);
138 }
139 else
140 {
141 const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
142 if (p != NULL)
143 {
144 return *(const u8 *)(p + (mem & 0xffff));
145 }
146 else
147 {
148 if (t == 0x1000)
149 return DEV9read8(mem);
150 PSXMEM_LOG("err lb %8.8lx", mem);
151 return 0;
152 }
153 }
154 }
155
156 u16 __fastcall iopMemRead16(u32 mem)
157 {
158 mem &= 0x1fffffff;
159 u32 t = mem >> 16;
160
161 if (t == 0x1f80)
162 {
163 switch( mem & 0xf000 )
164 {
165 case 0x1000: return IopMemory::iopHwRead16_Page1(mem);
166 case 0x3000: return IopMemory::iopHwRead16_Page3(mem);
167 case 0x8000: return IopMemory::iopHwRead16_Page8(mem);
168
169 default:
170 return psxHu16(mem);
171 }
172 }
173 else
174 {
175 const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
176 if (p != NULL)
177 {
178 if (t == 0x1d00)
179 {
180 u16 ret;
181 switch(mem & 0xF0)
182 {
183 case 0x00:
184 ret= psHu16(SBUS_F200);
185 break;
186 case 0x10:
187 ret= psHu16(SBUS_F210);
188 break;
189 case 0x40:
190 ret= psHu16(SBUS_F240) | 0x0002;
191 break;
192 case 0x60:
193 ret = 0;
194 break;
195 default:
196 ret = psxHu16(mem);
197 break;
198 }
199 //SIF_LOG("Sif reg read %x value %x", mem, ret);
200 return ret;
201 }
202 return *(const u16 *)(p + (mem & 0xffff));
203 }
204 else
205 {
206 if (t == 0x1F90)
207 return SPU2read(mem);
208 if (t == 0x1000)
209 return DEV9read16(mem);
210 PSXMEM_LOG("err lh %8.8lx", mem);
211 return 0;
212 }
213 }
214 }
215
216 u32 __fastcall iopMemRead32(u32 mem)
217 {
218 mem &= 0x1fffffff;
219 u32 t = mem >> 16;
220
221 if (t == 0x1f80)
222 {
223 switch( mem & 0xf000 )
224 {
225 case 0x1000: return IopMemory::iopHwRead32_Page1(mem);
226 case 0x3000: return IopMemory::iopHwRead32_Page3(mem);
227 case 0x8000: return IopMemory::iopHwRead32_Page8(mem);
228
229 default:
230 return psxHu32(mem);
231 }
232 } else
233 {
234 //see also Hw.c
235 const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
236 if (p != NULL)
237 {
238 if (t == 0x1d00)
239 {
240 u32 ret;
241 switch(mem & 0x8F0)
242 {
243 case 0x00:
244 ret= psHu32(SBUS_F200);
245 break;
246 case 0x10:
247 ret= psHu32(SBUS_F210);
248 break;
249 case 0x20:
250 ret= psHu32(SBUS_F220);
251 break;
252 case 0x30: // EE Side
253 ret= psHu32(SBUS_F230);
254 break;
255 case 0x40:
256 ret= psHu32(SBUS_F240) | 0xF0000002;
257 break;
258 case 0x60:
259 ret = 0;
260 break;
261
262 default:
263 ret = psxHu32(mem);
264 break;
265 }
266 //SIF_LOG("Sif reg read %x value %x", mem, ret);
267 return ret;
268 }
269 return *(const u32 *)(p + (mem & 0xffff));
270 }
271 else
272 {
273 if (t == 0x1000)
274 return DEV9read32(mem);
275 return 0;
276 }
277 }
278 }
279
280 void __fastcall iopMemWrite8(u32 mem, u8 value)
281 {
282 mem &= 0x1fffffff;
283 u32 t = mem >> 16;
284
285 if (t == 0x1f80)
286 {
287 switch( mem & 0xf000 )
288 {
289 case 0x1000: IopMemory::iopHwWrite8_Page1(mem,value); break;
290 case 0x3000: IopMemory::iopHwWrite8_Page3(mem,value); break;
291 case 0x8000: IopMemory::iopHwWrite8_Page8(mem,value); break;
292
293 default:
294 psxHu8(mem) = value;
295 break;
296 }
297 }
298 else if (t == 0x1f40)
299 {
300 psxHw4Write8(mem, value);
301 }
302 else
303 {
304 u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
305 if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
306 {
307 *(u8 *)(p + (mem & 0xffff)) = value;
308 psxCpu->Clear(mem&~3, 1);
309 }
310 else
311 {
312 if (t == 0x1d00)
313 {
314 Console.WriteLn("sw8 [0x%08X]=0x%08X", mem, value);
315 psxSu8(mem) = value;
316 return;
317 }
318 if (t == 0x1000)
319 {
320 DEV9write8(mem, value); return;
321 }
322 PSXMEM_LOG("err sb %8.8lx = %x", mem, value);
323 }
324 }
325 }
326
327 void __fastcall iopMemWrite16(u32 mem, u16 value)
328 {
329 mem &= 0x1fffffff;
330 u32 t = mem >> 16;
331
332 if (t == 0x1f80)
333 {
334 switch( mem & 0xf000 )
335 {
336 case 0x1000: IopMemory::iopHwWrite16_Page1(mem,value); break;
337 case 0x3000: IopMemory::iopHwWrite16_Page3(mem,value); break;
338 case 0x8000: IopMemory::iopHwWrite16_Page8(mem,value); break;
339
340 default:
341 psxHu16(mem) = value;
342 break;
343 }
344 } else
345 {
346 u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
347 if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
348 {
349 if( t==0x1D00 ) Console.WriteLn("sw16 [0x%08X]=0x%08X", mem, value);
350 *(u16 *)(p + (mem & 0xffff)) = value;
351 psxCpu->Clear(mem&~3, 1);
352 }
353 else
354 {
355 if (t == 0x1d00)
356 {
357 switch (mem & 0x8f0)
358 {
359 case 0x10:
360 // write to ps2 mem
361 psHu16(SBUS_F210) = value;
362 return;
363 case 0x40:
364 {
365 u32 temp = value & 0xF0;
366 // write to ps2 mem
367 if(value & 0x20 || value & 0x80)
368 {
369 psHu16(SBUS_F240) &= ~0xF000;
370 psHu16(SBUS_F240) |= 0x2000;
371 }
372
373
374 if(psHu16(SBUS_F240) & temp)
375 psHu16(SBUS_F240) &= ~temp;
376 else
377 psHu16(SBUS_F240) |= temp;
378 return;
379 }
380 case 0x60:
381 psHu32(SBUS_F260) = 0;
382 return;
383 }
384 psxSu16(mem) = value; return;
385 }
386 if (t == 0x1F90) {
387 SPU2write(mem, value); return;
388 }
389 if (t == 0x1000) {
390 DEV9write16(mem, value); return;
391 }
392 PSXMEM_LOG("err sh %8.8lx = %x", mem, value);
393 }
394 }
395 }
396
397 void __fastcall iopMemWrite32(u32 mem, u32 value)
398 {
399 mem &= 0x1fffffff;
400 u32 t = mem >> 16;
401
402 if (t == 0x1f80)
403 {
404 switch( mem & 0xf000 )
405 {
406 case 0x1000: IopMemory::iopHwWrite32_Page1(mem,value); break;
407 case 0x3000: IopMemory::iopHwWrite32_Page3(mem,value); break;
408 case 0x8000: IopMemory::iopHwWrite32_Page8(mem,value); break;
409
410 default:
411 psxHu32(mem) = value;
412 break;
413 }
414 } else
415 {
416 //see also Hw.c
417 u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
418 if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
419 {
420 *(u32 *)(p + (mem & 0xffff)) = value;
421 psxCpu->Clear(mem&~3, 1);
422 }
423 else
424 {
425 if (t == 0x1d00)
426 {
427 MEM_LOG("iop Sif reg write %x value %x", mem, value);
428 switch (mem & 0x8f0)
429 {
430 case 0x00: // EE write path (EE/IOP readable)
431 return; // this is the IOP, so read-only (do nothing)
432
433 case 0x10: // IOP write path (EE/IOP readable)
434 psHu32(SBUS_F210) = value;
435 return;
436
437 case 0x20: // Bits cleared when written from IOP.
438 psHu32(SBUS_F220) &= ~value;
439 return;
440
441 case 0x30: // bits set when written from IOP
442 psHu32(SBUS_F230) |= value;
443 return;
444
445 case 0x40: // Control Register
446 {
447 u32 temp = value & 0xF0;
448 if (value & 0x20 || value & 0x80)
449 {
450 psHu32(SBUS_F240) &= ~0xF000;
451 psHu32(SBUS_F240) |= 0x2000;
452 }
453
454
455 if (psHu32(SBUS_F240) & temp)
456 psHu32(SBUS_F240) &= ~temp;
457 else
458 psHu32(SBUS_F240) |= temp;
459 return;
460 }
461
462 case 0x60:
463 psHu32(SBUS_F260) = 0;
464 return;
465
466 }
467 psxSu32(mem) = value;
468
469 // wtf? why were we writing to the EE's sif space? Commenting this out doesn't
470 // break any of my games, and should be more correct, but I guess we'll see. --air
471 //*(u32*)(eeHw+0xf200+(mem&0xf0)) = value;
472 return;
473 }
474 else if (t == 0x1000)
475 {
476 DEV9write32(mem, value); return;
477 }
478 }
479 }
480 }

  ViewVC Help
Powered by ViewVC 1.1.22