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

Contents of /branch/r3113_0.9.7_beta_reference/pcsx2/gui/AppInit.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: 23244 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 "IniInterface.h"
18 #include "MainFrame.h"
19 #include "ConsoleLogger.h"
20 #include "MSWstuff.h"
21
22 #include "DebugTools/Debug.h"
23 #include "Dialogs/ModalPopups.h"
24
25 #include <wx/cmdline.h>
26 #include <wx/intl.h>
27 #include <wx/stdpaths.h>
28
29 static bool m_ForceWizard = false;
30
31 static void CpuCheckSSE2()
32 {
33 if( x86caps.hasStreamingSIMD2Extensions ) return;
34
35 // Only check once per process session:
36 static bool checked = false;
37 if( checked ) return;
38 checked = true;
39
40 wxDialogWithHelpers exconf( NULL, _("PCSX2 - SSE2 Recommended"), wxVERTICAL );
41
42 exconf += exconf.Heading( pxE( ".Error:Startup:NoSSE2",
43 L"Warning: Your computer does not support SSE2, which is required by many PCSX2 recompilers and plugins. "
44 L"Your options will be limited and emulation will be *very* slow." )
45 );
46
47 pxIssueConfirmation( exconf, MsgButtons().OK(), L"Error:Startup:NoSSE2" );
48
49 // Auto-disable anything that needs SSE2:
50
51 g_Conf->EmuOptions.Cpu.Recompiler.EnableEE = false;
52 g_Conf->EmuOptions.Cpu.Recompiler.EnableVU0 = false;
53 g_Conf->EmuOptions.Cpu.Recompiler.EnableVU1 = false;
54 }
55
56 void Pcsx2App::WipeUserModeSettings()
57 {
58 wxDirName usrlocaldir( wxStandardPaths::Get().GetUserLocalDataDir() );
59 if( !usrlocaldir.Exists() ) return;
60
61 wxString cwd( Path::Normalize( wxGetCwd() ) );
62 u32 hashres = HashTools::Hash( (char*)cwd.c_str(), cwd.Length() );
63
64 wxFileName usermodefile( FilenameDefs::GetUsermodeConfig() );
65 usermodefile.SetPath( usrlocaldir.ToString() );
66 ScopedPtr<wxFileConfig> conf_usermode( OpenFileConfig( usermodefile.GetFullPath() ) );
67
68 wxString groupname( wxsFormat( L"CWD.%08x", hashres ) );
69 Console.WriteLn( "(UserModeSettings) Removing entry:" );
70 Console.Indent().WriteLn( L"Path: %s\nHash:%s", cwd.c_str(), groupname.c_str() );
71 conf_usermode->DeleteGroup( groupname );
72 }
73
74 // User mode settings can't be stored in the CWD for two reasons:
75 // (a) the user may not have permission to do so (most obvious)
76 // (b) it would result in sloppy usermode.ini found all over a hard drive if people runs the
77 // exe from many locations (ugh).
78 //
79 // So better to use the registry on Win32 and a "default ini location" config file under Linux,
80 // and store the usermode settings for the CWD based on the CWD's hash.
81 //
82 void Pcsx2App::ReadUserModeSettings()
83 {
84 wxDirName usrlocaldir( wxStandardPaths::Get().GetUserLocalDataDir() );
85 if( !usrlocaldir.Exists() )
86 {
87 Console.WriteLn( L"Creating UserLocalData folder: " + usrlocaldir.ToString() );
88 usrlocaldir.Mkdir();
89 }
90
91 wxString cwd( Path::Normalize( wxGetCwd() ) );
92 u32 hashres = HashTools::Hash( (char*)cwd.c_str(), cwd.Length() );
93
94 wxFileName usermodefile( FilenameDefs::GetUsermodeConfig() );
95 usermodefile.SetPath( usrlocaldir.ToString() );
96 ScopedPtr<wxFileConfig> conf_usermode( OpenFileConfig( usermodefile.GetFullPath() ) );
97
98 wxString groupname( wxsFormat( L"CWD.%08x", hashres ) );
99
100 if (IOP_ENABLE_SIF_HACK == 1)
101 {
102 wxDialogWithHelpers hackedVersion( NULL, _("It will devour your young! - PCSX2 Shub-Niggurath edition"), wxVERTICAL );
103
104 hackedVersion.SetSizer( new wxBoxSizer( wxVERTICAL ) );
105 hackedVersion += new pxStaticText( &hackedVersion,
106 L"NOTICE!! This is a version of Pcsx2 with hacks enabled meant for developers only. "
107 L"It will likely crash on all games, devour your young, and make you an object of shame and disgrace among your family and friends. "
108 L"Do not report any bugs with this version if you received this popup. \n\nYou have been warned. ", wxALIGN_CENTER
109 );
110
111 hackedVersion += new wxButton( &hackedVersion, wxID_OK ) | pxSizerFlags::StdCenter();
112 hackedVersion.ShowModal();
113 }
114
115 bool hasGroup = conf_usermode->HasGroup( groupname );
116 bool forceWiz = m_ForceWizard || !hasGroup;
117
118 if( !forceWiz )
119 {
120 conf_usermode->SetPath( groupname );
121 forceWiz = !conf_usermode->HasEntry( L"DocumentsFolderMode" );
122 conf_usermode->SetPath( L".." );
123 }
124
125 if( forceWiz )
126 {
127 //// Beta Warning!
128
129 //if( !hasGroup )
130 //{
131 // wxDialogWithHelpers beta( NULL, _("PCSX2 0.9.7 Beta"), wxVERTICAL );
132
133 // beta.SetSizer( new wxBoxSizer( wxVERTICAL ) );
134 // beta += new pxStaticText( &beta,
135 // L"This is a *Beta* build of PCSX2 0.9.7. We are in the middle of major rewrites of the "
136 // L"user interface, and some parts of the program have *NOT* been implemented yet. Options will be missing. "
137 // L"Some things may crash or hang without warning.", wxALIGN_CENTER
138 // );
139 //
140 // beta += new wxButton( &beta, wxID_OK ) | pxSizerFlags::StdCenter();
141 // beta.ShowModal();
142 //}
143
144 // Beta Warning!
145 #if 0
146 if( !hasGroup )
147 {
148 //wxDialogWithHelpers beta( NULL, _fmt("Welcome to %s %u.%u.%u (r%u)", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo, SVN_REV ));
149 wxDialogWithHelpers beta( NULL, _fmt("Welcome to %s (%s)", pxGetAppName().c_str(), wxPCSX2_FULL_VERSION() ));
150 beta.SetMinWidth(480);
151
152 beta += beta.Heading(
153 L"PCSX2 0.9.7 is a work-in-progress. We are in the middle of major rewrites of the user interface, and some parts "
154 L"of the program have *NOT* been re-implemented yet. Options will be missing or disabled. Horrible crashes might be present. Enjoy!"
155 );
156 beta += StdPadding*2;
157 beta += new wxButton( &beta, wxID_OK ) | StdCenter();
158 beta.ShowModal();
159 }
160 #endif
161
162 // first time startup, so give the user the choice of user mode:
163 FirstTimeWizard wiz( NULL );
164 if( !wiz.RunWizard( wiz.GetUsermodePage() ) )
165 throw Exception::StartupAborted( L"Startup aborted: User canceled FirstTime Wizard." );
166
167 // Save user's new settings
168 IniSaver saver( *conf_usermode );
169 g_Conf->LoadSaveUserMode( saver, groupname );
170 AppConfig_OnChangedSettingsFolder( true );
171 AppSaveSettings();
172 }
173 else
174 {
175 // usermode.ini exists and is populated with valid data -- assume User Documents mode,
176 // unless the ini explicitly specifies otherwise.
177
178 DocsFolderMode = DocsFolder_User;
179
180 IniLoader loader( *conf_usermode );
181 g_Conf->LoadSaveUserMode( loader, groupname );
182
183 if( !wxFile::Exists( GetSettingsFilename() ) )
184 {
185 // user wiped their pcsx2.ini -- needs a reconfiguration via wizard!
186 // (we skip the first page since it's a usermode.ini thing)
187
188 // Fixme : Skipping the first page is a bad idea, as it does a lot of file / directory checks on hitting Apply.
189 // If anything is missing, the first page prompts to fix it.
190 // If we skip this check, it's very likely that actions like creating Memory Cards will fail.
191 FirstTimeWizard wiz( NULL );
192 if( !wiz.RunWizard( /*wiz.GetPostUsermodePage()*/ wiz.GetUsermodePage() ) )
193 throw Exception::StartupAborted( L"Startup aborted: User canceled Configuration Wizard." );
194
195 // Save user's new settings
196 IniSaver saver( *conf_usermode );
197 g_Conf->LoadSaveUserMode( saver, groupname );
198 AppConfig_OnChangedSettingsFolder( true );
199 AppSaveSettings();
200 }
201 }
202
203 // force unload plugins loaded by the wizard. If we don't do this the recompilers might
204 // fail to allocate the memory they need to function.
205 UnloadPlugins();
206 }
207
208 void Pcsx2App::DetectCpuAndUserMode()
209 {
210 cpudetectInit();
211
212 if( !x86caps.hasMultimediaExtensions )
213 {
214 // Note: due to memcpy_fast, we need minimum MMX even for interpreters. This will
215 // hopefully change later once we have a dynamically recompiled memcpy.
216 throw Exception::HardwareDeficiency(L"MMX Extensions not available.", _("PCSX2 requires cpu with MMX instruction to run."));
217 }
218
219 ReadUserModeSettings();
220 AppConfig_OnChangedSettingsFolder();
221
222 PostAppMethod( &Pcsx2App::OpenMainFrame );
223 PostAppMethod( &Pcsx2App::OpenProgramLog );
224 PostAppMethod( &Pcsx2App::AllocateCoreStuffs );
225 }
226
227 void Pcsx2App::OpenMainFrame()
228 {
229 if( GetMainFramePtr() != NULL ) return;
230
231 MainEmuFrame* mainFrame = new MainEmuFrame( NULL, L"PCSX2" );
232 m_id_MainFrame = mainFrame->GetId();
233
234 if( wxWindow* deleteme = GetProgramLog() )
235 {
236 deleteme->Destroy();
237 g_Conf->ProgLogBox.Visible = true;
238 m_id_ProgramLogBox = wxID_ANY;
239 PostIdleAppMethod( &Pcsx2App::OpenProgramLog );
240 }
241
242 SetTopWindow( mainFrame ); // not really needed...
243 SetExitOnFrameDelete( true ); // but being explicit doesn't hurt...
244 mainFrame->Show();
245 }
246
247 void Pcsx2App::OpenProgramLog()
248 {
249 if( GetProgramLog() != NULL ) return;
250 wxWindow* m_current_focus = wxGetActiveWindow();
251 m_id_ProgramLogBox = (new ConsoleLogFrame( GetMainFramePtr(), L"PCSX2 Program Log", g_Conf->ProgLogBox ))->GetId();
252 EnableAllLogging();
253
254 if( m_current_focus ) m_current_focus->SetFocus();
255 }
256
257 void Pcsx2App::AllocateCoreStuffs()
258 {
259 CpuCheckSSE2();
260 SysLogMachineCaps();
261 AppApplySettings();
262
263 if( !m_CoreAllocs )
264 {
265 m_CoreAllocs = new SysCoreAllocations();
266
267 if( m_CoreAllocs->HadSomeFailures( g_Conf->EmuOptions.Cpu.Recompiler ) )
268 {
269 // HadSomeFailures only returns 'true' if an *enabled* cpu type fails to init. If
270 // the user already has all interps configured, for example, then no point in
271 // popping up this dialog.
272
273 wxDialogWithHelpers exconf( NULL, _("PCSX2 Recompiler Error(s)"), wxVERTICAL );
274
275 exconf += 12;
276 exconf += exconf.Heading( pxE( ".Error:RecompilerInit",
277 L"Warning: Some of the configured PS2 recompilers failed to initialize and will not be available for this session:\n" )
278 );
279
280 wxTextCtrl* scrollableTextArea = new wxTextCtrl(
281 &exconf, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
282 wxTE_READONLY | wxTE_MULTILINE | wxTE_WORDWRAP
283 );
284
285 exconf += scrollableTextArea | pxSizerFlags::StdExpand();
286
287 if( !m_CoreAllocs->IsRecAvailable_EE() )
288 {
289 scrollableTextArea->AppendText( L"* R5900 (EE)\n\n" );
290
291 g_Conf->EmuOptions.Recompiler.EnableEE = false;
292 }
293
294 if( !m_CoreAllocs->IsRecAvailable_IOP() )
295 {
296 scrollableTextArea->AppendText( L"* R3000A (IOP)\n\n" );
297 g_Conf->EmuOptions.Recompiler.EnableIOP = false;
298 }
299
300 if( !m_CoreAllocs->IsRecAvailable_MicroVU0() )
301 {
302 scrollableTextArea->AppendText( L"* microVU0\n\n" );
303 g_Conf->EmuOptions.Recompiler.UseMicroVU0 = false;
304 g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && m_CoreAllocs->IsRecAvailable_SuperVU0();
305 }
306
307 if( !m_CoreAllocs->IsRecAvailable_MicroVU1() )
308 {
309 scrollableTextArea->AppendText( L"* microVU1\n\n" );
310 g_Conf->EmuOptions.Recompiler.UseMicroVU1 = false;
311 g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && m_CoreAllocs->IsRecAvailable_SuperVU1();
312 }
313
314 if( !m_CoreAllocs->IsRecAvailable_SuperVU0() )
315 {
316 scrollableTextArea->AppendText( L"* SuperVU0\n\n" );
317 g_Conf->EmuOptions.Recompiler.UseMicroVU0 = m_CoreAllocs->IsRecAvailable_MicroVU0();
318 g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && g_Conf->EmuOptions.Recompiler.UseMicroVU0;
319 }
320
321 if( !m_CoreAllocs->IsRecAvailable_SuperVU1() )
322 {
323 scrollableTextArea->AppendText( L"* SuperVU1\n\n" );
324 g_Conf->EmuOptions.Recompiler.UseMicroVU1 = m_CoreAllocs->IsRecAvailable_MicroVU1();
325 g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && g_Conf->EmuOptions.Recompiler.UseMicroVU1;
326 }
327
328 exconf += new ModalButtonPanel( &exconf, MsgButtons().OK() ) | pxSizerFlags::StdCenter();
329
330 exconf.ShowModal();
331
332 // Failures can be SSE-related OR memory related. Should do per-cpu error reports instead...
333
334 /*message += pxE( ".Popup Error:EmuCore:MemoryForRecs",
335 L"These errors are the result of memory allocation failures (see the program log for details). "
336 L"Closing out some memory hogging background tasks may resolve this error.\n\n"
337 L"These recompilers have been disabled and interpreters will be used in their place. "
338 L"Interpreters can be very slow, so don't get too excited. Press OK to continue or CANCEL to close PCSX2."
339 );*/
340
341 //if( !Msgbox::OkCancel( message, _("PCSX2 Initialization Error"), wxICON_ERROR ) )
342 // return false;
343 }
344 }
345
346 LoadPluginsPassive();
347 }
348
349
350 void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
351 {
352 parser.SetLogo( (wxString)L" >> PCSX2 -- A Playstation2 Emulator for the PC <<\n\n" +
353 _("All options are for the current session only and will not be saved.\n")
354 );
355
356 parser.AddParam( _("IsoFile"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL );
357
358 parser.AddSwitch( L"h", L"help", _("displays this list of command line options"), wxCMD_LINE_OPTION_HELP );
359
360 parser.AddSwitch( wxEmptyString,L"nogui", _("disables display of the gui while running games") );
361 parser.AddSwitch( wxEmptyString,L"skipbios",_("skips standard BIOS splash screens and software checks") );
362 parser.AddOption( wxEmptyString,L"elf", _("executes an ELF image"), wxCMD_LINE_VAL_STRING );
363 parser.AddSwitch( wxEmptyString,L"nodisc", _("boots an empty dvd tray; use to enter the PS2 system menu") );
364 parser.AddSwitch( wxEmptyString,L"usecd", _("boots from the configured CDVD plugin (ignores IsoFile parameter)") );
365
366 parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING );
367 parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use [not implemented]"), wxCMD_LINE_VAL_STRING );
368
369 parser.AddSwitch( wxEmptyString,L"forcewiz",_("Forces PCSX2 to start the First-time Wizard") );
370
371 const PluginInfo* pi = tbl_PluginInfo; do {
372 parser.AddOption( wxEmptyString, pi->GetShortname().Lower(),
373 wxsFormat( _("specify the file to use as the %s plugin"), pi->GetShortname().c_str() )
374 );
375 } while( ++pi, pi->shortname != NULL );
376
377 parser.SetSwitchChars( L"-" );
378 }
379
380 bool Pcsx2App::OnCmdLineError( wxCmdLineParser& parser )
381 {
382 wxApp::OnCmdLineError( parser );
383 return false;
384 }
385
386 bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
387 {
388 if( parser.GetParamCount() >= 1 )
389 {
390 // [TODO] : Unnamed parameter is taken as an "autorun" option for a cdvd/iso.
391 parser.GetParam( 0 );
392 }
393
394 // Suppress wxWidgets automatic options parsing since none of them pertain to PCSX2 needs.
395 //wxApp::OnCmdLineParsed( parser );
396
397 //bool yay = parser.Found(L"nogui");
398 m_ForceWizard = parser.Found( L"forcewiz" );
399
400 const PluginInfo* pi = tbl_PluginInfo; do
401 {
402 wxString dest;
403 if( !parser.Found( pi->GetShortname().Lower(), &dest ) ) continue;
404
405 OverrideOptions.Filenames.Plugins[pi->id] = dest;
406
407 if( wxFileExists( dest ) )
408 Console.Warning( pi->GetShortname() + L" override: " + dest );
409 else
410 {
411 bool result = Msgbox::OkCancel(
412 wxsFormat( _("Plugin Override Error! Specified %s plugin does not exist:\n\n"), pi->GetShortname().c_str() ) +
413 dest +
414 _("Press OK to use the default configured plugin, or Cancel to close."),
415 _("Plugin Override Error - PCSX2"), wxICON_ERROR
416 );
417
418 if( !result ) return false;
419 }
420 } while( ++pi, pi->shortname != NULL );
421
422 parser.Found( L"cfgpath", &OverrideOptions.SettingsFolder );
423
424 return true;
425 }
426
427 typedef void (wxEvtHandler::*pxInvokeAppMethodEventFunction)(Pcsx2AppMethodEvent&);
428 typedef void (wxEvtHandler::*pxStuckThreadEventHandler)(pxMessageBoxEvent&);
429
430 bool Pcsx2App::OnInit()
431 {
432 #define pxAppMethodEventHandler(func) \
433 (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxInvokeAppMethodEventFunction, &func )
434
435 pxDoAssert = AppDoAssert;
436
437 g_Conf = new AppConfig();
438 EnableAllLogging();
439
440 wxInitAllImageHandlers();
441 if( !_parent::OnInit() ) return false;
442
443 m_StdoutRedirHandle = NewPipeRedir(stdout);
444 m_StderrRedirHandle = NewPipeRedir(stderr);
445 wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
446
447 Connect( pxID_PadHandler_Keydown, wxEVT_KEY_DOWN, wxKeyEventHandler (Pcsx2App::OnEmuKeyDown) );
448
449 Connect( wxEVT_DESTROY, wxWindowDestroyEventHandler (Pcsx2App::OnDestroyWindow) );
450
451 // User/Admin Mode Dual Setup:
452 // PCSX2 now supports two fundamental modes of operation. The default is Classic mode,
453 // which uses the Current Working Directory (CWD) for all user data files, and requires
454 // Admin access on Vista (and some Linux as well). The second mode is the Vista-
455 // compatible \documents folder usage. The mode is determined by the presence and
456 // contents of a usermode.ini file in the CWD. If the ini file is missing, we assume
457 // the user is setting up a classic install. If the ini is present, we read the value of
458 // the UserMode and SettingsPath vars.
459 //
460 // Conveniently this dual mode setup applies equally well to most modern Linux distros.
461
462 try
463 {
464 InitDefaultGlobalAccelerators();
465 delete wxLog::SetActiveTarget( new pxLogConsole() );
466
467 m_RecentIsoList = new RecentIsoList();
468
469 #ifdef __WXMSW__
470 pxDwm_Load();
471 #endif
472
473 SysExecutorThread.Start();
474 DetectCpuAndUserMode();
475 }
476 // ----------------------------------------------------------------------------
477 catch( Exception::StartupAborted& ex ) // user-aborted, no popups needed.
478 {
479 Console.Warning( ex.FormatDiagnosticMessage() );
480 CleanupOnExit();
481 return false;
482 }
483 catch( Exception::HardwareDeficiency& ex )
484 {
485 Msgbox::Alert( ex.FormatDisplayMessage() + _("\n\nPress OK to close PCSX2."), _("PCSX2 Error: Hardware Deficiency") );
486 CleanupOnExit();
487 return false;
488 }
489 // ----------------------------------------------------------------------------
490 // Failures on the core initialization procedure (typically OutOfMemory errors) are bad,
491 // since it means the emulator is completely non-functional. Let's pop up an error and
492 // exit gracefully-ish.
493 //
494 catch( Exception::RuntimeError& ex )
495 {
496 Console.Error( ex.FormatDiagnosticMessage() );
497 Msgbox::Alert( ex.FormatDisplayMessage() + _("\n\nPress OK to close PCSX2."),
498 _("PCSX2 Critical Error"), wxICON_ERROR );
499 CleanupOnExit();
500 return false;
501 }
502 return true;
503 }
504
505 // This cleanup procedure can only be called when the App message pump is still active.
506 // OnExit() must use CleanupOnExit instead.
507 void Pcsx2App::CleanupRestartable()
508 {
509 AffinityAssert_AllowFrom_MainUI();
510
511 ShutdownPlugins();
512 SysExecutorThread.ShutdownQueue();
513
514 //PingDispatcher( "Cleanup" );
515 //DeletionDispatcher();
516 IdleEventDispatcher( L"Cleanup" );
517
518 if( g_Conf )
519 AppSaveSettings();
520 }
521
522 // This cleanup handler can be called from OnExit (it doesn't need a running message pump),
523 // but should not be called from the App destructor. It's needed because wxWidgets doesn't
524 // always call OnExit(), so I had to make CleanupRestartable, and then encapsulate it here
525 // to be friendly to the OnExit scenario (no message pump).
526 void Pcsx2App::CleanupOnExit()
527 {
528 AffinityAssert_AllowFrom_MainUI();
529
530 try
531 {
532 CleanupRestartable();
533 CleanupResources();
534 }
535 catch( Exception::CancelEvent& ) { throw; }
536 catch( Exception::RuntimeError& ex )
537 {
538 // Handle runtime errors gracefully during shutdown. Mostly these are things
539 // that we just don't care about by now, and just want to "get 'er done!" so
540 // we can exit the app. ;)
541
542 Console.Error( L"Runtime exception handled during CleanupOnExit:\n" );
543 Console.Indent().Error( ex.FormatDiagnosticMessage() );
544 }
545
546 #ifdef __WXMSW__
547 pxDwm_Unload();
548 #endif
549
550 // Notice: deleting the plugin manager (unloading plugins) here causes Lilypad to crash,
551 // likely due to some pending message in the queue that references lilypad procs.
552 // We don't need to unload plugins anyway tho -- shutdown is plenty safe enough for
553 // closing out all the windows. So just leave it be and let the plugins get unloaded
554 // during the wxApp destructor. -- air
555
556 // FIXME: performing a wxYield() here may fix that problem. -- air
557
558 pxDoAssert = pxAssertImpl_LogIt;
559 Console_SetActiveHandler( ConsoleWriter_Stdout );
560 }
561
562 void Pcsx2App::CleanupResources()
563 {
564 delete wxConfigBase::Set( NULL );
565
566 while( wxGetLocale() != NULL )
567 delete wxGetLocale();
568
569 m_Resources = NULL;
570 }
571
572 int Pcsx2App::OnExit()
573 {
574 CleanupOnExit();
575
576 return wxApp::OnExit();
577 }
578
579 void Pcsx2App::OnDestroyWindow( wxWindowDestroyEvent& evt )
580 {
581 // Precautions:
582 // * Whenever windows are destroyed, make sure to check if it matches our "active"
583 // console logger. If so, we need to disable logging to the console window, or else
584 // it'll crash. (this is because the console log system uses a cached window handle
585 // instead of looking the window up via it's ID -- fast but potentially unsafe).
586 //
587 // * The virtual machine's plugins usually depend on the GS window handle being valid,
588 // so if the GS window is the one being shut down then we need to make sure to close
589 // out the Corethread before it vanishes completely from existence.
590
591
592 OnProgramLogClosed( evt.GetId() );
593 OnGsFrameClosed( evt.GetId() );
594 evt.Skip();
595 }
596
597 // --------------------------------------------------------------------------------------
598 // SysEventHandler
599 // --------------------------------------------------------------------------------------
600 class SysEvtHandler : public pxEvtHandler
601 {
602 public:
603 wxString GetEvtHandlerName() const { return L"SysExecutor"; }
604
605 protected:
606 // When the SysExec message queue is finally empty, we should check the state of
607 // the menus and make sure they're all consistent to the current emulation states.
608 void _DoIdle()
609 {
610 UI_UpdateSysControls();
611 }
612 };
613
614
615 Pcsx2App::Pcsx2App()
616 : SysExecutorThread( new SysEvtHandler() )
617 {
618 m_PendingSaves = 0;
619 m_ScheduledTermination = false;
620
621 m_id_MainFrame = wxID_ANY;
622 m_id_GsFrame = wxID_ANY;
623 m_id_ProgramLogBox = wxID_ANY;
624
625 SetAppName( L"pcsx2" );
626 BuildCommandHash();
627 }
628
629 Pcsx2App::~Pcsx2App()
630 {
631 pxDoAssert = pxAssertImpl_LogIt;
632 }
633
634 void Pcsx2App::CleanUp()
635 {
636 CleanupResources();
637 m_Resources = NULL;
638 m_RecentIsoList = NULL;
639
640 DisableDiskLogging();
641
642 if( emuLog != NULL )
643 {
644 fclose( emuLog );
645 emuLog = NULL;
646 }
647
648 _parent::CleanUp();
649 }
650
651
652 // ------------------------------------------------------------------------------------------
653 // Using the MSVCRT to track memory leaks:
654 // ------------------------------------------------------------------------------------------
655 // When exiting PCSX2 normally, the CRT will make a list of all memory that's leaked. The
656 // number inside {} can be pasted into the line below to cause MSVC to breakpoint on that
657 // allocation at the time it's made. And then using a stacktrace you can figure out what
658 // leaked! :D
659 //
660 // Limitations: Unfortunately, wxWidgets gui uses a lot of heap allocations while handling
661 // messages, and so any mouse movements will pretty much screw up the leak value. So to use
662 // this feature you need to execute pcsx in no-gui mode, and then not move the mouse or use
663 // the keyboard until you get to the leak. >_<
664 //
665 // (but this tool is still better than nothing!)
666
667 #ifdef PCSX2_DEBUG
668 struct CrtDebugBreak
669 {
670 CrtDebugBreak( int spot )
671 {
672 #ifdef __WXMSW__
673 _CrtSetBreakAlloc( spot );
674 #endif
675 }
676 };
677
678 //CrtDebugBreak breakAt( 8564 );
679
680 #endif

  ViewVC Help
Powered by ViewVC 1.1.22