/[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 401 - (hide annotations) (download)
Fri Feb 25 17:31:09 2011 UTC (9 years, 9 months ago) by william
File size: 19772 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4358 local: v0.9.7.313-latest) in ./trunk
1 william 283 /* 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 "IopCommon.h"
19     #include "VUmicro.h"
20     #include "newVif.h"
21    
22     #include "SamplProf.h"
23    
24     #include "Elfheader.h"
25    
26     #include "System/RecTypes.h"
27    
28     #include "Utilities/MemsetFast.inl"
29    
30    
31     // --------------------------------------------------------------------------------------
32     // RecompiledCodeReserve (implementations)
33     // --------------------------------------------------------------------------------------
34    
35     // Constructor!
36     // Parameters:
37     // name - a nice long name that accurately describes the contents of this reserve.
38     RecompiledCodeReserve::RecompiledCodeReserve( const wxString& name, uint defCommit )
39     : BaseVmReserveListener( name )
40     {
41     m_blocksize = (1024 * 128) / __pagesize;
42     m_prot_mode = PageAccess_Any();
43     m_def_commit = defCommit / __pagesize;
44    
45     m_profiler_registered = false;
46     }
47    
48     RecompiledCodeReserve::~RecompiledCodeReserve() throw()
49     {
50     _termProfiler();
51     }
52    
53     void RecompiledCodeReserve::_registerProfiler()
54     {
55     if (m_profiler_name.IsEmpty() || !IsOk()) return;
56     ProfilerRegisterSource( m_profiler_name, m_baseptr, GetReserveSizeInBytes() );
57     m_profiler_registered = true;
58     }
59    
60     void RecompiledCodeReserve::_termProfiler()
61     {
62     if (m_profiler_registered)
63     ProfilerTerminateSource( m_profiler_name );
64     }
65    
66     uint RecompiledCodeReserve::_calcDefaultCommitInBlocks() const
67     {
68     return (m_def_commit + m_blocksize - 1) / m_blocksize;
69     }
70    
71     void* RecompiledCodeReserve::Reserve( size_t size, uptr base, uptr upper_bounds )
72     {
73     if (!_parent::Reserve(size, base, upper_bounds)) return NULL;
74     _registerProfiler();
75     return m_baseptr;
76     }
77    
78    
79     // Sets the abbreviated name used by the profiler. Name should be under 10 characters long.
80     // After a name has been set, a profiler source will be automatically registered and cleared
81     // in accordance with changes in the reserve area.
82     RecompiledCodeReserve& RecompiledCodeReserve::SetProfilerName( const wxString& shortname )
83     {
84     m_profiler_name = shortname;
85     _registerProfiler();
86     return *this;
87     }
88    
89     void RecompiledCodeReserve::DoCommitAndProtect( uptr page )
90     {
91     CommitBlocks(page, (m_pages_commited || !m_def_commit) ? 1 : _calcDefaultCommitInBlocks() );
92     }
93    
94     void RecompiledCodeReserve::OnCommittedBlock( void* block )
95     {
96     if (IsDevBuild)
97     {
98     // Clear the recompiled code block to 0xcc (INT3) -- this helps disasm tools show
99     // the assembly dump more cleanly. We don't clear the block on Release builds since
100     // it can add a noticeable amount of overhead to large block recompilations.
101    
102     memset_sse_a<0xcc>( block, m_blocksize * __pagesize );
103     }
104     }
105    
106     // This error message is shared by R5900, R3000, and microVU recompilers. It is not used by the
107     // SuperVU recompiler, since it has its own customized message.
108     void RecompiledCodeReserve::ThrowIfNotOk() const
109     {
110     if (IsOk()) return;
111    
112     throw Exception::OutOfMemory(m_name)
113     .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." ))
114     .SetUserMsg( pxE( "!Notice:Recompiler:VirtualMemoryAlloc",
115     L"This recompiler was unable to reserve contiguous memory required for internal caches. "
116     L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, "
117     L"or by another program that is hogging a lot of memory. You can also try reducing the default "
118     L"cache sizes for all PCSX2 recompilers, found under Host Settings."
119     ));
120     }
121    
122    
123     void SysOutOfMemory_EmergencyResponse(uptr blocksize)
124     {
125     // An out of memory error occurred. All we can try to do in response is reset the various
126     // recompiler caches (which can sometimes total over 120megs, so it can be quite helpful).
127     // If the user is using interpreters, or if the memory allocation failure was on a very small
128     // allocation, then this code could fail; but that's fine. We're already trying harder than
129     // 99.995% of all programs ever written. -- air
130    
131     if (Cpu)
132     {
133     Cpu->SetCacheReserve( (Cpu->GetCacheReserve() * 2) / 3 );
134     Cpu->Reset();
135     }
136    
137     if (CpuVU0)
138     {
139     CpuVU0->SetCacheReserve( (CpuVU0->GetCacheReserve() * 2) / 3 );
140     CpuVU0->Reset();
141     }
142    
143     if (CpuVU1)
144     {
145     CpuVU1->SetCacheReserve( (CpuVU1->GetCacheReserve() * 2) / 3 );
146     CpuVU1->Reset();
147     }
148    
149     if (psxCpu)
150     {
151     psxCpu->SetCacheReserve( (psxCpu->GetCacheReserve() * 2) / 3 );
152     psxCpu->Reset();
153     }
154     }
155    
156    
157     #if _MSC_VER
158     # include "svnrev.h"
159     #endif
160    
161     const Pcsx2Config EmuConfig;
162    
163     // Provides an accessor for quick modification of GS options. All GS options are allowed to be
164     // changed "on the fly" by the *main/gui thread only*.
165     Pcsx2Config::GSOptions& SetGSConfig()
166     {
167     //DbgCon.WriteLn( "Direct modification of EmuConfig.GS detected" );
168     AffinityAssert_AllowFrom_MainUI();
169     return const_cast<Pcsx2Config::GSOptions&>(EmuConfig.GS);
170     }
171    
172     // Provides an accessor for quick modification of Recompiler options.
173     // Used by loadGameSettings() to set clamp modes via database at game startup.
174     Pcsx2Config::RecompilerOptions& SetRecompilerConfig()
175     {
176     //DbgCon.WriteLn( "Direct modification of EmuConfig.Gamefixes detected" );
177     AffinityAssert_AllowFrom_MainUI();
178     return const_cast<Pcsx2Config::RecompilerOptions&>(EmuConfig.Cpu.Recompiler);
179     }
180    
181     // Provides an accessor for quick modification of Gamefix options.
182     // Used by loadGameSettings() to set gamefixes via database at game startup.
183     Pcsx2Config::GamefixOptions& SetGameFixConfig()
184     {
185     //DbgCon.WriteLn( "Direct modification of EmuConfig.Gamefixes detected" );
186     AffinityAssert_AllowFrom_MainUI();
187     return const_cast<Pcsx2Config::GamefixOptions&>(EmuConfig.Gamefixes);
188     }
189    
190     TraceLogFilters& SetTraceConfig()
191     {
192     //DbgCon.WriteLn( "Direct modification of EmuConfig.TraceLog detected" );
193     AffinityAssert_AllowFrom_MainUI();
194     return const_cast<TraceLogFilters&>(EmuConfig.Trace);
195     }
196    
197    
198     // This function should be called once during program execution.
199     void SysLogMachineCaps()
200     {
201 william 290 Console.WriteLn( Color_StrongGreen, "PCSX2 %s - compiled on " __DATE__, PCSX2_FULL_VERSION());
202 william 283
203     Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion);
204     Console.Newline();
205    
206     Console.WriteLn( Color_StrongBlack, "Host Machine Init:" );
207    
208     Console.Indent().WriteLn(
209     L"Operating System = %s\n"
210     L"Physical RAM = %u MB",
211    
212     GetOSVersionString().c_str(),
213     (u32)(GetPhysicalMemory() / _1mb)
214     );
215    
216     u32 speed = x86caps.CalculateMHz();
217    
218     Console.Indent().WriteLn(
219     L"CPU name = %s\n"
220     L"Vendor/Model = %s (stepping %02X)\n"
221     L"CPU speed = %u.%03u ghz (%u logical thread%s)\n"
222     L"x86PType = %s\n"
223     L"x86Flags = %08x %08x\n"
224     L"x86EFlags = %08x",
225     fromUTF8( x86caps.FamilyName ).Trim().Trim(false).c_str(),
226     fromUTF8( x86caps.VendorName ).c_str(), x86caps.StepID,
227     speed / 1000, speed % 1000,
228     x86caps.LogicalCores, (x86caps.LogicalCores==1) ? L"" : L"s",
229     x86caps.GetTypeName().c_str(),
230     x86caps.Flags, x86caps.Flags2,
231     x86caps.EFlags
232     );
233    
234     Console.Newline();
235    
236     wxArrayString features[2]; // 2 lines, for readability!
237    
238     if( x86caps.hasMultimediaExtensions ) features[0].Add( L"MMX" );
239     if( x86caps.hasStreamingSIMDExtensions ) features[0].Add( L"SSE" );
240     if( x86caps.hasStreamingSIMD2Extensions ) features[0].Add( L"SSE2" );
241     if( x86caps.hasStreamingSIMD3Extensions ) features[0].Add( L"SSE3" );
242     if( x86caps.hasSupplementalStreamingSIMD3Extensions ) features[0].Add( L"SSSE3" );
243     if( x86caps.hasStreamingSIMD4Extensions ) features[0].Add( L"SSE4.1" );
244     if( x86caps.hasStreamingSIMD4Extensions2 ) features[0].Add( L"SSE4.2" );
245 william 401 if( x86caps.hasAVX ) features[0].Add( L"AVX" );
246     if( x86caps.hasFMA) features[0].Add( L"FMA" );
247 william 283
248     if( x86caps.hasMultimediaExtensionsExt ) features[1].Add( L"MMX2 " );
249     if( x86caps.has3DNOWInstructionExtensions ) features[1].Add( L"3DNOW " );
250     if( x86caps.has3DNOWInstructionExtensionsExt ) features[1].Add( L"3DNOW2" );
251     if( x86caps.hasStreamingSIMD4ExtensionsA ) features[1].Add( L"SSE4a " );
252    
253     const wxString result[2] =
254     {
255     JoinString( features[0], L".. " ),
256     JoinString( features[1], L".. " )
257     };
258    
259     Console.WriteLn( Color_StrongBlack, L"x86 Features Detected:" );
260     Console.Indent().WriteLn( result[0] + (result[1].IsEmpty() ? L"" : (L"\n" + result[1])) );
261     Console.Newline();
262     }
263    
264     template< typename CpuType >
265     class CpuInitializer
266     {
267     public:
268     ScopedPtr<CpuType> MyCpu;
269     ScopedExcept ExThrown;
270    
271     CpuInitializer();
272     virtual ~CpuInitializer() throw();
273    
274     bool IsAvailable() const
275     {
276     return !!MyCpu;
277     }
278    
279     CpuType* GetPtr() { return MyCpu.GetPtr(); }
280     const CpuType* GetPtr() const { return MyCpu.GetPtr(); }
281    
282     operator CpuType*() { return GetPtr(); }
283     operator const CpuType*() const { return GetPtr(); }
284     };
285    
286     // --------------------------------------------------------------------------------------
287     // CpuInitializer Template
288     // --------------------------------------------------------------------------------------
289     // Helper for initializing various PCSX2 CPU providers, and handing errors and cleanup.
290     //
291     template< typename CpuType >
292     CpuInitializer< CpuType >::CpuInitializer()
293     {
294     try {
295     MyCpu = new CpuType();
296     MyCpu->Reserve();
297     }
298     catch( Exception::RuntimeError& ex )
299     {
300     Console.Error( L"CPU provider error:\n\t" + ex.FormatDiagnosticMessage() );
301     MyCpu = NULL;
302     ExThrown = ex.Clone();
303     }
304     catch( std::runtime_error& ex )
305     {
306     Console.Error( L"CPU provider error (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
307     MyCpu = NULL;
308     ExThrown = new Exception::RuntimeError(ex);
309     }
310     }
311    
312     template< typename CpuType >
313     CpuInitializer< CpuType >::~CpuInitializer() throw()
314     {
315     if (MyCpu)
316     MyCpu->Shutdown();
317     }
318    
319     // --------------------------------------------------------------------------------------
320     // CpuInitializerSet
321     // --------------------------------------------------------------------------------------
322     class CpuInitializerSet
323     {
324     public:
325     // Note: Allocate sVU first -- it's the most picky.
326    
327     CpuInitializer<recSuperVU0> superVU0;
328     CpuInitializer<recSuperVU1> superVU1;
329    
330     CpuInitializer<recMicroVU0> microVU0;
331     CpuInitializer<recMicroVU1> microVU1;
332    
333     CpuInitializer<InterpVU0> interpVU0;
334     CpuInitializer<InterpVU1> interpVU1;
335    
336     public:
337     CpuInitializerSet() {}
338     virtual ~CpuInitializerSet() throw() {}
339     };
340    
341    
342     // returns the translated error message for the Virtual Machine failing to allocate!
343     static wxString GetMemoryErrorVM()
344     {
345     return pxE( "!Notice:EmuCore::MemoryForVM",
346     L"PCSX2 is unable to allocate memory needed for the PS2 virtual machine. "
347     L"Close out some memory hogging background tasks and try again."
348     );
349     }
350    
351     // --------------------------------------------------------------------------------------
352     // SysReserveVM (implementations)
353     // --------------------------------------------------------------------------------------
354     SysMainMemory::SysMainMemory()
355     {
356     }
357    
358     SysMainMemory::~SysMainMemory() throw()
359     {
360     ReleaseAll();
361     }
362    
363     void SysMainMemory::ReserveAll()
364     {
365     pxInstallSignalHandler();
366    
367     DevCon.WriteLn( Color_StrongBlue, "Mapping host memory for virtual systems..." );
368     ConsoleIndentScope indent(1);
369    
370     m_ee.Reserve();
371     m_iop.Reserve();
372     m_vu.Reserve();
373    
374     reserveNewVif(0);
375     reserveNewVif(1);
376     }
377    
378     void SysMainMemory::CommitAll()
379     {
380     vtlb_Core_Alloc();
381     if (m_ee.IsCommitted() && m_iop.IsCommitted() && m_vu.IsCommitted()) return;
382    
383     DevCon.WriteLn( Color_StrongBlue, "Allocating host memory for virtual systems..." );
384     ConsoleIndentScope indent(1);
385    
386     m_ee.Commit();
387     m_iop.Commit();
388     m_vu.Commit();
389     }
390    
391    
392     void SysMainMemory::ResetAll()
393     {
394     CommitAll();
395    
396     DevCon.WriteLn( Color_StrongBlue, "Resetting host memory for virtual systems..." );
397     ConsoleIndentScope indent(1);
398    
399     m_ee.Reset();
400     m_iop.Reset();
401     m_vu.Reset();
402 william 401
403 william 283 // Note: newVif is reset as part of other VIF structures.
404     }
405    
406     void SysMainMemory::DecommitAll()
407     {
408     if (!m_ee.IsCommitted() && !m_iop.IsCommitted() && !m_vu.IsCommitted()) return;
409    
410     Console.WriteLn( Color_Blue, "Decommitting host memory for virtual systems..." );
411     ConsoleIndentScope indent(1);
412    
413     m_ee.Decommit();
414     m_iop.Decommit();
415     m_vu.Decommit();
416    
417     closeNewVif(0);
418     closeNewVif(1);
419    
420     vtlb_Core_Free();
421     }
422    
423     void SysMainMemory::ReleaseAll()
424     {
425     DecommitAll();
426    
427     Console.WriteLn( Color_Blue, "Releasing host memory maps for virtual systems..." );
428     ConsoleIndentScope indent(1);
429    
430     vtlb_Core_Free(); // Just to be sure... (calling order could result in it getting missed during Decommit).
431    
432     releaseNewVif(0);
433     releaseNewVif(1);
434    
435     m_ee.Decommit();
436     m_iop.Decommit();
437     m_vu.Decommit();
438    
439     safe_delete(Source_PageFault);
440     }
441    
442    
443     // --------------------------------------------------------------------------------------
444     // SysCpuProviderPack (implementations)
445     // --------------------------------------------------------------------------------------
446     SysCpuProviderPack::SysCpuProviderPack()
447     {
448     Console.WriteLn( Color_StrongBlue, "Reserving memory for recompilers..." );
449     ConsoleIndentScope indent(1);
450    
451     CpuProviders = new CpuInitializerSet();
452    
453     try {
454     recCpu.Reserve();
455     }
456     catch( Exception::RuntimeError& ex )
457     {
458     m_RecExceptionEE = ex.Clone();
459     Console.Error( L"EE Recompiler Reservation Failed:\n" + ex.FormatDiagnosticMessage() );
460     recCpu.Shutdown();
461     }
462    
463     try {
464     psxRec.Reserve();
465     }
466     catch( Exception::RuntimeError& ex )
467     {
468     m_RecExceptionIOP = ex.Clone();
469     Console.Error( L"IOP Recompiler Reservation Failed:\n" + ex.FormatDiagnosticMessage() );
470     psxRec.Shutdown();
471     }
472    
473     // hmm! : VU0 and VU1 pre-allocations should do sVU and mVU separately? Sounds complicated. :(
474 william 401
475     if (newVifDynaRec)
476     {
477     dVifReserve(0);
478     dVifReserve(1);
479     }
480 william 283 }
481    
482     bool SysCpuProviderPack::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
483     bool SysCpuProviderPack::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
484     BaseException* SysCpuProviderPack::GetException_MicroVU0() const { return CpuProviders->microVU0.ExThrown; }
485     BaseException* SysCpuProviderPack::GetException_MicroVU1() const { return CpuProviders->microVU1.ExThrown; }
486    
487     bool SysCpuProviderPack::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
488     bool SysCpuProviderPack::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
489     BaseException* SysCpuProviderPack::GetException_SuperVU0() const { return CpuProviders->superVU0.ExThrown; }
490     BaseException* SysCpuProviderPack::GetException_SuperVU1() const { return CpuProviders->superVU1.ExThrown; }
491    
492    
493     void SysCpuProviderPack::CleanupMess() throw()
494     {
495     try
496     {
497     psxRec.Shutdown();
498     recCpu.Shutdown();
499 william 401
500     if (newVifDynaRec)
501     {
502     dVifRelease(0);
503     dVifRelease(1);
504     }
505 william 283 }
506     DESTRUCTOR_CATCHALL
507     }
508    
509     SysCpuProviderPack::~SysCpuProviderPack() throw()
510     {
511     CleanupMess();
512     }
513    
514     bool SysCpuProviderPack::HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const
515     {
516     return (recOpts.EnableEE && !IsRecAvailable_EE()) ||
517     (recOpts.EnableIOP && !IsRecAvailable_IOP()) ||
518     (recOpts.EnableVU0 && recOpts.UseMicroVU0 && !IsRecAvailable_MicroVU0()) ||
519     (recOpts.EnableVU1 && recOpts.UseMicroVU0 && !IsRecAvailable_MicroVU1()) ||
520     (recOpts.EnableVU0 && !recOpts.UseMicroVU0 && !IsRecAvailable_SuperVU0()) ||
521     (recOpts.EnableVU1 && !recOpts.UseMicroVU1 && !IsRecAvailable_SuperVU1());
522    
523     }
524    
525     BaseVUmicroCPU* CpuVU0 = NULL;
526     BaseVUmicroCPU* CpuVU1 = NULL;
527    
528     void SysCpuProviderPack::ApplyConfig() const
529     {
530     Cpu = CHECK_EEREC ? &recCpu : &intCpu;
531     psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
532    
533     CpuVU0 = CpuProviders->interpVU0;
534     CpuVU1 = CpuProviders->interpVU1;
535    
536     if( EmuConfig.Cpu.Recompiler.EnableVU0 )
537     CpuVU0 = EmuConfig.Cpu.Recompiler.UseMicroVU0 ? (BaseVUmicroCPU*)CpuProviders->microVU0 : (BaseVUmicroCPU*)CpuProviders->superVU0;
538    
539     if( EmuConfig.Cpu.Recompiler.EnableVU1 )
540     CpuVU1 = EmuConfig.Cpu.Recompiler.UseMicroVU1 ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->superVU1;
541     }
542    
543     // This is a semi-hacky function for convenience
544     BaseVUmicroCPU* SysCpuProviderPack::getVUprovider(int whichProvider, int vuIndex) const {
545     switch (whichProvider) {
546     case 0: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->interpVU1 : (BaseVUmicroCPU*)CpuProviders->interpVU0;
547     case 1: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->superVU1 : (BaseVUmicroCPU*)CpuProviders->superVU0;
548     case 2: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->microVU0;
549     }
550     return NULL;
551     }
552    
553     // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
554     // This can be called at any time outside the context of a Cpu->Execute() block without
555     // bad things happening (recompilers will slow down for a brief moment since rec code blocks
556     // are dumped).
557     // Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
558     void SysClearExecutionCache()
559     {
560     GetCpuProviders().ApplyConfig();
561    
562     Cpu->Reset();
563     psxCpu->Reset();
564    
565     // mVU's VU0 needs to be properly initialized for macro mode even if it's not used for micro mode!
566     if (CHECK_EEREC)
567     ((BaseVUmicroCPU*)GetCpuProviders().CpuProviders->microVU0)->Reset();
568    
569     CpuVU0->Reset();
570     CpuVU1->Reset();
571    
572 william 401 if (newVifDynaRec)
573     {
574     dVifReset(0);
575     dVifReset(1);
576     }
577 william 283 }
578    
579     // Maps a block of memory for use as a recompiled code buffer, and ensures that the
580     // allocation is below a certain memory address (specified in "bounds" parameter).
581     // The allocated block has code execution privileges.
582     // Returns NULL on allocation failure.
583     u8* SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
584     {
585     u8* Mem = (u8*)HostSys::Mmap( base, size );
586    
587     if( (Mem == NULL) || (bounds != 0 && (((uptr)Mem + size) > bounds)) )
588     {
589     if( base )
590     {
591     DbgCon.Warning( "First try failed allocating %s at address 0x%x", caller, base );
592    
593     // Let's try again at an OS-picked memory area, and then hope it meets needed
594     // boundschecking criteria below.
595     SafeSysMunmap( Mem, size );
596     Mem = (u8*)HostSys::Mmap( 0, size );
597     }
598    
599     if( (bounds != 0) && (((uptr)Mem + size) > bounds) )
600     {
601     DevCon.Warning( "Second try failed allocating %s, block ptr 0x%x does not meet required criteria.", caller, Mem );
602     SafeSysMunmap( Mem, size );
603    
604     // returns NULL, caller should throw an exception.
605     }
606     }
607     return Mem;
608     }
609    
610     // This function always returns a valid DiscID -- using the Sony serial when possible, and
611     // falling back on the CRC checksum of the ELF binary if the PS2 software being run is
612     // homebrew or some other serial-less item.
613     wxString SysGetDiscID()
614     {
615     if( !DiscSerial.IsEmpty() ) return DiscSerial;
616    
617     if( !ElfCRC )
618     {
619     // FIXME: system is currently running the BIOS, so it should return a serial based on
620     // the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS
621     // region and revision).
622    
623     return wxEmptyString;
624     }
625    
626     return pxsFmt( L"%08x", ElfCRC );
627     }

  ViewVC Help
Powered by ViewVC 1.1.22