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

Annotation of /trunk/pcsx2/System.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 15314 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
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     #include "PrecompiledHeader.h"
17     #include "Common.h"
18 william 62 #include "IopCommon.h"
19 william 31
20     #include "System/PageFaultSource.h"
21     #include "Utilities/EventSource.inl"
22    
23     // Includes needed for cleanup, since we don't have a good system (yet) for
24     // cleaning up these things.
25     #include "sVU_zerorec.h"
26 william 62 #include "GameDatabase.h"
27     #include "Elfheader.h"
28 william 31
29     extern void closeNewVif(int idx);
30     extern void resetNewVif(int idx);
31    
32     template class EventSource< IEventListener_PageFault >;
33    
34     SrcType_PageFault Source_PageFault;
35    
36     EventListener_PageFault::EventListener_PageFault()
37     {
38     Source_PageFault.Add( *this );
39     }
40    
41     EventListener_PageFault::~EventListener_PageFault() throw()
42     {
43     Source_PageFault.Remove( *this );
44     }
45    
46     void SrcType_PageFault::Dispatch( const PageFaultInfo& params )
47     {
48     m_handled = false;
49     _parent::Dispatch( params );
50     }
51    
52     void SrcType_PageFault::_DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt )
53     {
54     do {
55     (*iter)->DispatchEvent( evt, m_handled );
56     } while( (++iter != iend) && !m_handled );
57     }
58    
59    
60     #if _MSC_VER
61     # include "svnrev.h"
62     #endif
63    
64     const Pcsx2Config EmuConfig;
65    
66     // Provides an accessor for quick modification of GS options. All GS options are allowed to be
67     // changed "on the fly" by the *main/gui thread only*.
68     Pcsx2Config::GSOptions& SetGSConfig()
69     {
70     //DbgCon.WriteLn( "Direct modification of EmuConfig.GS detected" );
71     AffinityAssert_AllowFrom_MainUI();
72     return const_cast<Pcsx2Config::GSOptions&>(EmuConfig.GS);
73     }
74    
75     // Provides an accessor for quick modification of Recompiler options.
76     // Used by loadGameSettings() to set clamp modes via database at game startup.
77     Pcsx2Config::RecompilerOptions& SetRecompilerConfig()
78     {
79     //DbgCon.WriteLn( "Direct modification of EmuConfig.Gamefixes detected" );
80     AffinityAssert_AllowFrom_MainUI();
81     return const_cast<Pcsx2Config::RecompilerOptions&>(EmuConfig.Cpu.Recompiler);
82     }
83    
84     // Provides an accessor for quick modification of Gamefix options.
85     // Used by loadGameSettings() to set gamefixes via database at game startup.
86     Pcsx2Config::GamefixOptions& SetGameFixConfig()
87     {
88     //DbgCon.WriteLn( "Direct modification of EmuConfig.Gamefixes detected" );
89     AffinityAssert_AllowFrom_MainUI();
90     return const_cast<Pcsx2Config::GamefixOptions&>(EmuConfig.Gamefixes);
91     }
92    
93     TraceLogFilters& SetTraceConfig()
94     {
95     //DbgCon.WriteLn( "Direct modification of EmuConfig.TraceLog detected" );
96     AffinityAssert_AllowFrom_MainUI();
97     return const_cast<TraceLogFilters&>(EmuConfig.Trace);
98     }
99    
100    
101     // This function should be called once during program execution.
102     void SysLogMachineCaps()
103     {
104 william 62 Console.WriteLn( Color_StrongGreen, "PCSX2 %u.%u.%u.r%d %s - compiled on " __DATE__, PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
105 william 31 SVN_REV, SVN_MODS ? "(modded)" : ""
106     );
107    
108     Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion);
109     Console.Newline();
110    
111     Console.WriteLn( Color_StrongBlack, "x86-32 Init:" );
112    
113 william 62 u32 speed = x86caps.CalculateMHz();
114    
115 william 31 Console.Indent().WriteLn(
116     L"CPU vendor name = %s\n"
117     L"FamilyID = %x\n"
118     L"x86Family = %s\n"
119     L"CPU speed = %d.%03d ghz\n"
120     L"Cores = %d physical [%d logical]\n"
121     L"x86PType = %s\n"
122     L"x86Flags = %8.8x %8.8x\n"
123     L"x86EFlags = %8.8x",
124     fromUTF8( x86caps.VendorName ).c_str(), x86caps.StepID,
125     fromUTF8( x86caps.FamilyName ).Trim().Trim(false).c_str(),
126 william 62 speed / 1000, speed % 1000,
127 william 31 x86caps.PhysicalCores, x86caps.LogicalCores,
128 william 62 x86caps.GetTypeName().c_str(),
129 william 31 x86caps.Flags, x86caps.Flags2,
130     x86caps.EFlags
131     );
132    
133     Console.Newline();
134    
135     wxArrayString features[2]; // 2 lines, for readability!
136    
137     if( x86caps.hasMultimediaExtensions ) features[0].Add( L"MMX" );
138     if( x86caps.hasStreamingSIMDExtensions ) features[0].Add( L"SSE" );
139     if( x86caps.hasStreamingSIMD2Extensions ) features[0].Add( L"SSE2" );
140     if( x86caps.hasStreamingSIMD3Extensions ) features[0].Add( L"SSE3" );
141     if( x86caps.hasSupplementalStreamingSIMD3Extensions ) features[0].Add( L"SSSE3" );
142     if( x86caps.hasStreamingSIMD4Extensions ) features[0].Add( L"SSE4.1" );
143     if( x86caps.hasStreamingSIMD4Extensions2 ) features[0].Add( L"SSE4.2" );
144    
145     if( x86caps.hasMultimediaExtensionsExt ) features[1].Add( L"MMX2 " );
146     if( x86caps.has3DNOWInstructionExtensions ) features[1].Add( L"3DNOW " );
147     if( x86caps.has3DNOWInstructionExtensionsExt ) features[1].Add( L"3DNOW2" );
148     if( x86caps.hasStreamingSIMD4ExtensionsA ) features[1].Add( L"SSE4a " );
149    
150 william 62 const wxString result[2] =
151     {
152     JoinString( features[0], L".. " ),
153     JoinString( features[1], L".. " )
154     };
155 william 31
156     Console.WriteLn( Color_StrongBlack, L"x86 Features Detected:" );
157     Console.Indent().WriteLn( result[0] + (result[1].IsEmpty() ? L"" : (L"\n" + result[1])) );
158     Console.Newline();
159     }
160    
161     template< typename CpuType >
162     class CpuInitializer
163     {
164     public:
165 william 62 ScopedPtr<CpuType> MyCpu;
166     ScopedPtr<BaseException> ExThrown;
167    
168 william 31 CpuInitializer();
169     virtual ~CpuInitializer() throw();
170    
171     bool IsAvailable() const
172     {
173     return !!MyCpu;
174     }
175    
176     CpuType* GetPtr() { return MyCpu.GetPtr(); }
177     const CpuType* GetPtr() const { return MyCpu.GetPtr(); }
178    
179     operator CpuType*() { return GetPtr(); }
180     operator const CpuType*() const { return GetPtr(); }
181     };
182    
183     // --------------------------------------------------------------------------------------
184     // CpuInitializer Template
185     // --------------------------------------------------------------------------------------
186     // Helper for initializing various PCSX2 CPU providers, and handing errors and cleanup.
187     //
188     template< typename CpuType >
189     CpuInitializer< CpuType >::CpuInitializer()
190     {
191     try {
192     MyCpu = new CpuType();
193     MyCpu->Allocate();
194     }
195     catch( Exception::RuntimeError& ex )
196     {
197     Console.Error( L"CPU provider error:\n\t" + ex.FormatDiagnosticMessage() );
198 william 62 MyCpu = NULL;
199     ExThrown = ex.Clone();
200 william 31 }
201     catch( std::runtime_error& ex )
202     {
203     Console.Error( L"CPU provider error (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
204 william 62 MyCpu = NULL;
205     ExThrown = new Exception::RuntimeError(ex);
206 william 31 }
207     }
208    
209     template< typename CpuType >
210     CpuInitializer< CpuType >::~CpuInitializer() throw()
211     {
212     if( MyCpu )
213     MyCpu->Shutdown();
214     }
215    
216     class CpuInitializerSet
217     {
218     public:
219     // Note: Allocate sVU first -- it's the most picky.
220    
221     CpuInitializer<recSuperVU0> superVU0;
222     CpuInitializer<recSuperVU1> superVU1;
223    
224     CpuInitializer<recMicroVU0> microVU0;
225     CpuInitializer<recMicroVU1> microVU1;
226    
227     CpuInitializer<InterpVU0> interpVU0;
228     CpuInitializer<InterpVU1> interpVU1;
229    
230     public:
231     CpuInitializerSet() {}
232     virtual ~CpuInitializerSet() throw() {}
233     };
234    
235    
236    
237     // returns the translated error message for the Virtual Machine failing to allocate!
238     static wxString GetMemoryErrorVM()
239     {
240 william 62 return pxE( ".Error:EmuCore::MemoryForVM",
241 william 31 L"PCSX2 is unable to allocate memory needed for the PS2 virtual machine. "
242     L"Close out some memory hogging background tasks and try again."
243     );
244     }
245    
246 william 62 // --------------------------------------------------------------------------------------
247     // SysAllocVM (implementations)
248     // --------------------------------------------------------------------------------------
249     SysAllocVM::SysAllocVM()
250 william 31 {
251     InstallSignalHandler();
252    
253 william 62 Console.WriteLn( "Allocating memory for the PS2 virtual machine..." );
254 william 31
255     try
256     {
257     vtlb_Core_Alloc();
258     memAlloc();
259     psxMemAlloc();
260     vuMicroMemAlloc();
261     }
262     // ----------------------------------------------------------------------------
263     catch( Exception::OutOfMemory& ex )
264     {
265 william 62 ex.UserMsg() += L"\n\n" + GetMemoryErrorVM();
266 william 31 CleanupMess();
267     throw;
268     }
269     catch( std::bad_alloc& ex )
270     {
271     CleanupMess();
272    
273     // re-throw std::bad_alloc as something more friendly. This is needed since
274     // much of the code uses new/delete internally, which throw std::bad_alloc on fail.
275    
276 william 62 throw Exception::OutOfMemory()
277     .SetDiagMsg(
278     L"std::bad_alloc caught while trying to allocate memory for the PS2 Virtual Machine.\n"
279     L"Error Details: " + fromUTF8( ex.what() )
280     )
281     .SetUserMsg(GetMemoryErrorVM()); // translated
282     }
283     }
284 william 31
285 william 62 void SysAllocVM::CleanupMess() throw()
286     {
287     try
288     {
289     vuMicroMemShutdown();
290     psxMemShutdown();
291     memShutdown();
292     vtlb_Core_Shutdown();
293 william 31 }
294 william 62 DESTRUCTOR_CATCHALL
295     }
296 william 31
297 william 62 SysAllocVM::~SysAllocVM() throw()
298     {
299     CleanupMess();
300     }
301    
302     // --------------------------------------------------------------------------------------
303     // SysCpuProviderPack (implementations)
304     // --------------------------------------------------------------------------------------
305     SysCpuProviderPack::SysCpuProviderPack()
306     {
307 william 31 Console.WriteLn( "Allocating memory for recompilers..." );
308    
309     CpuProviders = new CpuInitializerSet();
310    
311     try {
312     recCpu.Allocate();
313     }
314     catch( Exception::RuntimeError& ex )
315     {
316 william 62 m_RecExceptionEE = ex.Clone();
317 william 31 Console.Error( L"EE Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
318     recCpu.Shutdown();
319     }
320    
321     try {
322     psxRec.Allocate();
323     }
324     catch( Exception::RuntimeError& ex )
325     {
326 william 62 m_RecExceptionIOP = ex.Clone();
327 william 31 Console.Error( L"IOP Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
328     psxRec.Shutdown();
329     }
330    
331     // hmm! : VU0 and VU1 pre-allocations should do sVU and mVU separately? Sounds complicated. :(
332    
333     // If both VUrecs failed, then make sure the SuperVU is totally closed out, because it
334     // actually initializes everything once and then shares it between both VU recs.
335     if( !IsRecAvailable_SuperVU0() && !IsRecAvailable_SuperVU1() )
336     SuperVUDestroy( -1 );
337     }
338    
339 william 62 bool SysCpuProviderPack::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
340     bool SysCpuProviderPack::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
341     BaseException* SysCpuProviderPack::GetException_MicroVU0() const { return CpuProviders->microVU0.ExThrown; }
342     BaseException* SysCpuProviderPack::GetException_MicroVU1() const { return CpuProviders->microVU1.ExThrown; }
343 william 31
344 william 62 bool SysCpuProviderPack::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
345     bool SysCpuProviderPack::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
346     BaseException* SysCpuProviderPack::GetException_SuperVU0() const { return CpuProviders->superVU0.ExThrown; }
347     BaseException* SysCpuProviderPack::GetException_SuperVU1() const { return CpuProviders->superVU1.ExThrown; }
348 william 31
349    
350 william 62 void SysCpuProviderPack::CleanupMess() throw()
351 william 31 {
352     try
353     {
354     closeNewVif(0);
355     closeNewVif(1);
356    
357     // Special SuperVU "complete" terminator (stupid hacky recompiler)
358     SuperVUDestroy( -1 );
359    
360     psxRec.Shutdown();
361     recCpu.Shutdown();
362     }
363     DESTRUCTOR_CATCHALL
364     }
365    
366 william 62 SysCpuProviderPack::~SysCpuProviderPack() throw()
367 william 31 {
368     CleanupMess();
369     }
370    
371 william 62 bool SysCpuProviderPack::HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const
372 william 31 {
373     return (recOpts.EnableEE && !IsRecAvailable_EE()) ||
374     (recOpts.EnableIOP && !IsRecAvailable_IOP()) ||
375     (recOpts.EnableVU0 && recOpts.UseMicroVU0 && !IsRecAvailable_MicroVU0()) ||
376     (recOpts.EnableVU1 && recOpts.UseMicroVU0 && !IsRecAvailable_MicroVU1()) ||
377     (recOpts.EnableVU0 && !recOpts.UseMicroVU0 && !IsRecAvailable_SuperVU0()) ||
378     (recOpts.EnableVU1 && !recOpts.UseMicroVU1 && !IsRecAvailable_SuperVU1());
379    
380     }
381    
382     BaseVUmicroCPU* CpuVU0 = NULL;
383     BaseVUmicroCPU* CpuVU1 = NULL;
384    
385 william 62 void SysCpuProviderPack::ApplyConfig() const
386 william 31 {
387     Cpu = CHECK_EEREC ? &recCpu : &intCpu;
388     psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
389    
390     CpuVU0 = CpuProviders->interpVU0;
391     CpuVU1 = CpuProviders->interpVU1;
392    
393     if( EmuConfig.Cpu.Recompiler.EnableVU0 )
394     CpuVU0 = EmuConfig.Cpu.Recompiler.UseMicroVU0 ? (BaseVUmicroCPU*)CpuProviders->microVU0 : (BaseVUmicroCPU*)CpuProviders->superVU0;
395    
396     if( EmuConfig.Cpu.Recompiler.EnableVU1 )
397     CpuVU1 = EmuConfig.Cpu.Recompiler.UseMicroVU1 ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->superVU1;
398     }
399    
400 william 62 // This is a semi-hacky function for convenience
401     BaseVUmicroCPU* SysCpuProviderPack::getVUprovider(int whichProvider, int vuIndex) const {
402     switch (whichProvider) {
403     case 0: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->interpVU1 : (BaseVUmicroCPU*)CpuProviders->interpVU0;
404     case 1: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->superVU1 : (BaseVUmicroCPU*)CpuProviders->superVU0;
405     case 2: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->microVU0;
406     }
407     return NULL;
408     }
409 william 31
410     // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
411     // This can be called at any time outside the context of a Cpu->Execute() block without
412     // bad things happening (recompilers will slow down for a brief moment since rec code blocks
413     // are dumped).
414     // Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
415     void SysClearExecutionCache()
416     {
417 william 62 GetCpuProviders().ApplyConfig();
418 william 31
419     // SuperVUreset will do nothing is none of the recs are initialized.
420     // But it's needed if one or the other is initialized.
421     SuperVUReset(-1);
422    
423     Cpu->Reset();
424     psxCpu->Reset();
425 william 62 // mVU's VU0 needs to be properly initialised for macro mode even if it's not used for micro mode!
426     if (CHECK_EEREC)
427     ((BaseVUmicroCPU*)GetCpuProviders().CpuProviders->microVU0)->Reset();
428 william 31 CpuVU0->Reset();
429     CpuVU1->Reset();
430    
431     resetNewVif(0);
432     resetNewVif(1);
433     }
434    
435     // Maps a block of memory for use as a recompiled code buffer, and ensures that the
436     // allocation is below a certain memory address (specified in "bounds" parameter).
437     // The allocated block has code execution privileges.
438     // Returns NULL on allocation failure.
439 william 62 u8* SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
440 william 31 {
441 william 62 u8* Mem = (u8*)HostSys::Mmap( base, size );
442 william 31
443     if( (Mem == NULL) || (bounds != 0 && (((uptr)Mem + size) > bounds)) )
444     {
445     if( base != NULL )
446     {
447     DbgCon.Warning( "First try failed allocating %s at address 0x%x", caller, base );
448    
449     // memory allocation *must* have the top bit clear, so let's try again
450     // with NULL (let the OS pick something for us).
451    
452     SafeSysMunmap( Mem, size );
453    
454     Mem = (u8*)HostSys::Mmap( NULL, size );
455     }
456    
457     if( bounds != 0 && (((uptr)Mem + size) > bounds) )
458     {
459     DevCon.Warning( "Second try failed allocating %s, block ptr 0x%x does not meet required criteria.", caller, Mem );
460     SafeSysMunmap( Mem, size );
461    
462     // returns NULL, caller should throw an exception.
463     }
464     }
465     return Mem;
466     }
467 william 62
468     // This function always returns a valid DiscID -- using the Sony serial when possible, and
469     // falling back on the CRC checksum of the ELF binary if the PS2 software being run is
470     // homebrew or some other serial-less item.
471     wxString SysGetDiscID()
472     {
473     if( !DiscSerial.IsEmpty() ) return DiscSerial;
474    
475     if( !ElfCRC )
476     {
477     // FIXME: If the system is currently running the BIOS, it should return a serial based on
478     // the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS
479     // region and revision).
480     }
481    
482     return wxsFormat( L"%8.8x", ElfCRC );
483     }

  ViewVC Help
Powered by ViewVC 1.1.22