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

Contents of /trunk/pcsx2/System.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show 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 /* 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