diff --git a/common/include/PS2Edefs.h b/common/include/PS2Edefs.h index 610cd3fb84..43536dfd10 100644 --- a/common/include/PS2Edefs.h +++ b/common/include/PS2Edefs.h @@ -256,11 +256,8 @@ void CALLBACK GSsetFrameSkip(int frameskip); int CALLBACK GSsetupRecording(int start, void* pData); void CALLBACK GSreset(); +void CALLBACK GSgetTitleInfo( char dest[128] ); void CALLBACK GSwriteCSR(u32 value); -void CALLBACK GSgetDriverInfo(GSdriverInfo *info); -#ifdef _WIN32 -s32 CALLBACK GSsetWindowInfo(winInfo *info); -#endif s32 CALLBACK GSfreeze(int mode, freezeData *data); void CALLBACK GSconfigure(); void CALLBACK GSabout(); @@ -528,6 +525,7 @@ typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSgetTitleInfo)(char dest[128]); typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); typedef void (CALLBACK* _GSsetBaseMem)(void*); @@ -669,6 +667,7 @@ extern _GSreadFIFO GSreadFIFO; extern _GSreadFIFO2 GSreadFIFO2; extern _GSchangeSaveState GSchangeSaveState; +extern _GSgetTitleInfo GSgetTitleInfo; extern _GSmakeSnapshot GSmakeSnapshot; extern _GSmakeSnapshot2 GSmakeSnapshot2; extern _GSirqCallback GSirqCallback; diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index c21f96a204..860168c43f 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -32,11 +32,9 @@ using namespace Threading; extern u8 psxhblankgate; static const uint EECNT_FUTURE_TARGET = 0x10000000; +static int gates = 0; -u64 profile_starttick = 0; -u64 profile_totalticks = 0; - -int gates = 0; +uint g_FrameCount = 0; // Counter 4 takes care of scanlines - hSync/hBlanks // Counter 5 takes care of vSync/vBlanks @@ -47,6 +45,7 @@ SyncCounter vsyncCounter; u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate() s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate() + void rcntReset(int index) { counters[index].count = 0; counters[index].sCycleT = cpuRegs.cycle; @@ -125,6 +124,8 @@ void rcntInit() { int i; + g_FrameCount = 0; + memzero(counters); for (i=0; i<4; i++) { @@ -148,9 +149,6 @@ void rcntInit() cpuRcntSet(); } -// debug code, used for stats -int g_nhsyncCounter; -static uint iFrame = 0; #ifndef _WIN32 #include @@ -344,12 +342,12 @@ static __forceinline void VSyncStart(u32 sCycle) Cpu->CheckExecutionState(); GetCoreThread().VsyncInThread(); - EECNT_LOG( "///////// EE COUNTER VSYNC START (frame: %6d) \\\\\\\\\\\\\\\\\\\\ ", iFrame ); + EECNT_LOG( "///////// EE COUNTER VSYNC START (frame: %6d) \\\\\\\\\\\\\\\\\\\\ ", g_FrameCount ); // EE Profiling and Debug code. // FIXME: should probably be moved to VsyncInThread, and handled // by UI implementations. (ie, AppCoreThread in PCSX2-wx interface). - vSyncDebugStuff( iFrame ); + vSyncDebugStuff( g_FrameCount ); CpuVU0->Vsync(); CpuVU1->Vsync(); @@ -390,9 +388,9 @@ static __forceinline void VSyncStart(u32 sCycle) static __forceinline void VSyncEnd(u32 sCycle) { - EECNT_LOG( "///////// EE COUNTER VSYNC END \\\\\\\\\\\\\\\\\\\\ (frame: %d)", iFrame ); + EECNT_LOG( "///////// EE COUNTER VSYNC END (frame: %d) \\\\\\\\\\\\\\\\\\\\", g_FrameCount ); - iFrame++; + g_FrameCount++; gsPostVsyncEnd(); diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h index 5cc1496477..21a19774d3 100644 --- a/pcsx2/Counters.h +++ b/pcsx2/Counters.h @@ -130,6 +130,7 @@ extern SyncCounter vsyncCounter; extern s32 nextCounter; // delta until the next counter event (must be signed) extern u32 nextsCounter; +extern uint g_FrameCount; extern void rcntUpdate_hScanline(); extern void rcntUpdate_vSync(); diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 270637a56d..fcf2bcd648 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -145,6 +145,7 @@ _GSgifSoftReset GSgifSoftReset; _GSreadFIFO GSreadFIFO; _GSreadFIFO2 GSreadFIFO2; _GSchangeSaveState GSchangeSaveState; +_GSgetTitleInfo GSgetTitleInfo; _GSmakeSnapshot GSmakeSnapshot; _GSmakeSnapshot2 GSmakeSnapshot2; _GSirqCallback GSirqCallback; @@ -177,6 +178,14 @@ static void CALLBACK GS_printf(int timeout, char *fmt, ...) Console.WriteLn(msg); } +void CALLBACK GS_getTitleInfo( char dest[128] ) +{ + dest[0] = 'G'; + dest[1] = 'S'; + dest[2] = 0; +} + + // PAD _PADinit PADinit; _PADopen PADopen; @@ -297,6 +306,7 @@ static const LegacyApi_ReqMethod s_MethMessReq_GS[] = { "GSsetVsync", (vMeth**)&GSsetVsync, (vMeth*)GS_setVsync }, { "GSsetExclusive", (vMeth**)&GSsetExclusive, (vMeth*)GS_setExclusive }, { "GSchangeSaveState",(vMeth**)&GSchangeSaveState,(vMeth*)GS_changeSaveState }, + { "GSgetTitleInfo", (vMeth**)&GSgetTitleInfo, (vMeth*)GS_getTitleInfo }, { NULL } }; @@ -941,9 +951,9 @@ void PluginManager::Open( PluginsEnum_t pid ) bool result = true; switch( pid ) { - case PluginId_CDVD: result = OpenPlugin_CDVD(); break; case PluginId_GS: result = OpenPlugin_GS(); break; case PluginId_PAD: result = OpenPlugin_PAD(); break; + case PluginId_CDVD: result = OpenPlugin_CDVD(); break; case PluginId_SPU2: result = OpenPlugin_SPU2(); break; case PluginId_USB: result = OpenPlugin_USB(); break; case PluginId_FW: result = OpenPlugin_FW(); break; @@ -1003,17 +1013,54 @@ void PluginManager::ClosePlugin_GS() GetMTGS().Suspend(); } +void PluginManager::ClosePlugin_CDVD() +{ + DoCDVDclose(); +} + +void PluginManager::ClosePlugin_PAD() +{ + m_info[PluginId_PAD].CommonBindings.Close(); +} + +void PluginManager::ClosePlugin_SPU2() +{ + m_info[PluginId_SPU2].CommonBindings.Close(); +} + +void PluginManager::ClosePlugin_DEV9() +{ + m_info[PluginId_DEV9].CommonBindings.Close(); +} + +void PluginManager::ClosePlugin_USB() +{ + m_info[PluginId_USB].CommonBindings.Close(); +} + +void PluginManager::ClosePlugin_FW() +{ + m_info[PluginId_FW].CommonBindings.Close(); +} + + void PluginManager::Close( PluginsEnum_t pid ) { if( !m_info[pid].IsOpened ) return; Console.Indent().WriteLn( "Closing %s", tbl_PluginInfo[pid].shortname ); - if( pid == PluginId_GS ) - ClosePlugin_GS(); - else if( pid == PluginId_CDVD ) - DoCDVDclose(); - else - m_info[pid].CommonBindings.Close(); + switch( pid ) + { + case PluginId_GS: ClosePlugin_GS(); break; + case PluginId_PAD: ClosePlugin_PAD(); break; + case PluginId_CDVD: ClosePlugin_CDVD(); break; + case PluginId_SPU2: ClosePlugin_SPU2(); break; + case PluginId_USB: ClosePlugin_USB(); break; + case PluginId_FW: ClosePlugin_FW(); break; + case PluginId_DEV9: ClosePlugin_DEV9(); break; + + jNO_DEFAULT; + } m_info[pid].IsOpened = false; } @@ -1022,7 +1069,8 @@ void PluginManager::Close() { if( !NeedsClose() ) return; // Spam stopper; returns before writing any logs. >_< - // Close plugins in reverse order of the initialization procedure. + // Close plugins in reverse order of the initialization procedure, which + // ensures the GS gets closed last. DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." ); diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index abf82a021c..7257ae854d 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -339,6 +339,12 @@ protected: virtual bool OpenPlugin_FW(); virtual void ClosePlugin_GS(); + virtual void ClosePlugin_CDVD(); + virtual void ClosePlugin_PAD(); + virtual void ClosePlugin_SPU2(); + virtual void ClosePlugin_DEV9(); + virtual void ClosePlugin_USB(); + virtual void ClosePlugin_FW(); friend class SysMtgsThread; }; diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 8923d186ba..94fbbb7369 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -244,7 +244,7 @@ void SysCoreThread::_reset_stuff_as_needed() if( m_resetVirtualMachine ) { - cpuReset(); + DoCpuReset(); m_resetVirtualMachine = false; m_resetRecompilers = true; } @@ -259,6 +259,12 @@ void SysCoreThread::_reset_stuff_as_needed() SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR ); } +void SysCoreThread::DoCpuReset() +{ + AffinityAssert_AllowFromSelf( pxDiagSpot ); + cpuReset(); +} + void SysCoreThread::CpuInitializeMess() { if( m_hasValidState ) return; diff --git a/pcsx2/System/SysThreads.h b/pcsx2/System/SysThreads.h index 8d934659ea..b78208a8ea 100644 --- a/pcsx2/System/SysThreads.h +++ b/pcsx2/System/SysThreads.h @@ -220,6 +220,7 @@ protected: virtual void OnResumeInThread( bool IsSuspended ); virtual void OnCleanupInThread(); virtual void ExecuteTaskInThread(); + virtual void DoCpuReset(); void _StateCheckThrows(); }; diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 104cd512a9..6c7281efe8 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -57,6 +57,11 @@ static const int pxID_PadHandler_Keydown = 8030; // single for-loop to create them. static const int PluginMenuId_Interval = 0x10; +// Forces the Interface to destroy the GS viewport window when the GS plugin is +// destroyed. This has the side effect of forcing all plugins to close and re-open +// along with the GS, since the GS viewport window handle will have changed. +static const bool CloseViewportWithPlugins = false; + // ------------------------------------------------------------------------ // All Menu Options for the Main Window! :D // ------------------------------------------------------------------------ @@ -302,6 +307,31 @@ struct pxAppResources ~pxAppResources() throw() { } }; +// -------------------------------------------------------------------------------------- +// FramerateManager +// -------------------------------------------------------------------------------------- +class FramerateManager +{ +public: + static const uint FramerateQueueDepth = 64; + +protected: + u64 m_fpsqueue[FramerateQueueDepth]; + u64 m_fpsqueue_tally; + u64 m_ticks_lastframe; + int m_fpsqueue_writepos; + + uint m_FrameCounter; + +public: + virtual ~FramerateManager() throw() {} + + void Reset(); + void Resume(); + void DoFrame(); + double GetFramerate() const; +}; + // ===================================================================================================== // Pcsx2App - main wxApp class // ===================================================================================================== @@ -330,6 +360,7 @@ public: // ---------------------------------------------------------------------------- public: + FramerateManager FpsManager; CommandDictionary GlobalCommands; AcceleratorDictionary GlobalAccels; @@ -470,6 +501,7 @@ protected: enum CoreThreadStatus { CoreStatus_Indeterminate, + CoreStatus_Started, CoreStatus_Resumed, CoreStatus_Suspended, CoreStatus_Reset, @@ -494,13 +526,13 @@ public: protected: virtual void OnResumeReady(); - virtual void OnResumeInThread( bool IsSuspended ); virtual void OnSuspendInThread(); virtual void OnCleanupInThread(); //virtual void VsyncInThread(); virtual void PostVsyncToUI(); virtual void ExecuteTaskInThread(); + virtual void DoCpuReset(); }; DECLARE_APP(Pcsx2App) diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 799de5615e..4c91b8ba55 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -43,9 +43,7 @@ void AppCoreThread::Cancel( bool isBlocking ) void AppCoreThread::Reset() { ScopedBusyCursor::SetDefault( Cursor_KindaBusy ); - _parent::Reset(); - wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Reset ); } bool AppCoreThread::Suspend( bool isBlocking ) @@ -114,6 +112,12 @@ void AppCoreThread::ChangeCdvdSource( CDVD_SourceType type ) // TODO: Add a listener for CDVDsource changes? Or should we bother? } +void AppCoreThread::DoCpuReset() +{ + wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Reset ); + _parent::DoCpuReset(); +} + void AppCoreThread::OnResumeReady() { ApplySettings( g_Conf->EmuOptions ); @@ -185,6 +189,7 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src ) void AppCoreThread::ExecuteTaskInThread() { + wxGetApp().PostCommand( pxEvt_CoreThreadStatus, CoreStatus_Started ); _parent::ExecuteTaskInThread(); // ---------------------------------------------------------------------------- @@ -200,3 +205,4 @@ void AppCoreThread::ExecuteTaskInThread() } }*/ } + diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index de292c8aab..3e7f45ea91 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -197,7 +197,42 @@ void Pcsx2App::PadKeyDispatch( const keyEvent& ev ) } } -// OnLogicalVsync - Event received from the AppCoreThread (EEcore) for each vsync, +void FramerateManager::Reset() +{ + memzero( m_fpsqueue ); + m_fpsqueue_tally = 0; + m_fpsqueue_writepos = 0; + Resume(); +} + +// +void FramerateManager::Resume() +{ + m_ticks_lastframe = GetCPUTicks(); +} + +void FramerateManager::DoFrame() +{ + ++m_FrameCounter; + + u64 curtime = GetCPUTicks(); + u64 elapsed_time = curtime - m_ticks_lastframe; + m_ticks_lastframe = curtime; + + m_fpsqueue_tally += elapsed_time; + m_fpsqueue_tally -= m_fpsqueue[m_fpsqueue_writepos]; + + m_fpsqueue[m_fpsqueue_writepos] = elapsed_time; + m_fpsqueue_writepos = (m_fpsqueue_writepos + 1) % FramerateQueueDepth; +} + +double FramerateManager::GetFramerate() const +{ + u32 ticks_per_frame = m_fpsqueue_tally / FramerateQueueDepth; + return (double)GetTickFrequency() / (double)ticks_per_frame; +} + +// LogicalVsync - Event received from the AppCoreThread (EEcore) for each vsync, // roughly 50/60 times a second when frame limiting is enabled, and up to 10,000 // times a second if not (ok, not quite, but you get the idea... I hope.) void Pcsx2App::LogicalVsync() @@ -206,6 +241,10 @@ void Pcsx2App::LogicalVsync() if( !SysHasValidState() || g_plugins == NULL ) return; + // Update / Calculate framerate! + + FpsManager.DoFrame(); + // Only call PADupdate here if we're using GSopen2. Legacy GSopen plugins have the // GS window belonging to the MTGS thread. if( (PADupdate != NULL) && (GSopen2 != NULL) && (m_gsFrame != NULL) ) @@ -233,6 +272,22 @@ void Pcsx2App::LogicalVsync() // polling of the CoreThread rather than the belated status. void Pcsx2App::OnCoreThreadStatus( wxCommandEvent& evt ) { + CoreThreadStatus status = (CoreThreadStatus)evt.GetInt(); + + switch( status ) + { + case CoreStatus_Started: + case CoreStatus_Reset: + case CoreStatus_Stopped: + FpsManager.Reset(); + break; + + case CoreStatus_Resumed: + case CoreStatus_Suspended: + FpsManager.Resume(); + break; + } + // Clear the sticky key statuses, because hell knows what'll change while the PAD // plugin is suspended. @@ -421,8 +476,10 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& if( result == pxID_CUSTOM ) { - // fastest way to kill the process! - // (note: SIGTERM is a "handled" kill that performs shutdown stuff, which typically juse crashes anyway) + // fastest way to kill the process! (works in Linux and win32, thanks to windows having very + // limited Posix Signals support) + // + // (note: SIGTERM is a "handled" kill that performs shutdown stuff, which typically just crashes anyway) wxKill( wxGetProcessId(), wxSIGKILL ); } else if( result == wxID_CANCEL ) @@ -654,9 +711,9 @@ void Pcsx2App::CloseGsPanel() { if( SelfMethodInvoke( &Pcsx2App::CloseGsPanel ) ) return; - if( m_gsFrame != NULL ) + if( m_gsFrame != NULL && CloseViewportWithPlugins ) { - if( GSPanel* woot = (GSPanel*)m_gsFrame->FindWindowByName(L"GSPanel") ) + if( GSPanel* woot = m_gsFrame->GetViewport() ) woot->Destroy(); } } @@ -820,7 +877,7 @@ bool HasMainFrame() // frame has been closed). In most cases you'll want to use HasMainFrame() to test // for gui validity first, or use GetMainFramePtr() and manually check for NULL (choice // is a matter of programmer preference). -MainEmuFrame& GetMainFrame() +MainEmuFrame& GetMainFrame() { return wxGetApp().GetMainFrame(); } @@ -828,7 +885,7 @@ MainEmuFrame& GetMainFrame() // Returns a pointer to the main frame of the GUI (frame may be hidden from view), or // NULL if no main frame exists (NoGUI mode and/or the frame has been destroyed). If // the wxApp is NULL then this will also return NULL. -MainEmuFrame* GetMainFramePtr() +MainEmuFrame* GetMainFramePtr() { return wxTheApp ? wxGetApp().GetMainFramePtr() : NULL; } diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 1827ae0ff4..87e5c831e3 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -20,7 +20,6 @@ #include - void GSPanel::InitDefaultAccelerators() { typedef KeyAcceleratorCode AAC; @@ -73,6 +72,11 @@ GSPanel::GSPanel( wxWindow* parent ) Connect(wxEVT_SET_FOCUS, wxFocusEventHandler (GSPanel::OnFocus)); Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler (GSPanel::OnFocusLost)); + Connect(m_HideMouseTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(GSPanel::OnHideMouseTimeout) ); + + // Any and all events which should result in the mouse cursor being made visible + // are connected here. If I missed one, feel free to add it in! --air + Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler (GSPanel::OnShowMouse)); Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler (GSPanel::OnShowMouse)); Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler (GSPanel::OnShowMouse)); @@ -82,8 +86,6 @@ GSPanel::GSPanel( wxWindow* parent ) Connect(wxEVT_MIDDLE_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse)); Connect(wxEVT_RIGHT_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse)); Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (GSPanel::OnShowMouse)); - - Connect(m_HideMouseTimer.GetId(), wxEVT_TIMER, wxTimerEventHandler(GSPanel::OnHideMouseTimeout) ); } GSPanel::~GSPanel() throw() @@ -226,7 +228,7 @@ void GSPanel::DoSettingsApplied() } // -------------------------------------------------------------------------------------- -// GSFrame +// GSFrame Implementation // -------------------------------------------------------------------------------------- GSFrame::GSFrame(wxWindow* parent, const wxString& title) @@ -236,6 +238,7 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title) wxSYSTEM_MENU | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX ) , m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener ( this, OnSettingsApplied ) ) + , m_timer_UpdateTitle( this ) { SetIcons( wxGetApp().GetIconBundle() ); @@ -248,13 +251,16 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title) label->SetForegroundColour( *wxWHITE ); label->Show( EmuConfig.GS.DisableOutput ); - m_gspanel = new GSPanel( this ); // TODO : give this an id instead of using FindByName - m_gspanel->Show( !EmuConfig.GS.DisableOutput ); + GSPanel* gsPanel = new GSPanel( this ); + gsPanel->Show( !EmuConfig.GS.DisableOutput ); + m_gspanel_id = gsPanel->GetId(); //Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSFrame::OnCloseWindow) ); Connect( wxEVT_MOVE, wxMoveEventHandler (GSFrame::OnMove) ); Connect( wxEVT_SIZE, wxSizeEventHandler (GSFrame::OnResize) ); Connect( wxEVT_ACTIVATE, wxActivateEventHandler (GSFrame::OnActivate) ); + + Connect(m_timer_UpdateTitle.GetId(), wxEVT_TIMER, wxTimerEventHandler(GSFrame::OnUpdateTitle) ); } GSFrame::~GSFrame() throw() @@ -266,14 +272,23 @@ bool GSFrame::Show( bool shown ) { if( shown ) { - if( FindWindowByName(L"GSPanel") == NULL ) + GSPanel* gsPanel = GetViewport(); + + if( gsPanel == NULL || gsPanel->IsBeingDeleted() ) { - m_gspanel = new GSPanel( this ); - m_gspanel->Show( !EmuConfig.GS.DisableOutput ); + gsPanel = new GSPanel( this ); + m_gspanel_id = gsPanel->GetId(); } - m_gspanel->DoResize(); - m_gspanel->SetFocus(); + gsPanel->Show( !EmuConfig.GS.DisableOutput ); + gsPanel->DoResize(); + gsPanel->SetFocus(); + + m_timer_UpdateTitle.Start( 333 ); + } + else + { + m_timer_UpdateTitle.Stop(); } return _parent::Show( shown ); @@ -297,9 +312,35 @@ void GSFrame::DoSettingsApplied() label->Show( !EmuConfig.GS.DisableOutput ); } -wxWindow* GSFrame::GetViewport() +GSPanel* GSFrame::GetViewport() { - return FindWindowByName(L"GSPanel"); + return (GSPanel*)FindWindowById( m_gspanel_id ); +} + +void GSFrame::OnUpdateTitle( wxTimerEvent& evt ) +{ + double fps = wxGetApp().FpsManager.GetFramerate(); + + char gsDest[128]; + GSgetTitleInfo( gsDest ); + + const wxChar* limiterStr = L"None"; + + if( g_Conf->EmuOptions.GS.FrameLimitEnable ) + { + switch( g_LimiterMode ) + { + case Limit_Nominal: limiterStr = L"Normal"; break; + case Limit_Turbo: limiterStr = L"Turbo"; break; + case Limit_Slomo: limiterStr = L"Slomo"; break; + } + } + + SetTitle( wxsFormat( L"%s | Limiter: %s | fps: %2.02f", + fromUTF8(gsDest).c_str(), limiterStr, fps ) + ); + + //States_GetCurrentSlot() } void GSFrame::OnActivate( wxActivateEvent& evt ) @@ -307,7 +348,7 @@ void GSFrame::OnActivate( wxActivateEvent& evt ) if( IsBeingDeleted() ) return; evt.Skip(); - if( wxWindow* gsPanel = FindWindowByName(L"GSPanel") ) gsPanel->SetFocus(); + if( wxWindow* gsPanel = GetViewport() ) gsPanel->SetFocus(); } void GSFrame::OnMove( wxMoveEvent& evt ) @@ -341,7 +382,7 @@ void GSFrame::OnResize( wxSizeEvent& evt ) if( wxStaticText* label = (wxStaticText*)FindWindowByName(L"OutputDisabledLabel") ) label->CentreOnParent(); - if( GSPanel* gsPanel = (GSPanel*)FindWindowByName(L"GSPanel") ) + if( GSPanel* gsPanel = GetViewport() ) { gsPanel->DoResize(); gsPanel->SetFocus(); diff --git a/pcsx2/gui/GlobalCommands.cpp b/pcsx2/gui/GlobalCommands.cpp index eb2b14f0ea..c7427818d5 100644 --- a/pcsx2/gui/GlobalCommands.cpp +++ b/pcsx2/gui/GlobalCommands.cpp @@ -53,14 +53,7 @@ wxString KeyAcceleratorCode::ToString() const ).ToString(); } -enum LimiterModeType -{ - Limit_Nominal, - Limit_Turbo, - Limit_Slomo, -}; - -static LimiterModeType g_LimiterMode = Limit_Nominal; +LimiterModeType g_LimiterMode = Limit_Nominal; namespace Implementations { diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h index 220b09acb7..7a72e697cb 100644 --- a/pcsx2/gui/MainFrame.h +++ b/pcsx2/gui/MainFrame.h @@ -21,6 +21,15 @@ #include "App.h" +enum LimiterModeType +{ + Limit_Nominal, + Limit_Turbo, + Limit_Slomo, +}; + +extern LimiterModeType g_LimiterMode; + // -------------------------------------------------------------------------------------- // GSPanel // -------------------------------------------------------------------------------------- @@ -71,14 +80,15 @@ class GSFrame : public wxFrame protected: EventListenerBinding m_Listener_SettingsApplied; - GSPanel* m_gspanel; + wxTimer m_timer_UpdateTitle; + wxWindowID m_gspanel_id; wxStaticText* m_label_Disabled; public: GSFrame(wxWindow* parent, const wxString& title); virtual ~GSFrame() throw(); - wxWindow* GetViewport(); + GSPanel* GetViewport(); bool Show( bool shown=true ); @@ -86,6 +96,7 @@ protected: void OnMove( wxMoveEvent& evt ); void OnResize( wxSizeEvent& evt ); void OnActivate( wxActivateEvent& evt ); + void OnUpdateTitle( wxTimerEvent& evt ); void DoSettingsApplied(); diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index 737c990d5f..6e85b0f676 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -174,6 +174,7 @@ void MainEmuFrame::Menu_IsoBrowse_Click( wxCommandEvent &event ) // (useful for disc swapping) SysUpdateIsoSrcFile( result ); + AppSaveSettings(); } core.Resume(); diff --git a/pcsx2/gui/Plugins.cpp b/pcsx2/gui/Plugins.cpp index 17e2beca3c..38f64ebe97 100644 --- a/pcsx2/gui/Plugins.cpp +++ b/pcsx2/gui/Plugins.cpp @@ -86,6 +86,7 @@ public: sApp.PostPluginStatus( PluginsEvt_Opened ); } + // Yay, this plugin is guaranteed to always be opened first and closed last. bool OpenPlugin_GS() { if( GSopen2 != NULL ) @@ -96,8 +97,20 @@ public: return _parent::OpenPlugin_GS(); } + // Yay, this plugin is guaranteed to always be opened first and closed last. void ClosePlugin_GS() { + if( GSopen2 == NULL || CloseViewportWithPlugins ) + { + // All other plugins must be closed before the GS, because they all rely on + // the GS window handle being valid. The recursion guard will protect this + // function from being called a million times. ;) + + static int _guard; + RecursionGuard mess( _guard ); + if( !mess.IsReentrant() ) Close(); + } + _parent::ClosePlugin_GS(); sApp.CloseGsPanel(); } @@ -110,6 +123,7 @@ public: void Close( PluginsEnum_t pid ) { + _parent::Close( pid ); }*/ };