/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta_reference/pcsx2/System.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta_reference/pcsx2/System.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 174 - (show annotations) (download)
Mon Sep 13 17:24:24 2010 UTC (9 years, 11 months ago) by william
File size: 13793 byte(s)
merge r171-173 from https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/debug/0.X/0.9.X/0.9.7/r3113
-- pick up:
* local versioning support from trunk
* get rig of annoying warnings
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 %u.%u.%u.r%d %s - compiled on " __DATE__, PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
111 // SVN_REV, SVN_MODS ? "(modded)" : ""
112 //);
113 Console.WriteLn( Color_StrongGreen, "PCSX2 %s - compiled on " __DATE__, PCSX2_FULL_VERSION());
114 Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion);
115 Console.Newline();
116
117 Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion);
118 Console.Newline();
119
120 Console.WriteLn( Color_StrongBlack, "x86-32 Init:" );
121
122 Console.Indent().WriteLn(
123 L"CPU vendor name = %s\n"
124 L"FamilyID = %x\n"
125 L"x86Family = %s\n"
126 L"CPU speed = %d.%03d ghz\n"
127 L"Cores = %d physical [%d logical]\n"
128 L"x86PType = %s\n"
129 L"x86Flags = %8.8x %8.8x\n"
130 L"x86EFlags = %8.8x",
131 fromUTF8( x86caps.VendorName ).c_str(), x86caps.StepID,
132 fromUTF8( x86caps.FamilyName ).Trim().Trim(false).c_str(),
133 x86caps.Speed / 1000, x86caps.Speed % 1000,
134 x86caps.PhysicalCores, x86caps.LogicalCores,
135 fromUTF8( x86caps.TypeName ).c_str(),
136 x86caps.Flags, x86caps.Flags2,
137 x86caps.EFlags
138 );
139
140 Console.Newline();
141
142 wxArrayString features[2]; // 2 lines, for readability!
143
144 if( x86caps.hasMultimediaExtensions ) features[0].Add( L"MMX" );
145 if( x86caps.hasStreamingSIMDExtensions ) features[0].Add( L"SSE" );
146 if( x86caps.hasStreamingSIMD2Extensions ) features[0].Add( L"SSE2" );
147 if( x86caps.hasStreamingSIMD3Extensions ) features[0].Add( L"SSE3" );
148 if( x86caps.hasSupplementalStreamingSIMD3Extensions ) features[0].Add( L"SSSE3" );
149 if( x86caps.hasStreamingSIMD4Extensions ) features[0].Add( L"SSE4.1" );
150 if( x86caps.hasStreamingSIMD4Extensions2 ) features[0].Add( L"SSE4.2" );
151
152 if( x86caps.hasMultimediaExtensionsExt ) features[1].Add( L"MMX2 " );
153 if( x86caps.has3DNOWInstructionExtensions ) features[1].Add( L"3DNOW " );
154 if( x86caps.has3DNOWInstructionExtensionsExt ) features[1].Add( L"3DNOW2" );
155 if( x86caps.hasStreamingSIMD4ExtensionsA ) features[1].Add( L"SSE4a " );
156
157 wxString result[2];
158 JoinString( result[0], features[0], L".. " );
159 JoinString( result[1], features[1], L".. " );
160
161 Console.WriteLn( Color_StrongBlack, L"x86 Features Detected:" );
162 Console.Indent().WriteLn( result[0] + (result[1].IsEmpty() ? L"" : (L"\n" + result[1])) );
163 Console.Newline();
164 }
165
166 template< typename CpuType >
167 class CpuInitializer
168 {
169 public:
170 ScopedPtr<CpuType> MyCpu;
171
172 CpuInitializer();
173 virtual ~CpuInitializer() throw();
174
175 bool IsAvailable() const
176 {
177 return !!MyCpu;
178 }
179
180 CpuType* GetPtr() { return MyCpu.GetPtr(); }
181 const CpuType* GetPtr() const { return MyCpu.GetPtr(); }
182
183 operator CpuType*() { return GetPtr(); }
184 operator const CpuType*() const { return GetPtr(); }
185 };
186
187 // --------------------------------------------------------------------------------------
188 // CpuInitializer Template
189 // --------------------------------------------------------------------------------------
190 // Helper for initializing various PCSX2 CPU providers, and handing errors and cleanup.
191 //
192 template< typename CpuType >
193 CpuInitializer< CpuType >::CpuInitializer()
194 {
195 try {
196 MyCpu = new CpuType();
197 MyCpu->Allocate();
198 }
199 catch( Exception::RuntimeError& ex )
200 {
201 Console.Error( L"CPU provider error:\n\t" + ex.FormatDiagnosticMessage() );
202 if( MyCpu )
203 MyCpu = NULL;
204 }
205 catch( std::runtime_error& ex )
206 {
207 Console.Error( L"CPU provider error (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
208 if( MyCpu )
209 MyCpu = NULL;
210 }
211 }
212
213 template< typename CpuType >
214 CpuInitializer< CpuType >::~CpuInitializer() throw()
215 {
216 if( MyCpu )
217 MyCpu->Shutdown();
218 }
219
220 class CpuInitializerSet
221 {
222 public:
223 // Note: Allocate sVU first -- it's the most picky.
224
225 CpuInitializer<recSuperVU0> superVU0;
226 CpuInitializer<recSuperVU1> superVU1;
227
228 CpuInitializer<recMicroVU0> microVU0;
229 CpuInitializer<recMicroVU1> microVU1;
230
231 CpuInitializer<InterpVU0> interpVU0;
232 CpuInitializer<InterpVU1> interpVU1;
233
234 public:
235 CpuInitializerSet() {}
236 virtual ~CpuInitializerSet() throw() {}
237 };
238
239
240
241 // returns the translated error message for the Virtual Machine failing to allocate!
242 static wxString GetMemoryErrorVM()
243 {
244 return pxE( ".Popup Error:EmuCore::MemoryForVM",
245 L"PCSX2 is unable to allocate memory needed for the PS2 virtual machine. "
246 L"Close out some memory hogging background tasks and try again."
247 );
248 }
249
250 SysCoreAllocations::SysCoreAllocations()
251 {
252 InstallSignalHandler();
253
254 Console.WriteLn( "Initializing PS2 virtual machine..." );
255
256 m_RecSuccessEE = false;
257 m_RecSuccessIOP = false;
258
259 try
260 {
261 vtlb_Core_Alloc();
262 memAlloc();
263 psxMemAlloc();
264 vuMicroMemAlloc();
265 }
266 // ----------------------------------------------------------------------------
267 catch( Exception::OutOfMemory& ex )
268 {
269 wxString newmsg( ex.UserMsg() + L"\n\n" + GetMemoryErrorVM() );
270 ex.UserMsg() = newmsg;
271 CleanupMess();
272 throw;
273 }
274 catch( std::bad_alloc& ex )
275 {
276 CleanupMess();
277
278 // re-throw std::bad_alloc as something more friendly. This is needed since
279 // much of the code uses new/delete internally, which throw std::bad_alloc on fail.
280
281 throw Exception::OutOfMemory(
282 L"std::bad_alloc caught while trying to allocate memory for the PS2 Virtual Machine.\n"
283 L"Error Details: " + fromUTF8( ex.what() ),
284
285 GetMemoryErrorVM() // translated
286 );
287 }
288
289 Console.WriteLn( "Allocating memory for recompilers..." );
290
291 CpuProviders = new CpuInitializerSet();
292
293 try {
294 recCpu.Allocate();
295 m_RecSuccessEE = true;
296 }
297 catch( Exception::RuntimeError& ex )
298 {
299 Console.Error( L"EE Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
300 recCpu.Shutdown();
301 }
302
303 try {
304 psxRec.Allocate();
305 m_RecSuccessIOP = true;
306 }
307 catch( Exception::RuntimeError& ex )
308 {
309 Console.Error( L"IOP Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
310 psxRec.Shutdown();
311 }
312
313 // hmm! : VU0 and VU1 pre-allocations should do sVU and mVU separately? Sounds complicated. :(
314
315 // If both VUrecs failed, then make sure the SuperVU is totally closed out, because it
316 // actually initializes everything once and then shares it between both VU recs.
317 if( !IsRecAvailable_SuperVU0() && !IsRecAvailable_SuperVU1() )
318 SuperVUDestroy( -1 );
319 }
320
321 bool SysCoreAllocations::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
322 bool SysCoreAllocations::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
323
324 bool SysCoreAllocations::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
325 bool SysCoreAllocations::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
326
327
328 void SysCoreAllocations::CleanupMess() throw()
329 {
330 try
331 {
332 GameDB.Delete();
333 closeNewVif(0);
334 closeNewVif(1);
335
336 // Special SuperVU "complete" terminator (stupid hacky recompiler)
337 SuperVUDestroy( -1 );
338
339 psxRec.Shutdown();
340 recCpu.Shutdown();
341
342 vuMicroMemShutdown();
343 psxMemShutdown();
344 memShutdown();
345 vtlb_Core_Shutdown();
346 }
347 DESTRUCTOR_CATCHALL
348 }
349
350 SysCoreAllocations::~SysCoreAllocations() throw()
351 {
352 CleanupMess();
353 }
354
355 bool SysCoreAllocations::HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const
356 {
357 return (recOpts.EnableEE && !IsRecAvailable_EE()) ||
358 (recOpts.EnableIOP && !IsRecAvailable_IOP()) ||
359 (recOpts.EnableVU0 && recOpts.UseMicroVU0 && !IsRecAvailable_MicroVU0()) ||
360 (recOpts.EnableVU1 && recOpts.UseMicroVU0 && !IsRecAvailable_MicroVU1()) ||
361 (recOpts.EnableVU0 && !recOpts.UseMicroVU0 && !IsRecAvailable_SuperVU0()) ||
362 (recOpts.EnableVU1 && !recOpts.UseMicroVU1 && !IsRecAvailable_SuperVU1());
363
364 }
365
366 BaseVUmicroCPU* CpuVU0 = NULL;
367 BaseVUmicroCPU* CpuVU1 = NULL;
368
369 void SysCoreAllocations::SelectCpuProviders() const
370 {
371 Cpu = CHECK_EEREC ? &recCpu : &intCpu;
372 psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
373
374 CpuVU0 = CpuProviders->interpVU0;
375 CpuVU1 = CpuProviders->interpVU1;
376
377 if( EmuConfig.Cpu.Recompiler.EnableVU0 )
378 CpuVU0 = EmuConfig.Cpu.Recompiler.UseMicroVU0 ? (BaseVUmicroCPU*)CpuProviders->microVU0 : (BaseVUmicroCPU*)CpuProviders->superVU0;
379
380 if( EmuConfig.Cpu.Recompiler.EnableVU1 )
381 CpuVU1 = EmuConfig.Cpu.Recompiler.UseMicroVU1 ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->superVU1;
382 }
383
384
385 // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
386 // This can be called at any time outside the context of a Cpu->Execute() block without
387 // bad things happening (recompilers will slow down for a brief moment since rec code blocks
388 // are dumped).
389 // Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
390 void SysClearExecutionCache()
391 {
392 GetSysCoreAlloc().SelectCpuProviders();
393
394 // SuperVUreset will do nothing is none of the recs are initialized.
395 // But it's needed if one or the other is initialized.
396 SuperVUReset(-1);
397
398 Cpu->Reset();
399 psxCpu->Reset();
400 CpuVU0->Reset();
401 CpuVU1->Reset();
402
403 resetNewVif(0);
404 resetNewVif(1);
405 }
406
407 // Maps a block of memory for use as a recompiled code buffer, and ensures that the
408 // allocation is below a certain memory address (specified in "bounds" parameter).
409 // The allocated block has code execution privileges.
410 // Returns NULL on allocation failure.
411 u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
412 {
413 u8 *Mem = (u8*)HostSys::Mmap( base, size );
414
415 if( (Mem == NULL) || (bounds != 0 && (((uptr)Mem + size) > bounds)) )
416 {
417 if( base != NULL )
418 {
419 DbgCon.Warning( "First try failed allocating %s at address 0x%x", caller, base );
420
421 // memory allocation *must* have the top bit clear, so let's try again
422 // with NULL (let the OS pick something for us).
423
424 SafeSysMunmap( Mem, size );
425
426 Mem = (u8*)HostSys::Mmap( NULL, size );
427 }
428
429 if( bounds != 0 && (((uptr)Mem + size) > bounds) )
430 {
431 DevCon.Warning( "Second try failed allocating %s, block ptr 0x%x does not meet required criteria.", caller, Mem );
432 SafeSysMunmap( Mem, size );
433
434 // returns NULL, caller should throw an exception.
435 }
436 }
437 return Mem;
438 }

  ViewVC Help
Powered by ViewVC 1.1.22