/[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 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 10739 byte(s)
committing r3113 initial commit again...
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     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( "psxMemAlloc > failed allocating memory for the IOP processor." );
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     jASSUME( psxMemWLUT != NULL );
58     jASSUME( 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)&PS2MEM_ROM[i << 16];
91     }
92    
93     for (int i=0; i<0x0004; i++)
94     {
95     psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_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*)(PS2MEM_HW+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