Some missing svn:eol-style=native props. It's like they vanish into thin air these things.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2981 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-05-11 11:44:33 +00:00
parent 02038a7dc1
commit 338cc07ce9
8 changed files with 1649 additions and 1649 deletions

View File

@ -1,52 +1,52 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "AppCommon.h"
// --------------------------------------------------------------------------------------
// AppPluginManager
// --------------------------------------------------------------------------------------
// This extension of PluginManager provides event listener sources for plugins -- loading,
// unloading, open, close, shutdown, etc.
//
// FIXME : Should this be made part of the PCSX2 core emulation? (integrated into PluginManager)
// I'm undecided on if it makes sense more in that context or in this one (interface).
//
class AppPluginManager : public PluginManager
{
typedef PluginManager _parent;
public:
AppPluginManager();
virtual ~AppPluginManager() throw();
void Load( const wxString (&folders)[PluginId_Count] );
void Load( PluginsEnum_t pid, const wxString& srcfile );
void Unload( PluginsEnum_t pid );
void Unload();
void Init();
void Init( PluginsEnum_t pid );
void Shutdown( PluginsEnum_t pid );
void Shutdown();
void Close();
void Open();
protected:
bool OpenPlugin_GS();
void ClosePlugin_GS();
};
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "AppCommon.h"
// --------------------------------------------------------------------------------------
// AppPluginManager
// --------------------------------------------------------------------------------------
// This extension of PluginManager provides event listener sources for plugins -- loading,
// unloading, open, close, shutdown, etc.
//
// FIXME : Should this be made part of the PCSX2 core emulation? (integrated into PluginManager)
// I'm undecided on if it makes sense more in that context or in this one (interface).
//
class AppPluginManager : public PluginManager
{
typedef PluginManager _parent;
public:
AppPluginManager();
virtual ~AppPluginManager() throw();
void Load( const wxString (&folders)[PluginId_Count] );
void Load( PluginsEnum_t pid, const wxString& srcfile );
void Unload( PluginsEnum_t pid );
void Unload();
void Init();
void Init( PluginsEnum_t pid );
void Shutdown( PluginsEnum_t pid );
void Shutdown();
void Close();
void Open();
protected:
bool OpenPlugin_GS();
void ClosePlugin_GS();
};

View File

