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

Annotation of /trunk/pcsx2/IopMem.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (hide annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 9 months ago) by william
File size: 10627 byte(s)
re-commit (had local access denied errors when committing)
1 william 31 /* 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 william 273 IopVM_MemoryAllocMess* iopMem = NULL;
24 william 31
25 william 273 __pagealigned u8 iopHw[Ps2MemSize::IopHardware];
26    
27 william 280 // --------------------------------------------------------------------------------------
28     // iopMemoryReserve
29     // --------------------------------------------------------------------------------------
30     iopMemoryReserve::iopMemoryReserve()
31     : _parent( L"IOP Main Memory (2mb)", sizeof(*iopMem) )
32 william 31 {
33 william 280 }
34 william 31
35 william 280 void iopMemoryReserve::Reserve()
36     {
37     _parent::Reserve(HostMemoryMap::IOPmem);
38     //_parent::Reserve(EmuConfig.HostMap.IOP);
39 william 31 }
40    
41 william 280 void iopMemoryReserve::Commit()
42     {
43     _parent::Commit();
44     iopMem = (IopVM_MemoryAllocMess*)m_reserve.GetPtr();
45     }
46    
47 william 31 // Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated,
48     // which is performed by MemInit and PsxMemInit()
49 william 280 void iopMemoryReserve::Reset()
50 william 31 {
51 william 280 _parent::Reset();
52 william 31
53 william 280 pxAssume( iopMem );
54 william 31
55 william 280 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 william 31 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 william 273 psxMemWLUT[i + 0x0000] = (uptr)&iopMem->Main[(i & 0x1f) << 16];
73 william 31
74     // RLUTs, accessed through WLUT.
75 william 273 psxMemWLUT[i + 0x2000] = (uptr)&iopMem->Main[(i & 0x1f) << 16];
76 william 31 }
77    
78     // A few single-page allocations for things we store in special locations.
79 william 273 psxMemWLUT[0x2000 + 0x1f00] = (uptr)iopMem->P;
80     psxMemWLUT[0x2000 + 0x1f80] = (uptr)iopHw;
81     //psxMemWLUT[0x1bf80] = (uptr)iopHw;
82 william 31
83 william 273 psxMemWLUT[0x1f00] = (uptr)iopMem->P;
84     psxMemWLUT[0x1f80] = (uptr)iopHw;
85     //psxMemWLUT[0xbf80] = (uptr)iopHw;
86 william 31
87     // Read-only memory areas, so don't map WLUT for these...
88     for (int i=0; i<0x0040; i++)
89     {
90 william 62 psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&eeMem->ROM[i << 16];
91 william 31 }
92    
93     for (int i=0; i<0x0004; i++)
94     {
95 william 62 psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&eeMem->ROM1[i << 16];
96 william 31 }
97    
98     // sif!! (which is read only? (air))
99 william 273 psxMemWLUT[0x2000 + 0x1d00] = (uptr)iopMem->Sif;
100     //psxMemWLUT[0x1bd00] = (uptr)iopMem->Sif;
101 william 31
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 william 280 void iopMemoryReserve::Decommit()
108 william 31 {
109 william 280 _parent::Decommit();
110 william 31
111     safe_aligned_free(psxMemWLUT);
112     psxMemRLUT = NULL;
113 william 280 iopMem = NULL;
114 william 31 }
115    
116 william 280 void iopMemoryReserve::Release()
117     {
118     _parent::Release();
119     iopMem = NULL;
120     }
121    
122    
123 william 31 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 william 62 //*(u32*)(eeHw+0xf200+(mem&0xf0)) = value;
477 william 31 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