From 24d6221141aa28e51c823031ad7c6f2668fc18ce Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Mon, 2 Nov 2009 19:56:38 +0000 Subject: [PATCH] * More MXCSR fixes (roundmode / DaZ / FtZ). * Fixed a bug in the Full-mode FPU recompiler. * Added some better error handling to the BIOS Rom loader. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2117 96395faa-99c1-11dd-bbfe-3dabce05a288 --- .../implement/simd_templated_helpers.h | 7 ++- pcsx2/System/SysCoreThread.cpp | 16 ++++--- pcsx2/System/SysThreads.h | 3 ++ pcsx2/gui/AppCoreThread.cpp | 45 +++-------------- pcsx2/gui/AppMain.cpp | 34 +++++++++++++ pcsx2/gui/Dialogs/ConfigurationDialog.cpp | 2 +- pcsx2/gui/Dialogs/ModalPopups.h | 2 + pcsx2/ps2/BiosTools.cpp | 48 +++++++++++-------- pcsx2/ps2/BiosTools.h | 14 +++++- pcsx2/x86/iFPUd.cpp | 12 +++-- pcsx2/x86/iMisc.cpp | 7 +-- pcsx2/x86/ix86-32/iR5900-32.cpp | 3 -- 12 files changed, 111 insertions(+), 82 deletions(-) diff --git a/common/include/x86emitter/implement/simd_templated_helpers.h b/common/include/x86emitter/implement/simd_templated_helpers.h index 65e6bd581d..7abd4112ed 100644 --- a/common/include/x86emitter/implement/simd_templated_helpers.h +++ b/common/include/x86emitter/implement/simd_templated_helpers.h @@ -27,7 +27,12 @@ class SimdImpl_DestRegSSE { public: __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } - __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const + { + bool isReallyAligned = ((from.Displacement & 0x0f) == 0) && from.Index.IsEmpty() && from.Base.IsEmpty(); + pxAssertDev( isReallyAligned, "Alignment check failed on SSE indirect load." ); + xOpWrite0F( Prefix, Opcode, to, from ); + } SimdImpl_DestRegSSE() {} //GCWho? }; diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index 7530b06413..62e2bd6311 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -21,18 +21,15 @@ #include "SysThreads.h" #include "SaveState.h" -#include "Elfheader.h" -#include "Plugins.h" -#include "R5900.h" -#include "R3000A.h" #include "VUmicro.h" - #include "GS.h" #ifdef __WXMSW__ # include #endif +#include + static __threadlocal SysCoreThread* tls_coreThread = NULL; // -------------------------------------------------------------------------------------- @@ -203,6 +200,7 @@ void SysCoreThread::CpuInitializeMess() // fast bott up option. (though not recommended for games because of rare ill side // effects). + SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR ); cpuExecuteBios(); loadElfFile( elf_file ); } @@ -229,12 +227,14 @@ void SysCoreThread::StateCheckInThread() void SysCoreThread::ExecuteTaskInThread() { Threading::EnableHiresScheduler(); - tls_coreThread = this; - m_sem_event.WaitWithoutYield(); + + m_mxcsr_saved.bitmask = _mm_getcsr(); + PCSX2_PAGEFAULT_PROTECT { StateCheckInThread(); + SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR ); Cpu->Execute(); } PCSX2_PAGEFAULT_EXCEPT; } @@ -260,6 +260,8 @@ void SysCoreThread::OnCleanupInThread() { m_hasValidState = false; + _mm_setcsr( m_mxcsr_saved.bitmask ); + Threading::DisableHiresScheduler(); if( g_plugins != NULL ) diff --git a/pcsx2/System/SysThreads.h b/pcsx2/System/SysThreads.h index ae30fef9d3..44e9625317 100644 --- a/pcsx2/System/SysThreads.h +++ b/pcsx2/System/SysThreads.h @@ -16,6 +16,7 @@ #pragma once #include "Utilities/Threading.h" +#include "x86emitter/tools.h" using namespace Threading; @@ -194,6 +195,8 @@ protected: bool m_CoreCancelDamnit; wxString m_elf_override; + + SSE_MXCSR m_mxcsr_saved; public: static SysCoreThread& Get(); diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 4c921687ce..b5d6b4bea7 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -15,6 +15,7 @@ #include "PrecompiledHeader.h" #include "MainFrame.h" +#include "ps2/BiosTools.h" AppCoreThread CoreThread; @@ -191,52 +192,18 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src ) void AppCoreThread::ExecuteTaskInThread() { - try - { - SysCoreThread::ExecuteTaskInThread(); - } - // ---------------------------------------------------------------------------- - catch( Exception::FileNotFound& ex ) - { - if( g_plugins != NULL ) g_plugins->Close(); - if( ex.StreamName == g_Conf->FullpathToBios() ) - { - bool result = Msgbox::OkCancel( ex.FormatDisplayMessage() + - _("\n\nPress Ok to go to the BIOS Configuration Panel.") ); + _parent::ExecuteTaskInThread(); - if( result ) - { - if( wxGetApp().ThreadedModalDialog( DialogId_BiosSelector ) == wxID_CANCEL ) - { - // fixme: handle case where user cancels the settings dialog. (should return FALSE). - } - else - { - // fixme: automatically re-try emu startup here... - } - } - } - } // ---------------------------------------------------------------------------- - catch( Exception::PluginError& ex ) + /*catch( Exception::PluginError& ex ) { if( g_plugins != NULL ) g_plugins->Close(); Console.Error( ex.FormatDiagnosticMessage() ); Msgbox::Alert( ex.FormatDisplayMessage(), _("Plugin Open Error") ); - /*if( HandlePluginError( ex ) ) + if( HandlePluginError( ex ) ) { // fixme: automatically re-try emu startup here... - }*/ - } - // ---------------------------------------------------------------------------- - // [TODO] : Add exception handling here for debuggable PS2 exceptions that allows - // invocation of the PCSX2 debugger and such. - // - catch( Exception::BaseException& ex ) - { - // Sent the exception back to the main gui thread? - if( g_plugins != NULL ) g_plugins->Close(); - Msgbox::Alert( ex.FormatDisplayMessage() ); - } + } + }*/ } diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index e74aea286a..6f845e7dc9 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -18,6 +18,7 @@ #include "MainFrame.h" #include "Plugins.h" #include "SaveState.h" +#include "ps2/BiosTools.h" #include "Dialogs/ModalPopups.h" #include "Dialogs/ConfigurationDialog.h" @@ -139,6 +140,7 @@ void Pcsx2App::OnCoreThreadStatus( wxCommandEvent& evt ) { m_evtsrc_CoreThreadStatus.Dispatch( evt ); ScopedBusyCursor::SetDefault( Cursor_NotBusy ); + CoreThread.RethrowException(); } void Pcsx2App::OnSemaphorePing( wxCommandEvent& evt ) @@ -218,12 +220,44 @@ void Pcsx2App::OnEmuKeyDown( wxKeyEvent& evt ) } +// Returns a string message telling the user to consult guides for obtaining a legal BIOS. +// This message is in a function because it's used as part of several dialogs in PCSX2 (there +// are multiple variations on the BIOS and BIOS folder checks). +wxString BIOS_GetMsg_Required() +{ + return pxE( ".Popup:BiosDumpRequired", + L"\n\n" + L"PCSX2 requires a PS2 BIOS in order to run. For legal reasons, you *must* obtain \n" + L"a BIOS from an actual PS2 unit that you own (borrowing doesn't count).\n" + L"Please consult the FAQs and Guides for further instructions.\n" + ); +} + + void Pcsx2App::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const { try { (handler->*func)(event); } // ---------------------------------------------------------------------------- + catch( Exception::BiosLoadFailed& ex ) + { + bool result = Dialogs::ExtensibleConfirmation( NULL, ConfButtons().OK().Cancel(), + L"PS2 BIOS Error", + ex.FormatDisplayMessage() + BIOS_GetMsg_Required() + _("\nPress Ok to go to the BIOS Configuration Panel.") + ).ShowModal() != wxID_CANCEL; + + if( !result ) + Console.Warning( "User denied option to re-configure BIOS." ); + + if( (wxTheApp != NULL) && (Dialogs::BiosSelectorDialog().ShowModal() != wxID_CANCEL) ) + { + sApp.SysExecute(); + } + else + Console.Warning( "User canceled BIOS configuration." ); + } + // ---------------------------------------------------------------------------- catch( Exception::CancelEvent& ex ) { Console.Warning( ex.FormatDiagnosticMessage() ); diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.cpp b/pcsx2/gui/Dialogs/ConfigurationDialog.cpp index cc73b9fc08..59e9dd9b24 100644 --- a/pcsx2/gui/Dialogs/ConfigurationDialog.cpp +++ b/pcsx2/gui/Dialogs/ConfigurationDialog.cpp @@ -40,7 +40,7 @@ using namespace Panels; static const int s_orient = wxBK_LEFT; #endif -static const int IdealWidth = 500; +static const int IdealWidth = 575; template< typename T > void Dialogs::ConfigurationDialog::AddPage( const char* label, int iconid ) diff --git a/pcsx2/gui/Dialogs/ModalPopups.h b/pcsx2/gui/Dialogs/ModalPopups.h index 96bb1346c5..76a6a7703c 100644 --- a/pcsx2/gui/Dialogs/ModalPopups.h +++ b/pcsx2/gui/Dialogs/ModalPopups.h @@ -93,6 +93,8 @@ public: ConfButtons& Abort() { m_Abort = true; return *this; } ConfButtons& Retry() { m_Retry = true; return *this; } ConfButtons& Ignore() { m_Ignore = true; return *this; } + + ConfButtons& OKCancel() { m_OK = m_Cancel = true; return *this; } bool HasOK() const { return m_OK; } bool HasCancel() const { return m_Cancel; } diff --git a/pcsx2/ps2/BiosTools.cpp b/pcsx2/ps2/BiosTools.cpp index 960aa2c25f..360395ace6 100644 --- a/pcsx2/ps2/BiosTools.cpp +++ b/pcsx2/ps2/BiosTools.cpp @@ -44,16 +44,17 @@ struct romdir u32 BiosVersion; // Used in Memory, Misc, CDVD -// Returns a string message telling the user to consult guides for obtaining a legal BIOS. -// This message is in a function because it's used as part of several dialogs in PCSX2 (there -// are multiple variations on the BIOS and BIOS folder checks). -wxString BIOS_GetMsg_Required() +Exception::BiosLoadFailed::BiosLoadFailed( const wxString& filename, const wxString& msg_diag, const wxString& msg_user ) { - return pxE( ".Popup:BiosDumpRequired", - L"PCSX2 requires a PS2 BIOS in order to run. For legal reasons, you *must* obtain \n" - L"a BIOS from an actual PS2 unit that you own (borrowing doesn't count).\n" - L"Please consult the FAQs and Guides for further instructions." + wxString diag( msg_user.IsEmpty() ? + L"BIOS has not been configured, or the configuration has been corrupted." : msg_user ); + wxString user( msg_user.IsEmpty() ? + _("The PS2 BIOS has not been configured, or the configuration has been corrupted. Please re-configure.") : msg_user + ); + + BaseException::InitBaseEx( diag, user ); + StreamName = filename; } // Returns the version information of the bios currently loaded into memory. @@ -146,27 +147,32 @@ static void loadBiosRom( const wxChar *ext, u8 *dest, s64 maxSize ) void LoadBIOS() { pxAssertDev( PS2MEM_ROM != NULL, "PS2 system memory has not been initialized yet." ); - + wxString Bios( g_Conf->FullpathToBios() ); + if( !g_Conf->BaseFilenames.Bios.IsOk() || g_Conf->BaseFilenames.Bios.IsDir() ) + throw Exception::BiosLoadFailed( Bios ); s64 filesize = Path::GetFileSize( Bios ); - if( filesize > 0 ) + if( filesize <= 0 ) { - wxFile fp( Bios.c_str() ); - fp.Read( PS2MEM_ROM, min( (s64)Ps2MemSize::Rom, filesize ) ); - } - else - { - // Translated: Bios file not found or not specified ... A bios is required for Pcsx2 to run! - throw Exception::FileNotFound( Bios, - L"Configured Bios file does not exist", - - _("The configured BIOS file does not exist, or no BIOS has been configured.\n\n") + - BIOS_GetMsg_Required() + throw Exception::BiosLoadFailed( Bios, + L"Configured BIOS file does not exist.", + _("The configured BIOS file does not exist. Please re-configure.") ); } + wxFile fp( Bios ); + fp.Read( PS2MEM_ROM, min( (s64)Ps2MemSize::Rom, filesize ) ); + BiosVersion = GetBiosVersion(); + if( BiosVersion == -1 ) + { + throw Exception::BiosLoadFailed( Bios, + L"Configured BIOS file is not a valid PS2 BIOS.", + _("The configured BIOS file is not a valid PS2 BIOS. Please re-configure.") + ); + } + Console.WriteLn("Bios Version %d.%d", BiosVersion >> 8, BiosVersion & 0xff); //injectIRX("host.irx"); //not fully tested; still buggy diff --git a/pcsx2/ps2/BiosTools.h b/pcsx2/ps2/BiosTools.h index 9599ae4fd5..3d951d018c 100644 --- a/pcsx2/ps2/BiosTools.h +++ b/pcsx2/ps2/BiosTools.h @@ -15,8 +15,20 @@ #pragma once +namespace Exception +{ + class BiosLoadFailed : public FileNotFound + { + public: + DEFINE_EXCEPTION_COPYTORS( BiosLoadFailed ) + + explicit BiosLoadFailed( const wxString& filename, + const wxString& msg_diag=wxEmptyString, + const wxString& msg_user=wxEmptyString ); + }; +} + extern u32 BiosVersion; // Used by CDVD -extern wxString BIOS_GetMsg_Required(); extern void LoadBIOS(); extern bool IsBIOS(const wxString& filename, wxString& description); diff --git a/pcsx2/x86/iFPUd.cpp b/pcsx2/x86/iFPUd.cpp index 90cd7d4c5b..ba934dcbd3 100644 --- a/pcsx2/x86/iFPUd.cpp +++ b/pcsx2/x86/iFPUd.cpp @@ -116,7 +116,9 @@ struct FPUd_Globals u64 dbl_cvt_overflow, // needs special code if above or equal dbl_ps2_overflow, // overflow & clamp if above or equal dbl_underflow; // underflow if below - + + u64 padding; + u64 dbl_s_pos[2]; //u64 dlb_s_neg[2]; }; @@ -132,9 +134,11 @@ static const __aligned(32) FPUd_Globals s_const = {DOUBLE(0,1,0), 0}, - DOUBLE(0,1151,0), - DOUBLE(0,1152,0), - DOUBLE(0,897,0), + DOUBLE(0,1151,0), // cvt_overflow + DOUBLE(0,1152,0), // ps2_overflow + DOUBLE(0,897,0), // underflow + + 0, // Padding!! {0x7fffffffffffffffULL, 0}, //{0x8000000000000000ULL, 0}, diff --git a/pcsx2/x86/iMisc.cpp b/pcsx2/x86/iMisc.cpp index 44c1b02247..ee2cff4a70 100644 --- a/pcsx2/x86/iMisc.cpp +++ b/pcsx2/x86/iMisc.cpp @@ -15,6 +15,7 @@ #include "PrecompiledHeader.h" +#include SSE_MXCSR g_sseMXCSR = { DEFAULT_sseMXCSR }; SSE_MXCSR g_sseVUMXCSR = { DEFAULT_sseVUMXCSR }; @@ -29,10 +30,6 @@ void SetCPUState(SSE_MXCSR sseMXCSR, SSE_MXCSR sseVUMXCSR) g_sseMXCSR = sseMXCSR.ApplyReserveMask(); g_sseVUMXCSR = sseVUMXCSR.ApplyReserveMask(); -#ifdef _MSC_VER - __asm ldmxcsr g_sseMXCSR; // set the new sse control -#else - __asm__ __volatile__("ldmxcsr %[g_sseMXCSR]" : : [g_sseMXCSR]"m"(g_sseMXCSR) ); -#endif + _mm_setcsr( g_sseMXCSR.bitmask ); } diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index cb1da488ff..b2b805a3b1 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -688,13 +688,11 @@ static void recExecute() { eeRecIsReset = false; g_EEFreezeRegs = true; - SetCPUState(g_sseMXCSR, g_sseVUMXCSR); try { EnterRecompiledCode(); } catch( Exception::ForceDispatcherReg& ) { } - } } catch( Exception::ExitRecExecute& ) {} @@ -719,7 +717,6 @@ static void recExecute() pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate ); eeRecIsReset = false; - SetCPUState(g_sseMXCSR, g_sseVUMXCSR); #ifdef _WIN32 __try {