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

  ViewVC Help
Powered by ViewVC 1.1.22