@ -1,236 +1,236 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "System/SysThreads.h"
#include "AppCommon.h"
#include "AppCorePlugins.h"
#include "SaveState.h"
#define AffinityAssert_AllowFrom_CoreThread() \
pxAssertMsg( GetCoreThread().IsSelf(), "Thread affinity violation: Call allowed from SysCoreThread only." )
#define AffinityAssert_DisallowFrom_CoreThread() \
pxAssertMsg( !GetCoreThread().IsSelf(), "Thread affinity violation: Call is *not* allowed from SysCoreThread." )
class IScopedCoreThread;
class BaseScopedCoreThread;
enum ScopedCoreResumeType
{
ScopedCore_BlockingResume
, ScopedCore_NonblockingResume
, ScopedCore_SkipResume
};
// --------------------------------------------------------------------------------------
// BaseSysExecEvent_ScopedCore
// --------------------------------------------------------------------------------------
class BaseSysExecEvent_ScopedCore : public SysExecEvent
{
protected:
SynchronousActionState* m_resume;
Threading::Mutex* m_mtx_resume;
public:
virtual ~BaseSysExecEvent_ScopedCore() throw() {}
BaseSysExecEvent_ScopedCore& SetResumeStates( SynchronousActionState* sync, Threading::Mutex* mutex )
{
m_resume = sync;
m_mtx_resume = mutex;
return *this;
}
BaseSysExecEvent_ScopedCore& SetResumeStates( SynchronousActionState& sync, Threading::Mutex& mutex )
{
m_resume = &sync;
m_mtx_resume = &mutex;
return *this;
}
protected:
BaseSysExecEvent_ScopedCore( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: SysExecEvent( sync )
{
m_resume = resume_sync;
m_mtx_resume = mtx_resume;
}
void _post_and_wait( IScopedCoreThread& core );
virtual void DoScopedTask() {}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_CoreThreadClose
// --------------------------------------------------------------------------------------
class SysExecEvent_CoreThreadClose : public BaseSysExecEvent_ScopedCore
{
public:
wxString GetEventName() const { return L"CloseCoreThread"; }
virtual ~SysExecEvent_CoreThreadClose() throw() {}
SysExecEvent_CoreThreadClose* Clone() const { return new SysExecEvent_CoreThreadClose( *this ); }
SysExecEvent_CoreThreadClose( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: BaseSysExecEvent_ScopedCore( sync, resume_sync, mtx_resume ) { }
protected:
void InvokeEvent();
};
// --------------------------------------------------------------------------------------
// SysExecEvent_CoreThreadPause
// --------------------------------------------------------------------------------------
class SysExecEvent_CoreThreadPause : public BaseSysExecEvent_ScopedCore
{
public:
wxString GetEventName() const { return L"PauseCoreThread"; }
virtual ~SysExecEvent_CoreThreadPause() throw() {}
SysExecEvent_CoreThreadPause* Clone() const { return new SysExecEvent_CoreThreadPause( *this ); }
SysExecEvent_CoreThreadPause( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: BaseSysExecEvent_ScopedCore( sync, resume_sync, mtx_resume ) { }
protected:
void InvokeEvent();
};
// --------------------------------------------------------------------------------------
// AppCoreThread class
// --------------------------------------------------------------------------------------
class AppCoreThread : public SysCoreThread
{
typedef SysCoreThread _parent;
public:
AppCoreThread();
virtual ~AppCoreThread() throw();
virtual void Suspend( bool isBlocking=false );
virtual void Resume();
virtual void Shutdown();
virtual void Cancel( bool isBlocking=true );
virtual void StateCheckInThread();
virtual void ChangeCdvdSource();
virtual void ApplySettings( const Pcsx2Config& src );
virtual void UploadStateCopy( const VmStateBuffer& copy );
protected:
virtual void OnResumeReady();
virtual void OnResumeInThread( bool IsSuspended );
virtual void OnSuspendInThread();
virtual void OnCleanupInThread();
virtual void PostVsyncToUI();
virtual void ExecuteTaskInThread();
virtual void DoCpuReset();
};
// --------------------------------------------------------------------------------------
// IScopedCoreThread / BaseScopedCoreThread
// --------------------------------------------------------------------------------------
class IScopedCoreThread
{
protected:
IScopedCoreThread() {}
public:
virtual ~IScopedCoreThread() throw() {};
virtual void AllowResume()=0;
virtual void DisallowResume()=0;
};
class BaseScopedCoreThread : public IScopedCoreThread
{
DeclareNoncopyableObject( BaseScopedCoreThread );
protected:
bool m_allowResume;
bool m_alreadyStopped;
bool m_alreadyScoped;
SynchronousActionState m_sync;
SynchronousActionState m_sync_resume;
Threading::Mutex m_mtx_resume;
BaseScopedCoreThread();
public:
virtual ~BaseScopedCoreThread() throw()=0;
virtual void AllowResume();
virtual void DisallowResume();
virtual bool PostToSysExec( BaseSysExecEvent_ScopedCore* msg );
protected:
// Called from destructors -- do not make virtual!!
void DoResume();
};
// --------------------------------------------------------------------------------------
// ScopedCoreThreadClose / ScopedCoreThreadPause / ScopedCoreThreadPopup
// --------------------------------------------------------------------------------------
// This class behaves a bit differently from other scoped classes due to the "standard"
// assumption that we actually do *not* want to resume CoreThread operations when an
// exception occurs. Because of this, the destructor of this class does *not* unroll the
// suspend operation. Instead you must manually instruct the class to resume using a call
// to the provisioned AllowResume() method.
//
// If the class leaves scope without having been resumed, a log is written to the console.
// This can be useful for troubleshooting, and also allows the log a second line of info
// indicating the status of CoreThread execution at the time of the exception.
//
// ScopedCoreThreadPopup is intended for use where message boxes are popped up to the user.
// The old style GUI (without GSopen2) must use a full close of the CoreThread, in order to
// ensure that the GS window isn't blocking the popup, and to avoid crashes if the GS window
// is maximized or fullscreen.
//
class ScopedCoreThreadClose : public BaseScopedCoreThread
{
typedef BaseScopedCoreThread _parent;
public:
ScopedCoreThreadClose();
virtual ~ScopedCoreThreadClose() throw();
void LoadPlugins();
};
struct ScopedCoreThreadPause : public BaseScopedCoreThread
{
typedef BaseScopedCoreThread _parent;
public:
ScopedCoreThreadPause( BaseSysExecEvent_ScopedCore* abuse_me=NULL );
virtual ~ScopedCoreThreadPause() throw();
};
struct ScopedCoreThreadPopup : public IScopedCoreThread
{
protected:
ScopedPtr<BaseScopedCoreThread> m_scoped_core;
public:
ScopedCoreThreadPopup();
virtual ~ScopedCoreThreadPopup() throw() {}
virtual void AllowResume();
virtual void DisallowResume();
};
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "System/SysThreads.h"
#include "AppCommon.h"
#include "AppCorePlugins.h"
#include "SaveState.h"
#define AffinityAssert_AllowFrom_CoreThread() \
pxAssertMsg( GetCoreThread().IsSelf(), "Thread affinity violation: Call allowed from SysCoreThread only." )
#define AffinityAssert_DisallowFrom_CoreThread() \
pxAssertMsg( !GetCoreThread().IsSelf(), "Thread affinity violation: Call is *not* allowed from SysCoreThread." )
class IScopedCoreThread;
class BaseScopedCoreThread;
enum ScopedCoreResumeType
{
ScopedCore_BlockingResume
, ScopedCore_NonblockingResume
, ScopedCore_SkipResume
};
// --------------------------------------------------------------------------------------
// BaseSysExecEvent_ScopedCore
// --------------------------------------------------------------------------------------
class BaseSysExecEvent_ScopedCore : public SysExecEvent
{
protected:
SynchronousActionState* m_resume;
Threading::Mutex* m_mtx_resume;
public:
virtual ~BaseSysExecEvent_ScopedCore() throw() {}
BaseSysExecEvent_ScopedCore& SetResumeStates( SynchronousActionState* sync, Threading::Mutex* mutex )
{
m_resume = sync;
m_mtx_resume = mutex;
return *this;
}
BaseSysExecEvent_ScopedCore& SetResumeStates( SynchronousActionState& sync, Threading::Mutex& mutex )
{
m_resume = &sync;
m_mtx_resume = &mutex;
return *this;
}
protected:
BaseSysExecEvent_ScopedCore( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: SysExecEvent( sync )
{
m_resume = resume_sync;
m_mtx_resume = mtx_resume;
}
void _post_and_wait( IScopedCoreThread& core );
virtual void DoScopedTask() {}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_CoreThreadClose
// --------------------------------------------------------------------------------------
class SysExecEvent_CoreThreadClose : public BaseSysExecEvent_ScopedCore
{
public:
wxString GetEventName() const { return L"CloseCoreThread"; }
virtual ~SysExecEvent_CoreThreadClose() throw() {}
SysExecEvent_CoreThreadClose* Clone() const { return new SysExecEvent_CoreThreadClose( *this ); }
SysExecEvent_CoreThreadClose( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: BaseSysExecEvent_ScopedCore( sync, resume_sync, mtx_resume ) { }
protected:
void InvokeEvent();
};
// --------------------------------------------------------------------------------------
// SysExecEvent_CoreThreadPause
// --------------------------------------------------------------------------------------
class SysExecEvent_CoreThreadPause : public BaseSysExecEvent_ScopedCore
{
public:
wxString GetEventName() const { return L"PauseCoreThread"; }
virtual ~SysExecEvent_CoreThreadPause() throw() {}
SysExecEvent_CoreThreadPause* Clone() const { return new SysExecEvent_CoreThreadPause( *this ); }
SysExecEvent_CoreThreadPause( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: BaseSysExecEvent_ScopedCore( sync, resume_sync, mtx_resume ) { }
protected:
void InvokeEvent();
};
// --------------------------------------------------------------------------------------
// AppCoreThread class
// --------------------------------------------------------------------------------------
class AppCoreThread : public SysCoreThread
{
typedef SysCoreThread _parent;
public:
AppCoreThread();
virtual ~AppCoreThread() throw();
virtual void Suspend( bool isBlocking=false );
virtual void Resume();
virtual void Shutdown();
virtual void Cancel( bool isBlocking=true );
virtual void StateCheckInThread();
virtual void ChangeCdvdSource();
virtual void ApplySettings( const Pcsx2Config& src );
virtual void UploadStateCopy( const VmStateBuffer& copy );
protected:
virtual void OnResumeReady();
virtual void OnResumeInThread( bool IsSuspended );
virtual void OnSuspendInThread();
virtual void OnCleanupInThread();
virtual void PostVsyncToUI();
virtual void ExecuteTaskInThread();
virtual void DoCpuReset();
};
// --------------------------------------------------------------------------------------
// IScopedCoreThread / BaseScopedCoreThread
// --------------------------------------------------------------------------------------
class IScopedCoreThread
{
protected:
IScopedCoreThread() {}
public:
virtual ~IScopedCoreThread() throw() {};
virtual void AllowResume()=0;
virtual void DisallowResume()=0;
};
class BaseScopedCoreThread : public IScopedCoreThread
{
DeclareNoncopyableObject( BaseScopedCoreThread );
protected:
bool m_allowResume;
bool m_alreadyStopped;
bool m_alreadyScoped;
SynchronousActionState m_sync;
SynchronousActionState m_sync_resume;
Threading::Mutex m_mtx_resume;
BaseScopedCoreThread();
public:
virtual ~BaseScopedCoreThread() throw()=0;
virtual void AllowResume();
virtual void DisallowResume();
virtual bool PostToSysExec( BaseSysExecEvent_ScopedCore* msg );
protected:
// Called from destructors -- do not make virtual!!
void DoResume();
};
// --------------------------------------------------------------------------------------
// ScopedCoreThreadClose / ScopedCoreThreadPause / ScopedCoreThreadPopup
// --------------------------------------------------------------------------------------
// This class behaves a bit differently from other scoped classes due to the "standard"
// assumption that we actually do *not* want to resume CoreThread operations when an
// exception occurs. Because of this, the destructor of this class does *not* unroll the
// suspend operation. Instead you must manually instruct the class to resume using a call
// to the provisioned AllowResume() method.
//
// If the class leaves scope without having been resumed, a log is written to the console.
// This can be useful for troubleshooting, and also allows the log a second line of info
// indicating the status of CoreThread execution at the time of the exception.
//
// ScopedCoreThreadPopup is intended for use where message boxes are popped up to the user.
// The old style GUI (without GSopen2) must use a full close of the CoreThread, in order to
// ensure that the GS window isn't blocking the popup, and to avoid crashes if the GS window
// is maximized or fullscreen.
//
class ScopedCoreThreadClose : public BaseScopedCoreThread
{
typedef BaseScopedCoreThread _parent;
public:
ScopedCoreThreadClose();
virtual ~ScopedCoreThreadClose() throw();
void LoadPlugins();
};
struct ScopedCoreThreadPause : public BaseScopedCoreThread
{
typedef BaseScopedCoreThread _parent;
public:
ScopedCoreThreadPause( BaseSysExecEvent_ScopedCore* abuse_me=NULL );
virtual ~ScopedCoreThreadPause() throw();
};
struct ScopedCoreThreadPopup : public IScopedCoreThread
{
protected:
ScopedPtr<BaseScopedCoreThread> m_scoped_core;
public:
ScopedCoreThreadPopup();
virtual ~ScopedCoreThreadPopup() throw() {}
virtual void AllowResume();
virtual void DisallowResume();
};

View File

@ -1,28 +1,28 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <wx/listbook.h>
template< typename T >
void Dialogs::BaseConfigurationDialog::AddPage( const char* label, int iconid )
{
const wxString labelstr( fromUTF8( label ) );
const int curidx = m_labels.Add( labelstr );
m_ApplyState.SetCurrentPage( curidx );
m_listbook.AddPage( new T( &m_listbook ), wxGetTranslation( labelstr ),
( labelstr == GetConfSettingsTabName() ), iconid );
}
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <wx/listbook.h>
template< typename T >
void Dialogs::BaseConfigurationDialog::AddPage( const char* label, int iconid )
{
const wxString labelstr( fromUTF8( label ) );
const int curidx = m_labels.Add( labelstr );
m_ApplyState.SetCurrentPage( curidx );
m_listbook.AddPage( new T( &m_listbook ), wxGetTranslation( labelstr ),
( labelstr == GetConfSettingsTabName() ), iconid );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,120 +1,120 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "App.h"
#include "CpuUsageProvider.h"
enum LimiterModeType
{
Limit_Nominal,
Limit_Turbo,
Limit_Slomo,
};
extern LimiterModeType g_LimiterMode;
// --------------------------------------------------------------------------------------
// GSPanel
// --------------------------------------------------------------------------------------
class GSPanel : public wxWindow, public EventListener_AppStatus
{
typedef wxWindow _parent;
protected:
AcceleratorDictionary m_Accels;
wxTimer m_HideMouseTimer;
bool m_CursorShown;
bool m_HasFocus;
public:
GSPanel( wxWindow* parent );
virtual ~GSPanel() throw();
void DoResize();
void DoShowMouse();
protected:
void AppStatusEvent_OnSettingsApplied();
#ifdef __WXMSW__
virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
#endif
void InitDefaultAccelerators();
void OnCloseWindow( wxCloseEvent& evt );
void OnResize(wxSizeEvent& event);
void OnShowMouse( wxMouseEvent& evt );
void OnHideMouseTimeout( wxTimerEvent& evt );
void OnKeyDown( wxKeyEvent& evt );
void OnFocus( wxFocusEvent& evt );
void OnFocusLost( wxFocusEvent& evt );
};
// --------------------------------------------------------------------------------------
// GSFrame
// --------------------------------------------------------------------------------------
class GSFrame : public wxFrame,
public EventListener_AppStatus,
public EventListener_CoreThread
{
typedef wxFrame _parent;
protected:
wxTimer m_timer_UpdateTitle;
wxWindowID m_id_gspanel;
wxWindowID m_id_OutputDisabled;
wxStaticText* m_label_Disabled;
wxStatusBar* m_statusbar;
CpuUsageProvider m_CpuUsage;
public:
GSFrame(wxWindow* parent, const wxString& title);
virtual ~GSFrame() throw();
GSPanel* GetViewport();
void SetFocus();
bool Show( bool shown=true );
wxStaticText* GetLabel_OutputDisabled() const;
protected:
void OnCloseWindow( wxCloseEvent& evt );
void OnMove( wxMoveEvent& evt );
void OnResize( wxSizeEvent& evt );
void OnActivate( wxActivateEvent& evt );
void OnUpdateTitle( wxTimerEvent& evt );
void AppStatusEvent_OnSettingsApplied();
void CoreThread_OnResumed();
void CoreThread_OnSuspended();
};
// --------------------------------------------------------------------------------------
// s* macros! ['s' stands for 'shortcut']
// --------------------------------------------------------------------------------------
// Use these for "silent fail" invocation of PCSX2 Application-related constructs. If the
// construct (albeit wxApp, MainFrame, CoreThread, etc) is null, the requested method will
// not be invoked, and an optional "else" clause can be affixed for handling the end case.
//
// See App.h (sApp) for more details.
//
#define sGSFrame \
if( GSFrame* __gsframe_ = wxGetApp().GetGsFramePtr() ) (*__gsframe_)
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "App.h"
#include "CpuUsageProvider.h"
enum LimiterModeType
{
Limit_Nominal,
Limit_Turbo,
Limit_Slomo,
};
extern LimiterModeType g_LimiterMode;
// --------------------------------------------------------------------------------------
// GSPanel
// --------------------------------------------------------------------------------------
class GSPanel : public wxWindow, public EventListener_AppStatus
{
typedef wxWindow _parent;
protected:
AcceleratorDictionary m_Accels;
wxTimer m_HideMouseTimer;
bool m_CursorShown;
bool m_HasFocus;
public:
GSPanel( wxWindow* parent );
virtual ~GSPanel() throw();
void DoResize();
void DoShowMouse();
protected:
void AppStatusEvent_OnSettingsApplied();
#ifdef __WXMSW__
virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
#endif
void InitDefaultAccelerators();
void OnCloseWindow( wxCloseEvent& evt );
void OnResize(wxSizeEvent& event);
void OnShowMouse( wxMouseEvent& evt );
void OnHideMouseTimeout( wxTimerEvent& evt );
void OnKeyDown( wxKeyEvent& evt );
void OnFocus( wxFocusEvent& evt );
void OnFocusLost( wxFocusEvent& evt );
};
// --------------------------------------------------------------------------------------
// GSFrame
// --------------------------------------------------------------------------------------
class GSFrame : public wxFrame,
public EventListener_AppStatus,
public EventListener_CoreThread
{
typedef wxFrame _parent;
protected:
wxTimer m_timer_UpdateTitle;
wxWindowID m_id_gspanel;
wxWindowID m_id_OutputDisabled;
wxStaticText* m_label_Disabled;
wxStatusBar* m_statusbar;
CpuUsageProvider m_CpuUsage;
public:
GSFrame(wxWindow* parent, const wxString& title);
virtual ~GSFrame() throw();
GSPanel* GetViewport();
void SetFocus();
bool Show( bool shown=true );
wxStaticText* GetLabel_OutputDisabled() const;
protected:
void OnCloseWindow( wxCloseEvent& evt );
void OnMove( wxMoveEvent& evt );
void OnResize( wxSizeEvent& evt );
void OnActivate( wxActivateEvent& evt );
void OnUpdateTitle( wxTimerEvent& evt );
void AppStatusEvent_OnSettingsApplied();
void CoreThread_OnResumed();
void CoreThread_OnSuspended();
};
// --------------------------------------------------------------------------------------
// s* macros! ['s' stands for 'shortcut']
// --------------------------------------------------------------------------------------
// Use these for "silent fail" invocation of PCSX2 Application-related constructs. If the
// construct (albeit wxApp, MainFrame, CoreThread, etc) is null, the requested method will
// not be invoked, and an optional "else" clause can be affixed for handling the end case.
//
// See App.h (sApp) for more details.
//
#define sGSFrame \
if( GSFrame* __gsframe_ = wxGetApp().GetGsFramePtr() ) (*__gsframe_)

View File

@ -1,353 +1,353 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of te License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "App.h"
#include "System/SysThreads.h"
#include "SaveState.h"
#include "ZipTools/ThreadedZipTools.h"
// Used to hold the current state backup (fullcopy of PS2 memory and plugin states).
//static VmStateBuffer state_buffer( L"Public Savestate Buffer" );
static const char SavestateIdentString[] = "PCSX2 Savestate";
static const uint SavestateIdentLen = sizeof(SavestateIdentString);
static void SaveStateFile_WriteHeader( IStreamWriter& thr )
{
thr.Write( SavestateIdentString );
thr.Write( g_SaveVersion );
}
static void SaveStateFile_ReadHeader( IStreamReader& thr )
{
char ident[SavestateIdentLen] = {0};
thr.Read( ident );
if( strcmp(SavestateIdentString, ident) )
throw Exception::SaveStateLoadError( thr.GetStreamName(),
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
);
u32 savever;
thr.Read( savever );
if( (savever >> 16) != (g_SaveVersion >> 16) )
throw Exception::SaveStateLoadError( thr.GetStreamName(),
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
);
if( savever > g_SaveVersion )
throw Exception::SaveStateLoadError( thr.GetStreamName(),
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
);
};
// --------------------------------------------------------------------------------------
// gzipReader
// --------------------------------------------------------------------------------------
// Interface for reading data from a gzip stream.
//
class gzipReader : public IStreamReader
{
DeclareNoncopyableObject(gzipReader);
protected:
wxString m_filename;
gzFile m_gzfp;
public:
gzipReader( const wxString& filename )
: m_filename( filename )
{
if( NULL == (m_gzfp = gzopen( m_filename.ToUTF8(), "rb" )) )
throw Exception::CannotCreateStream( m_filename, "Cannot open file for reading." );
gzbuffer(m_gzfp, 0x100000); // 1mb buffer for zlib internal operations
}
virtual ~gzipReader() throw ()
{
if( m_gzfp ) gzclose( m_gzfp );
}
wxString GetStreamName() const { return m_filename; }
void Read( void* dest, size_t size )
{
int result = gzread( m_gzfp, dest, size );
if( result == -1)
throw Exception::BadStream( m_filename, "Data read failed: Invalid or corrupted gzip archive." );
if( (size_t)result < size )
throw Exception::EndOfStream( m_filename );
}
};
static bool IsSavingOrLoading = false;
// --------------------------------------------------------------------------------------
// SysExecEvent_DownloadState
// --------------------------------------------------------------------------------------
// Pauses core emulation and downloads the savestate into the state_buffer.
//
class SysExecEvent_DownloadState : public SysExecEvent
{
protected:
VmStateBuffer* m_dest_buffer;
public:
wxString GetEventName() const { return L"VM_Download"; }
virtual ~SysExecEvent_DownloadState() throw() {}
SysExecEvent_DownloadState* Clone() const { return new SysExecEvent_DownloadState( *this ); }
SysExecEvent_DownloadState( VmStateBuffer* dest=NULL )
{
m_dest_buffer = dest;
}
bool IsCriticalEvent() const { return true; }
bool AllowCancelOnExit() const { return false; }
protected:
void InvokeEvent()
{
ScopedCoreThreadPause paused_core;
if( !SysHasValidState() )
throw Exception::RuntimeError( L"Cannot complete state freeze request; the virtual machine state is reset.", _("You'll need to start a new virtual machine before you can save its state.") );
memSavingState(m_dest_buffer).FreezeAll();
UI_EnableStateActions();
paused_core.AllowResume();
}
};
// It's bad mojo to have savestates trying to read and write from the same file at the
// same time. To prevent that we use this mutex lock, which is used by both the
// CompressThread and the UnzipFromDisk events. (note that CompressThread locks the
// mutex during OnStartInThread, which ensures that the ZipToDisk event blocks; preventing
// the SysExecutor's Idle Event from re-enabing savestates and slots.)
//
static Mutex mtx_CompressToDisk;
// --------------------------------------------------------------------------------------
// CompressThread_VmState
// --------------------------------------------------------------------------------------
class VmStateZipThread : public CompressThread_gzip
{
typedef CompressThread_gzip _parent;
protected:
ScopedLock m_lock_Compress;
public:
VmStateZipThread( const wxString& file, VmStateBuffer* srcdata )
: _parent( file, srcdata, SaveStateFile_WriteHeader )
{
m_lock_Compress.Assign(mtx_CompressToDisk);
}
VmStateZipThread( const wxString& file, ScopedPtr<VmStateBuffer>& srcdata )
: _parent( file, srcdata, SaveStateFile_WriteHeader )
{
m_lock_Compress.Assign(mtx_CompressToDisk);
}
virtual ~VmStateZipThread() throw()
{
}
protected:
void OnStartInThread()
{
_parent::OnStartInThread();
m_lock_Compress.Acquire();
}
void OnCleanupInThread()
{
m_lock_Compress.Release();
_parent::OnCleanupInThread();
}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_ZipToDisk
// --------------------------------------------------------------------------------------
class SysExecEvent_ZipToDisk : public SysExecEvent
{
protected:
VmStateBuffer* m_src_buffer;
wxString m_filename;
public:
wxString GetEventName() const { return L"VM_ZipToDisk"; }
virtual ~SysExecEvent_ZipToDisk() throw()
{
delete m_src_buffer;
}
SysExecEvent_ZipToDisk* Clone() const { return new SysExecEvent_ZipToDisk( *this ); }
SysExecEvent_ZipToDisk( ScopedPtr<VmStateBuffer>& src, const wxString& filename )
: m_filename( filename )
{
m_src_buffer = src.DetachPtr();
}
SysExecEvent_ZipToDisk( VmStateBuffer* src, const wxString& filename )
: m_filename( filename )
{
m_src_buffer = src;
}
bool IsCriticalEvent() const { return true; }
bool AllowCancelOnExit() const { return false; }
protected:
void InvokeEvent()
{
(new VmStateZipThread( m_filename, m_src_buffer ))->Start();
m_src_buffer = NULL;
}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_UnzipFromDisk
// --------------------------------------------------------------------------------------
// Note: Unzipping always goes directly into the SysCoreThread's static VM state, and is
// always a blocking action on the SysExecutor thread (the system cannot execute other
// commands while states are unzipping or uploading into the system).
//
class SysExecEvent_UnzipFromDisk : public SysExecEvent
{
protected:
wxString m_filename;
public:
wxString GetEventName() const { return L"VM_UnzipFromDisk"; }
virtual ~SysExecEvent_UnzipFromDisk() throw() {}
SysExecEvent_UnzipFromDisk* Clone() const { return new SysExecEvent_UnzipFromDisk( *this ); }
SysExecEvent_UnzipFromDisk( const wxString& filename )
: m_filename( filename )
{
}
wxString GetStreamName() const { return m_filename; }
protected:
void InvokeEvent()
{
ScopedLock lock( mtx_CompressToDisk );
gzipReader m_gzreader(m_filename );
SaveStateFile_ReadHeader( m_gzreader );
// We use direct Suspend/Resume control here, since it's desirable that emulation
// *ALWAYS* start execution after the new savestate is loaded.
GetCoreThread().Pause();
// fixme: should start initially with the file size, and then grow from there.
static const int BlockSize = 0x100000;
VmStateBuffer buffer( 0x800000, L"StateBuffer_UnzipFromDisk" ); // start with an 8 meg buffer to avoid frequent reallocation.
int curidx = 0;
try {
while(true) {
buffer.MakeRoomFor( curidx+BlockSize );
m_gzreader.Read( buffer.GetPtr(curidx), BlockSize );
curidx += BlockSize;
Threading::pxTestCancel();
}
}
catch( Exception::EndOfStream& )
{
// This exception actually means success! Any others we let get sent
// to the main event handler/thread for handling.
}
// Optional shutdown of plugins when loading states? I'm not implementing it yet because some
// things, like the SPU2-recovery trick, rely on not resetting the plugins prior to loading
// the new savestate data.
//if( ShutdownOnStateLoad ) GetCoreThread().Cancel();
GetCoreThread().UploadStateCopy( buffer );
GetCoreThread().Resume(); // force resume regardless of emulation state earlier.
}
};
// =====================================================================================================
// StateCopy Public Interface
// =====================================================================================================
void StateCopy_SaveToFile( const wxString& file )
{
UI_DisableStateActions();
ScopedPtr<VmStateBuffer> zipbuf(new VmStateBuffer( L"Zippable Savestate" ));
GetSysExecutorThread().PostEvent(new SysExecEvent_DownloadState( zipbuf ));
GetSysExecutorThread().PostEvent(new SysExecEvent_ZipToDisk( zipbuf, file ));
}
void StateCopy_LoadFromFile( const wxString& file )
{
UI_DisableSysActions();
GetSysExecutorThread().PostEvent(new SysExecEvent_UnzipFromDisk( file ));
}
// Saves recovery state info to the given saveslot, or saves the active emulation state
// (if one exists) and no recovery data was found. This is needed because when a recovery
// state is made, the emulation state is usually reset so the only persisting state is
// the one in the memory save. :)
void StateCopy_SaveToSlot( uint num )
{
const wxString file( SaveStateBase::GetFilename( num ) );
Console.WriteLn( Color_StrongGreen, "Saving savestate to slot %d...", num );
Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", file.c_str() );
StateCopy_SaveToFile( file );
}
void StateCopy_LoadFromSlot( uint slot )
{
wxString file( SaveStateBase::GetFilename( slot ) );
if( !wxFileExists( file ) )
{
Console.Warning( "Savestate slot %d is empty.", slot );
return;
}
Console.WriteLn( Color_StrongGreen, "Loading savestate from slot %d...", slot );
Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", file.c_str() );
StateCopy_LoadFromFile( file );
}
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of te License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "App.h"
#include "System/SysThreads.h"
#include "SaveState.h"
#include "ZipTools/ThreadedZipTools.h"
// Used to hold the current state backup (fullcopy of PS2 memory and plugin states).
//static VmStateBuffer state_buffer( L"Public Savestate Buffer" );
static const char SavestateIdentString[] = "PCSX2 Savestate";
static const uint SavestateIdentLen = sizeof(SavestateIdentString);
static void SaveStateFile_WriteHeader( IStreamWriter& thr )
{
thr.Write( SavestateIdentString );
thr.Write( g_SaveVersion );
}
static void SaveStateFile_ReadHeader( IStreamReader& thr )
{
char ident[SavestateIdentLen] = {0};
thr.Read( ident );
if( strcmp(SavestateIdentString, ident) )
throw Exception::SaveStateLoadError( thr.GetStreamName(),
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
);
u32 savever;
thr.Read( savever );
if( (savever >> 16) != (g_SaveVersion >> 16) )
throw Exception::SaveStateLoadError( thr.GetStreamName(),
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
);
if( savever > g_SaveVersion )
throw Exception::SaveStateLoadError( thr.GetStreamName(),
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
);
};
// --------------------------------------------------------------------------------------
// gzipReader
// --------------------------------------------------------------------------------------
// Interface for reading data from a gzip stream.
//
class gzipReader : public IStreamReader
{
DeclareNoncopyableObject(gzipReader);
protected:
wxString m_filename;
gzFile m_gzfp;
public:
gzipReader( const wxString& filename )
: m_filename( filename )
{
if( NULL == (m_gzfp = gzopen( m_filename.ToUTF8(), "rb" )) )
throw Exception::CannotCreateStream( m_filename, "Cannot open file for reading." );
gzbuffer(m_gzfp, 0x100000); // 1mb buffer for zlib internal operations
}
virtual ~gzipReader() throw ()
{
if( m_gzfp ) gzclose( m_gzfp );
}
wxString GetStreamName() const { return m_filename; }
void Read( void* dest, size_t size )
{
int result = gzread( m_gzfp, dest, size );
if( result == -1)
throw Exception::BadStream( m_filename, "Data read failed: Invalid or corrupted gzip archive." );
if( (size_t)result < size )
throw Exception::EndOfStream( m_filename );
}
};
static bool IsSavingOrLoading = false;
// --------------------------------------------------------------------------------------
// SysExecEvent_DownloadState
// --------------------------------------------------------------------------------------
// Pauses core emulation and downloads the savestate into the state_buffer.
//
class SysExecEvent_DownloadState : public SysExecEvent
{
protected:
VmStateBuffer* m_dest_buffer;
public:
wxString GetEventName() const { return L"VM_Download"; }
virtual ~SysExecEvent_DownloadState() throw() {}
SysExecEvent_DownloadState* Clone() const { return new SysExecEvent_DownloadState( *this ); }
SysExecEvent_DownloadState( VmStateBuffer* dest=NULL )
{
m_dest_buffer = dest;
}
bool IsCriticalEvent() const { return true; }
bool AllowCancelOnExit() const { return false; }
protected:
void InvokeEvent()
{
ScopedCoreThreadPause paused_core;
if( !SysHasValidState() )
throw Exception::RuntimeError( L"Cannot complete state freeze request; the virtual machine state is reset.", _("You'll need to start a new virtual machine before you can save its state.") );
memSavingState(m_dest_buffer).FreezeAll();
UI_EnableStateActions();
paused_core.AllowResume();
}
};
// It's bad mojo to have savestates trying to read and write from the same file at the
// same time. To prevent that we use this mutex lock, which is used by both the
// CompressThread and the UnzipFromDisk events. (note that CompressThread locks the
// mutex during OnStartInThread, which ensures that the ZipToDisk event blocks; preventing
// the SysExecutor's Idle Event from re-enabing savestates and slots.)
//
static Mutex mtx_CompressToDisk;
// --------------------------------------------------------------------------------------
// CompressThread_VmState
// --------------------------------------------------------------------------------------
class VmStateZipThread : public CompressThread_gzip
{
typedef CompressThread_gzip _parent;
protected:
ScopedLock m_lock_Compress;
public:
VmStateZipThread( const wxString& file, VmStateBuffer* srcdata )
: _parent( file, srcdata, SaveStateFile_WriteHeader )
{
m_lock_Compress.Assign(mtx_CompressToDisk);
}
VmStateZipThread( const wxString& file, ScopedPtr<VmStateBuffer>& srcdata )
: _parent( file, srcdata, SaveStateFile_WriteHeader )
{
m_lock_Compress.Assign(mtx_CompressToDisk);
}
virtual ~VmStateZipThread() throw()
{
}
protected:
void OnStartInThread()
{
_parent::OnStartInThread();
m_lock_Compress.Acquire();
}
void OnCleanupInThread()
{
m_lock_Compress.Release();
_parent::OnCleanupInThread();
}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_ZipToDisk
// --------------------------------------------------------------------------------------
class SysExecEvent_ZipToDisk : public SysExecEvent
{
protected:
VmStateBuffer* m_src_buffer;
wxString m_filename;
public:
wxString GetEventName() const { return L"VM_ZipToDisk"; }
virtual ~SysExecEvent_ZipToDisk() throw()
{
delete m_src_buffer;
}
SysExecEvent_ZipToDisk* Clone() const { return new SysExecEvent_ZipToDisk( *this ); }
SysExecEvent_ZipToDisk( ScopedPtr<VmStateBuffer>& src, const wxString& filename )
: m_filename( filename )
{
m_src_buffer = src.DetachPtr();
}
SysExecEvent_ZipToDisk( VmStateBuffer* src, const wxString& filename )
: m_filename( filename )
{
m_src_buffer = src;
}
bool IsCriticalEvent() const { return true; }
bool AllowCancelOnExit() const { return false; }
protected:
void InvokeEvent()
{
(new VmStateZipThread( m_filename, m_src_buffer ))->Start();
m_src_buffer = NULL;
}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_UnzipFromDisk
// --------------------------------------------------------------------------------------
// Note: Unzipping always goes directly into the SysCoreThread's static VM state, and is
// always a blocking action on the SysExecutor thread (the system cannot execute other
// commands while states are unzipping or uploading into the system).
//
class SysExecEvent_UnzipFromDisk : public SysExecEvent
{
protected:
wxString m_filename;
public:
wxString GetEventName() const { return L"VM_UnzipFromDisk"; }
virtual ~SysExecEvent_UnzipFromDisk() throw() {}
SysExecEvent_UnzipFromDisk* Clone() const { return new SysExecEvent_UnzipFromDisk( *this ); }
SysExecEvent_UnzipFromDisk( const wxString& filename )
: m_filename( filename )
{
}
wxString GetStreamName() const { return m_filename; }
protected:
void InvokeEvent()
{
ScopedLock lock( mtx_CompressToDisk );
gzipReader m_gzreader(m_filename );
SaveStateFile_ReadHeader( m_gzreader );
// We use direct Suspend/Resume control here, since it's desirable that emulation
// *ALWAYS* start execution after the new savestate is loaded.
GetCoreThread().Pause();
// fixme: should start initially with the file size, and then grow from there.
static const int BlockSize = 0x100000;
VmStateBuffer buffer( 0x800000, L"StateBuffer_UnzipFromDisk" ); // start with an 8 meg buffer to avoid frequent reallocation.
int curidx = 0;
try {
while(true) {
buffer.MakeRoomFor( curidx+BlockSize );
m_gzreader.Read( buffer.GetPtr(curidx), BlockSize );
curidx += BlockSize;
Threading::pxTestCancel();
}
}
catch( Exception::EndOfStream& )
{
// This exception actually means success! Any others we let get sent
// to the main event handler/thread for handling.
}
// Optional shutdown of plugins when loading states? I'm not implementing it yet because some
// things, like the SPU2-recovery trick, rely on not resetting the plugins prior to loading
// the new savestate data.
//if( ShutdownOnStateLoad ) GetCoreThread().Cancel();
GetCoreThread().UploadStateCopy( buffer );
GetCoreThread().Resume(); // force resume regardless of emulation state earlier.
}
};
// =====================================================================================================
// StateCopy Public Interface
// =====================================================================================================
void StateCopy_SaveToFile( const wxString& file )
{
UI_DisableStateActions();
ScopedPtr<VmStateBuffer> zipbuf(new VmStateBuffer( L"Zippable Savestate" ));
GetSysExecutorThread().PostEvent(new SysExecEvent_DownloadState( zipbuf ));
GetSysExecutorThread().PostEvent(new SysExecEvent_ZipToDisk( zipbuf, file ));
}
void StateCopy_LoadFromFile( const wxString& file )
{
UI_DisableSysActions();
GetSysExecutorThread().PostEvent(new SysExecEvent_UnzipFromDisk( file ));
}
// Saves recovery state info to the given saveslot, or saves the active emulation state
// (if one exists) and no recovery data was found. This is needed because when a recovery
// state is made, the emulation state is usually reset so the only persisting state is
// the one in the memory save. :)
void StateCopy_SaveToSlot( uint num )
{
const wxString file( SaveStateBase::GetFilename( num ) );
Console.WriteLn( Color_StrongGreen, "Saving savestate to slot %d...", num );
Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", file.c_str() );
StateCopy_SaveToFile( file );
}
void StateCopy_LoadFromSlot( uint slot )
{
wxString file( SaveStateBase::GetFilename( slot ) );
if( !wxFileExists( file ) )
{
Console.Warning( "Savestate slot %d is empty.", slot );
return;
}
Console.WriteLn( Color_StrongGreen, "Loading savestate from slot %d...", slot );
Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", file.c_str() );
StateCopy_LoadFromFile( file );
}

View File

@ -1,109 +1,109 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "MainFrame.h"
#include "GSFrame.h"
// General Notes:
// * It's very important that we re-discover menu items by ID every time we change them,
// because the modern era of configurable GUIs means that we can't be assured the IDs
// exist anymore.
// This is necessary because this stupid wxWidgets thing has implicit debug errors
// in the FindItem call that asserts if the menu options are missing. This is bad
// mojo for configurable/dynamic menus. >_<
void MainEmuFrame::EnableMenuItem( int id, bool enable )
{
if( wxMenuItem* item = m_menubar.FindItem(id) )
item->Enable( enable );
}
static void _SaveLoadStuff( bool enabled )
{
sMainFrame.EnableMenuItem( MenuId_Sys_LoadStates, enabled );
sMainFrame.EnableMenuItem( MenuId_Sys_SaveStates, enabled );
}
// Updates the enable/disable status of all System related controls: menus, toolbars,
// etc. Typically called by SysEvtHandler whenever the message pump becomes idle.
void UI_UpdateSysControls()
{
if( wxGetApp().PostMethodMyself( &UI_UpdateSysControls ) ) return;
sApp.PostAction( CoreThreadStatusEvent( CoreThread_Indeterminate ) );
_SaveLoadStuff( true );
}
void UI_DisableSysReset()
{
if( wxGetApp().PostMethodMyself( UI_DisableSysReset ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
_SaveLoadStuff( false );
}
void UI_DisableSysShutdown()
{
if( wxGetApp().PostMethodMyself( &UI_DisableSysShutdown ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, false );
}
void UI_EnableSysShutdown()
{
if( wxGetApp().PostMethodMyself( &UI_EnableSysShutdown ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, true );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, true );
}
void UI_DisableSysActions()
{
if( wxGetApp().PostMethodMyself( &UI_DisableSysActions ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, false );
_SaveLoadStuff( false );
}
void UI_EnableSysActions()
{
if( wxGetApp().PostMethodMyself( &UI_EnableSysActions ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, true );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, true );
_SaveLoadStuff( true );
}
void UI_DisableStateActions()
{
if( wxGetApp().PostMethodMyself( &UI_DisableStateActions ) ) return;
_SaveLoadStuff( false );
}
void UI_EnableStateActions()
{
if( wxGetApp().PostMethodMyself( &UI_EnableStateActions ) ) return;
_SaveLoadStuff( true );
}
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "MainFrame.h"
#include "GSFrame.h"
// General Notes:
// * It's very important that we re-discover menu items by ID every time we change them,
// because the modern era of configurable GUIs means that we can't be assured the IDs
// exist anymore.
// This is necessary because this stupid wxWidgets thing has implicit debug errors
// in the FindItem call that asserts if the menu options are missing. This is bad
// mojo for configurable/dynamic menus. >_<
void MainEmuFrame::EnableMenuItem( int id, bool enable )
{
if( wxMenuItem* item = m_menubar.FindItem(id) )
item->Enable( enable );
}
static void _SaveLoadStuff( bool enabled )
{
sMainFrame.EnableMenuItem( MenuId_Sys_LoadStates, enabled );
sMainFrame.EnableMenuItem( MenuId_Sys_SaveStates, enabled );
}
// Updates the enable/disable status of all System related controls: menus, toolbars,
// etc. Typically called by SysEvtHandler whenever the message pump becomes idle.
void UI_UpdateSysControls()
{
if( wxGetApp().PostMethodMyself( &UI_UpdateSysControls ) ) return;
sApp.PostAction( CoreThreadStatusEvent( CoreThread_Indeterminate ) );
_SaveLoadStuff( true );
}
void UI_DisableSysReset()
{
if( wxGetApp().PostMethodMyself( UI_DisableSysReset ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
_SaveLoadStuff( false );
}
void UI_DisableSysShutdown()
{
if( wxGetApp().PostMethodMyself( &UI_DisableSysShutdown ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, false );
}
void UI_EnableSysShutdown()
{
if( wxGetApp().PostMethodMyself( &UI_EnableSysShutdown ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, true );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, true );
}
void UI_DisableSysActions()
{
if( wxGetApp().PostMethodMyself( &UI_DisableSysActions ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, false );
_SaveLoadStuff( false );
}
void UI_EnableSysActions()
{
if( wxGetApp().PostMethodMyself( &UI_EnableSysActions ) ) return;
sMainFrame.EnableMenuItem( MenuId_Sys_Restart, true );
sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, true );
_SaveLoadStuff( true );
}
void UI_DisableStateActions()
{
if( wxGetApp().PostMethodMyself( &UI_DisableStateActions ) ) return;
_SaveLoadStuff( false );
}
void UI_EnableStateActions()
{
if( wxGetApp().PostMethodMyself( &UI_EnableStateActions ) ) return;
_SaveLoadStuff( true );
}

View File

@ -1,237 +1,237 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Utilities/PersistentThread.h"
#include "Utilities/pxEvents.h"
// TODO!! Make this system a bit more generic, and then move it to the Utilities library.
// --------------------------------------------------------------------------------------
// SysExecEvent
// --------------------------------------------------------------------------------------
// Base class for all pxEvtHandler processable events.
//
// Rules for deriving:
// * Override InvokeEvent(), *NOT* _DoInvokeEvent(). _DoInvokeEvent() performs setup and
// wraps exceptions for transport to the invoking context/thread, and then itself calls
// InvokeEvent() to perform the derived class implementation.
//
// * Derived classes must implement their own versions of an empty constructor and
// Clone(), or else the class will fail to be copied to the event handler's thread
// context correctly.
//
// * This class is not abstract, and gives no error if the invocation method is not
// overridden: It can be used as a simple ping device against the event queue, Re-
// awaking the invoking thread as soon as the queue has caught up to and processed
// the event.
//
// * Avoid using virtual class inheritence. It's unreliable at best.
//
class SysExecEvent : public ICloneable
{
protected:
SynchronousActionState* m_sync;
public:
virtual ~SysExecEvent() throw() {}
SysExecEvent* Clone() const { return new SysExecEvent( *this ); }
SysExecEvent( SynchronousActionState* sync=NULL )
{
m_sync = sync;
}
SysExecEvent( SynchronousActionState& sync )
{
m_sync = &sync;
}
const SynchronousActionState* GetSyncState() const { return m_sync; }
SynchronousActionState* GetSyncState() { return m_sync; }
SysExecEvent& SetSyncState( SynchronousActionState* obj ) { m_sync = obj; return *this; }
SysExecEvent& SetSyncState( SynchronousActionState& obj ) { m_sync = &obj; return *this; }
// Tells the Event Handler whether or not this event can be skipped when the system
// is being quit or reset. Typically set this to true for events which shut down the
// system, since program crashes can occur if the program tries to exit while threads
// are running.
virtual bool IsCriticalEvent() const { return false; }
// Tells the Event Handler whether or not this event can be canceled. Typically events
// should not prohibit cancellation, since it expedites program termination and helps
// avoid permanent deadlock. Some actions like saving states and shutdown procedures
// should not allow cancellation since they could result in program crashes or corrupted
// data.
virtual bool AllowCancelOnExit() const { return true; }
virtual void _DoInvokeEvent();
virtual void PostResult() const;
virtual wxString GetEventName() const;
virtual wxString GetEventMessage() const;
virtual int GetResult()
{
if( !pxAssertDev( m_sync != NULL, "SysEvent: Expecting return value, but no sync object provided." ) ) return 0;
return m_sync->return_value;
}
virtual void SetException( BaseException* ex );
void SetException( const BaseException& ex );
protected:
virtual void InvokeEvent();
virtual void CleanupEvent();
};
// --------------------------------------------------------------------------------------
// SysExecEvent_MethodVoid
// --------------------------------------------------------------------------------------
class SysExecEvent_MethodVoid : public SysExecEvent
{
protected:
FnType_Void* m_method;
public:
wxString GetEventName() const { return L"MethodVoid"; }
virtual ~SysExecEvent_MethodVoid() throw() {}
SysExecEvent_MethodVoid* Clone() const { return new SysExecEvent_MethodVoid( *this ); }
explicit SysExecEvent_MethodVoid( FnType_Void* method = NULL )
{
m_method = method;
}
protected:
void InvokeEvent()
{
if( m_method ) m_method();
}
};
typedef std::list<SysExecEvent*> pxEvtList;
// --------------------------------------------------------------------------------------
// pxEvtHandler
// --------------------------------------------------------------------------------------
// Purpose: To provide a safe environment for queuing tasks that must be executed in
// sequential order (in blocking fashion). Unlike the wxWidgets event handlers, instances
// of this handler can be stalled for extended periods of time without affecting the
// responsiveness of the GUI or frame updates of the DirectX output windows. This class
// is mostly intended to be used from the context of an ExecutorThread.
//
// Rationales:
// * Using the main event handler of wxWidgets is dangerous because it must call itself
// recursively when waiting on threaded events such as semaphore and mutexes. Thus,
// tasks such as suspending the VM would invoke the event queue while waiting,
// running events that expect the suspend to be complete while the suspend was still
// pending.
//
// * wxWidgets Event Queue (wxEvtHandler) isn't thread-safe and isn't even
// intended for use for anything other than wxWindow events (it uses static vars
// and checks/modifies wxApp globals while processing), so it's useless to us.
// Have to roll our own. -_-
//
class pxEvtHandler
{
protected:
pxEvtList m_pendingEvents;
pxEvtList m_idleEvents;
Threading::MutexRecursive m_mtx_pending;
Threading::Semaphore m_wakeup;
wxThreadIdType m_OwnerThreadId;
volatile u32 m_Quitting;
// Used for performance measuring the execution of individual events,
// and also for detecting deadlocks during message processing.
volatile u64 m_qpc_Start;
public:
pxEvtHandler();
virtual ~pxEvtHandler() throw() {}
virtual wxString GetEventHandlerName() const { return L"pxEvtHandler"; }
virtual void ShutdownQueue();
bool IsShuttingDown() const { return !!m_Quitting; }
void ProcessEvents( pxEvtList& list );
void ProcessPendingEvents();
void ProcessIdleEvents();
void Idle();
void AddPendingEvent( SysExecEvent& evt );
void PostEvent( SysExecEvent* evt );
void PostEvent( const SysExecEvent& evt );
void PostIdleEvent( SysExecEvent* evt );
void PostIdleEvent( const SysExecEvent& evt );
void ProcessEvent( SysExecEvent* evt );
void ProcessEvent( SysExecEvent& evt );
bool ProcessMethodSelf( FnType_Void* method );
void SetActiveThread();
protected:
virtual void _DoIdle() {}
};
// --------------------------------------------------------------------------------------
// ExecutorThread
// --------------------------------------------------------------------------------------
// Threaded wrapper class for implementing pxEvtHandler. Simply create the desired
// EvtHandler, start the thread, and enjoy queued event execution in fully blocking fashion.
//
class ExecutorThread : public Threading::PersistentThread
{
typedef Threading::PersistentThread _parent;
protected:
ScopedPtr<wxTimer> m_ExecutorTimer;
ScopedPtr<pxEvtHandler> m_EvtHandler;
public:
ExecutorThread( pxEvtHandler* evtandler = NULL );
virtual ~ExecutorThread() throw() { }
virtual void ShutdownQueue();
void PostEvent( SysExecEvent* evt );
void PostEvent( const SysExecEvent& evt );
void PostIdleEvent( SysExecEvent* evt );
void PostIdleEvent( const SysExecEvent& evt );
void ProcessEvent( SysExecEvent* evt );
void ProcessEvent( SysExecEvent& evt );
bool ProcessMethodSelf( void (*evt)() )
{
return m_EvtHandler ? m_EvtHandler->ProcessMethodSelf( evt ) : false;
}
protected:
void OnStart();
void ExecuteTaskInThread();
void OnCleanupInThread();
};
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Utilities/PersistentThread.h"
#include "Utilities/pxEvents.h"
// TODO!! Make this system a bit more generic, and then move it to the Utilities library.
// --------------------------------------------------------------------------------------
// SysExecEvent
// --------------------------------------------------------------------------------------
// Base class for all pxEvtHandler processable events.
//
// Rules for deriving:
// * Override InvokeEvent(), *NOT* _DoInvokeEvent(). _DoInvokeEvent() performs setup and
// wraps exceptions for transport to the invoking context/thread, and then itself calls
// InvokeEvent() to perform the derived class implementation.
//
// * Derived classes must implement their own versions of an empty constructor and
// Clone(), or else the class will fail to be copied to the event handler's thread
// context correctly.
//
// * This class is not abstract, and gives no error if the invocation method is not
// overridden: It can be used as a simple ping device against the event queue, Re-
// awaking the invoking thread as soon as the queue has caught up to and processed
// the event.
//
// * Avoid using virtual class inheritence. It's unreliable at best.
//
class SysExecEvent : public ICloneable
{
protected:
SynchronousActionState* m_sync;
public:
virtual ~SysExecEvent() throw() {}
SysExecEvent* Clone() const { return new SysExecEvent( *this ); }
SysExecEvent( SynchronousActionState* sync=NULL )
{
m_sync = sync;
}
SysExecEvent( SynchronousActionState& sync )
{
m_sync = &sync;
}
const SynchronousActionState* GetSyncState() const { return m_sync; }
SynchronousActionState* GetSyncState() { return m_sync; }
SysExecEvent& SetSyncState( SynchronousActionState* obj ) { m_sync = obj; return *this; }
SysExecEvent& SetSyncState( SynchronousActionState& obj ) { m_sync = &obj; return *this; }
// Tells the Event Handler whether or not this event can be skipped when the system
// is being quit or reset. Typically set this to true for events which shut down the
// system, since program crashes can occur if the program tries to exit while threads
// are running.
virtual bool IsCriticalEvent() const { return false; }
// Tells the Event Handler whether or not this event can be canceled. Typically events
// should not prohibit cancellation, since it expedites program termination and helps
// avoid permanent deadlock. Some actions like saving states and shutdown procedures
// should not allow cancellation since they could result in program crashes or corrupted
// data.
virtual bool AllowCancelOnExit() const { return true; }
virtual void _DoInvokeEvent();
virtual void PostResult() const;
virtual wxString GetEventName() const;
virtual wxString GetEventMessage() const;
virtual int GetResult()
{
if( !pxAssertDev( m_sync != NULL, "SysEvent: Expecting return value, but no sync object provided." ) ) return 0;
return m_sync->return_value;
}
virtual void SetException( BaseException* ex );
void SetException( const BaseException& ex );
protected:
virtual void InvokeEvent();
virtual void CleanupEvent();
};
// --------------------------------------------------------------------------------------
// SysExecEvent_MethodVoid
// --------------------------------------------------------------------------------------
class SysExecEvent_MethodVoid : public SysExecEvent
{
protected:
FnType_Void* m_method;
public:
wxString GetEventName() const { return L"MethodVoid"; }
virtual ~SysExecEvent_MethodVoid() throw() {}
SysExecEvent_MethodVoid* Clone() const { return new SysExecEvent_MethodVoid( *this ); }
explicit SysExecEvent_MethodVoid( FnType_Void* method = NULL )
{
m_method = method;
}
protected:
void InvokeEvent()
{
if( m_method ) m_method();
}
};
typedef std::list<SysExecEvent*> pxEvtList;
// --------------------------------------------------------------------------------------
// pxEvtHandler
// --------------------------------------------------------------------------------------
// Purpose: To provide a safe environment for queuing tasks that must be executed in
// sequential order (in blocking fashion). Unlike the wxWidgets event handlers, instances
// of this handler can be stalled for extended periods of time without affecting the
// responsiveness of the GUI or frame updates of the DirectX output windows. This class
// is mostly intended to be used from the context of an ExecutorThread.
//
// Rationales:
// * Using the main event handler of wxWidgets is dangerous because it must call itself
// recursively when waiting on threaded events such as semaphore and mutexes. Thus,
// tasks such as suspending the VM would invoke the event queue while waiting,
// running events that expect the suspend to be complete while the suspend was still
// pending.
//
// * wxWidgets Event Queue (wxEvtHandler) isn't thread-safe and isn't even
// intended for use for anything other than wxWindow events (it uses static vars
// and checks/modifies wxApp globals while processing), so it's useless to us.
// Have to roll our own. -_-
//
class pxEvtHandler
{
protected:
pxEvtList m_pendingEvents;
pxEvtList m_idleEvents;
Threading::MutexRecursive m_mtx_pending;
Threading::Semaphore m_wakeup;
wxThreadIdType m_OwnerThreadId;
volatile u32 m_Quitting;
// Used for performance measuring the execution of individual events,
// and also for detecting deadlocks during message processing.
volatile u64 m_qpc_Start;
public:
pxEvtHandler();
virtual ~pxEvtHandler() throw() {}
virtual wxString GetEventHandlerName() const { return L"pxEvtHandler"; }
virtual void ShutdownQueue();
bool IsShuttingDown() const { return !!m_Quitting; }
void ProcessEvents( pxEvtList& list );
void ProcessPendingEvents();
void ProcessIdleEvents();
void Idle();
void AddPendingEvent( SysExecEvent& evt );
void PostEvent( SysExecEvent* evt );
void PostEvent( const SysExecEvent& evt );
void PostIdleEvent( SysExecEvent* evt );
void PostIdleEvent( const SysExecEvent& evt );
void ProcessEvent( SysExecEvent* evt );
void ProcessEvent( SysExecEvent& evt );
bool ProcessMethodSelf( FnType_Void* method );
void SetActiveThread();
protected:
virtual void _DoIdle() {}
};
// --------------------------------------------------------------------------------------
// ExecutorThread
// --------------------------------------------------------------------------------------
// Threaded wrapper class for implementing pxEvtHandler. Simply create the desired
// EvtHandler, start the thread, and enjoy queued event execution in fully blocking fashion.
//
class ExecutorThread : public Threading::PersistentThread
{
typedef Threading::PersistentThread _parent;
protected:
ScopedPtr<wxTimer> m_ExecutorTimer;
ScopedPtr<pxEvtHandler> m_EvtHandler;
public:
ExecutorThread( pxEvtHandler* evtandler = NULL );
virtual ~ExecutorThread() throw() { }
virtual void ShutdownQueue();
void PostEvent( SysExecEvent* evt );
void PostEvent( const SysExecEvent& evt );
void PostIdleEvent( SysExecEvent* evt );
void PostIdleEvent( const SysExecEvent& evt );
void ProcessEvent( SysExecEvent* evt );
void ProcessEvent( SysExecEvent& evt );
bool ProcessMethodSelf( void (*evt)() )
{
return m_EvtHandler ? m_EvtHandler->ProcessMethodSelf( evt ) : false;
}
protected:
void OnStart();
void ExecuteTaskInThread();
void OnCleanupInThread();
};