diff --git a/common/include/Pcsx2Config.h b/common/include/Pcsx2Config.h deleted file mode 100644 index ac8c45b37b..0000000000 --- a/common/include/Pcsx2Config.h +++ /dev/null @@ -1,223 +0,0 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2009 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __PCSX2CONFIG_H__ -#define __PCSX2CONFIG_H__ - -// Hack so that you can still use this file from C (not C++), or from a plugin without access to Paths.h. -// .. and removed in favor of a less hackish approach (air) - -#ifndef g_MaxPath -#define g_MaxPath 255 -#endif - -///////////////////////////////////////////////////////////////////////// -// Session Configuration Override Flags -// -// a handful of flags that can override user configurations for the current application session -// only. This allows us to do things like force-disable recompilers if the memory allocations -// for them fail. -struct SessionOverrideFlags -{ - bool ForceDisableEErec:1; - bool ForceDisableVU0rec:1; - bool ForceDisableVU1rec:1; -}; - -extern SessionOverrideFlags g_Session; - -////////////////////////////////////////////////////////////////////////// -// Pcsx2 User Configuration Options! - -#define PCSX2_EEREC 0x0010 -#define PCSX2_VU0REC 0x0020 -#define PCSX2_VU1REC 0x0040 -#define PCSX2_FRAMELIMIT_MASK 0x0c00 -#define PCSX2_FRAMELIMIT_NORMAL 0x0000 -#define PCSX2_FRAMELIMIT_LIMIT 0x0400 -#define PCSX2_FRAMELIMIT_SKIP 0x0800 -#define PCSX2_MICROVU0 0x1000 // Use Micro VU0 recs instead of Zero VU0 Recs -#define PCSX2_MICROVU1 0x2000 // Use Micro VU1 recs instead of Zero VU1 Recs - -#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK) - -//------------ CPU Options!!! --------------- -#define CHECK_MICROVU0 (Config.Options&PCSX2_MICROVU0) -#define CHECK_MICROVU1 (Config.Options&PCSX2_MICROVU1) -#define CHECK_MACROVU0 // ifndef = Use sVU for VU macro, ifdef = Use mVU for VU macro -#define CHECK_EEREC (!g_Session.ForceDisableEErec && Config.Options&PCSX2_EEREC) -#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC) -#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC)) - -//------------ SPECIAL GAME FIXES!!! --------------- -#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x01) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. -#define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x04) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu. -#define CHECK_VUCLIPFLAGHACK (Config.GameFixes & 0x02) // Special Fix for Persona games, maybe others. It's to do with the VU clip flag (again). -#define CHECK_FPUMULHACK (Config.GameFixes & 0x08) // Special Fix for Tales of Destiny hangs. -#define CHECK_DMAEXECHACK (Config.GameFixes & 0x10) // Special Fix for Fatal Frame; breaks Gust and Tri-Ace games. -#define CHECK_XGKICKHACK (Config.GameFixes & 0x20) // Special Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics. - -//------------ Advanced Options!!! --------------- -#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1) -#define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs -#define CHECK_VU_SIGN_OVERFLOW (Config.vuOptions & 0x4) -#define CHECK_VU_UNDERFLOW (Config.vuOptions & 0x8) -#define CHECK_VU_EXTRA_FLAGS 0 // Always disabled now // Sets correct flags in the VU recs -#define CHECK_FPU_OVERFLOW (Config.eeOptions & 0x1) -#define CHECK_FPU_EXTRA_OVERFLOW (Config.eeOptions & 0x2) // If enabled, Operands are checked for infinities before being used in the FPU recs -#define CHECK_FPU_EXTRA_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions -#define CHECK_FPU_FULL (Config.eeOptions & 0x4) -#define DEFAULT_eeOptions 0x01 -#define DEFAULT_vuOptions 0x01 - -//------------ DEFAULT sseMXCSR VALUES!!! --------------- -#define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop" -#define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop" - -//------------ Recompiler defines - Comment to disable a recompiler --------------- -// Yay! These work now! (air) ... almost (air) - -#define SHIFT_RECOMPILE // Speed majorly reduced if disabled -#define BRANCH_RECOMPILE // Speed extremely reduced if disabled - more then shift - -// Disabling all the recompilers in this block is interesting, as it still runs at a reasonable rate. -// It also adds a few glitches. Really reminds me of the old Linux 64-bit version. --arcum42 -#define ARITHMETICIMM_RECOMPILE -#define ARITHMETIC_RECOMPILE -#define MULTDIV_RECOMPILE -#define JUMP_RECOMPILE -#define LOADSTORE_RECOMPILE -#define MOVE_RECOMPILE -#define MMI_RECOMPILE -#define MMI0_RECOMPILE -#define MMI1_RECOMPILE -#define MMI2_RECOMPILE -#define MMI3_RECOMPILE -#define FPU_RECOMPILE -#define CP0_RECOMPILE -#define CP2_RECOMPILE - -// You can't recompile ARITHMETICIMM without ARITHMETIC. -#ifndef ARITHMETIC_RECOMPILE -#undef ARITHMETICIMM_RECOMPILE -#endif - -#define EE_CONST_PROP // rec2 - enables constant propagation (faster) - -// These are broken, so don't enable. -//#define PCSX2_CACHE_EMU_MEM -//#define ENABLECACHE - -// Memory Card configuration, per slot. -struct McdConfig -{ - // filename of the memory card for this slot. - // If the string is empty characters long then the default is used. - char Filename[g_MaxPath]; - - // Enables the memory card at the emulation level. When false, games will treat this - // slot as if the memory card has been physically removed from the PS2. - bool Enabled; -}; - -struct PluginNames -{ - char GS[g_MaxPath]; - char PAD1[g_MaxPath]; - char PAD2[g_MaxPath]; - char SPU2[g_MaxPath]; - char CDVD[g_MaxPath]; - char DEV9[g_MaxPath]; - char USB[g_MaxPath]; - char FW[g_MaxPath]; -}; - -// This is intended to be where all the main paths for Pcsx2 are. -// This may end up being moved to Paths.h. It may also be converted to strings. -struct FilePaths -{ - string Working; - char Plugins[g_MaxPath]; - char Bios[g_MaxPath]; - - // These are mainly placeholders for later. - string Isos; - string Dumps; - - // This is intended for the program to populate, and the plugins to read. - // Obviously can't be saved in the config file. :) - string Inis; -}; - -struct Hacks_t -{ - int EECycleRate; - bool IOPCycleDouble; - //bool WaitCycleExt; - bool INTCSTATSlow; - bool IdleLoopFF; - int VUCycleSteal; - bool vuFlagHack; - bool vuMinMax; - bool ESCExits; // this is a hack!? -}; - -struct PcsxConfig -{ -public: - // The Bios name isn't really a plugin name, so doesn't go with the Plugins. - char Bios[g_MaxPath]; - - PluginNames Plugins; - FilePaths Paths; - - char Lang[g_MaxPath]; - - McdConfig Mcd[2]; - - bool McdEnableNTFS; // enables NTFS compression on cards and the mcd folder. - bool McdEnableEject; // enables auto-ejection of cards after loading savestates. - - u32 Options; // PCSX2_X options - - bool PsxOut; - bool Profiler; // Displays profiling info to console - bool cdvdPrint; // Prints cdvd reads to console - bool closeGSonEsc; // closes the GS (and saves its state) on escape automatically. - - int PsxType; - int Patch; - int CustomFps; - - Hacks_t Hacks; - - int GameFixes; - int CustomFrameSkip; - int CustomConsecutiveFrames; - int CustomConsecutiveSkip; - u32 sseMXCSR; - u32 sseVUMXCSR; - u32 eeOptions; - u32 vuOptions; - - int Blockdump; -}; - -extern PcsxConfig Config; - -#endif // __PCSX2CONFIG_H__ diff --git a/common/include/Utilities/Threading.h b/common/include/Utilities/Threading.h index 2ce51764ca..adc0ae0e67 100644 --- a/common/include/Utilities/Threading.h +++ b/common/include/Utilities/Threading.h @@ -72,9 +72,10 @@ namespace Threading #if wxUSE_GUI void WaitGui(); + bool WaitGui( const wxTimeSpan& timeout ); #endif void Wait(); - void Wait( const wxTimeSpan& timeout ); + bool Wait( const wxTimeSpan& timeout ); void WaitNoCancel(); int Count(); }; @@ -125,6 +126,7 @@ namespace Threading typedef int (*PlainJoeFP)(); pthread_t m_thread; Semaphore m_sem_event; // general wait event that's needed by most threads. + Semaphore m_sem_finished; // used for canceling and closing threads in a deadlock-safe manner sptr m_returncode; // value returned from the thread on close. volatile long m_detached; // a boolean value which indicates if the m_thread handle is valid diff --git a/common/include/wx/folderdesc.txt b/common/include/wx/folderdesc.txt index 9988adbdcd..445d474d78 100644 --- a/common/include/wx/folderdesc.txt +++ b/common/include/wx/folderdesc.txt @@ -1,13 +1,13 @@ -------------------------------------------------- - include/wx folder -- PCSX2 Common Includes -------------------------------------------------- - -This folder contains various classes borrowed from wxWidgets 2.9.x / 3.0. - -/Common/include is a PCSX2 project default include search path, and with the /wx -folder prefix, these files can be included the same way as other wxWidgets includes: - -#include - -If/when PCSX2 upgrades to wx2.9/3.0 these files will be removed and the wxWidgets -distribution files will automatically be used instead. +------------------------------------------------- + include/wx folder -- PCSX2 Common Includes +------------------------------------------------- + +This folder contains various classes borrowed from wxWidgets 2.9.x / 3.0. + +/Common/include is a PCSX2 project default include search path, and with the /wx +folder prefix, these files can be included the same way as other wxWidgets includes: + +#include + +If/when PCSX2 upgrades to wx2.9/3.0 these files will be removed and the wxWidgets +distribution files will automatically be used instead. diff --git a/common/include/x86emitter/inlines.inl b/common/include/x86emitter/inlines.inl index 424beec7b1..2677c67dfe 100644 --- a/common/include/x86emitter/inlines.inl +++ b/common/include/x86emitter/inlines.inl @@ -1,316 +1,316 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2009 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/* - * ix86 core v0.9.0 - * - * Original Authors (v0.6.2 and prior): - * linuzappz - * alexey silinov - * goldfinger - * zerofrog(@gmail.com) - * - * Authors of v0.9.0: - * Jake.Stine(@gmail.com) - * cottonvibes(@gmail.com) - * sudonim(1@gmail.com) - */ - -#pragma once - -// This header module contains functions which, under most circumstances, inline -// nicely with constant propagation from the compiler, resulting in little or -// no actual codegen in the majority of emitter statements. (common forms include: -// RegToReg, PointerToReg, RegToPointer). These cannot be included in the class -// definitions in the .h file because of inter-dependencies with other classes. -// (score one for C++!!) -// -// In order for MSVC to work correctly with __forceinline on class members, -// however, we need to include these methods into all source files which might -// reference them. Without this MSVC generates linker errors. Or, in other words, -// global optimization fails to resolve the externals and junk. -// (score one for MSVC!) - -namespace x86Emitter -{ - extern const char *const x86_regnames_gpr8[8]; - extern const char *const x86_regnames_gpr16[8]; - extern const char *const x86_regnames_gpr32[8]; - - extern const char *const x86_regnames_sse[8]; - extern const char *const x86_regnames_mmx[8]; - - ////////////////////////////////////////////////////////////////////////////////////////// - // Diagnostic -- returns a string representation of this register. - // - template< typename T > - const char* xGetRegName( const xRegister& src ) - { - if( src.IsEmpty() ) return "empty"; - - switch( sizeof(T) ) - { - case 1: return x86_regnames_gpr8[ src.Id ]; - case 2: return x86_regnames_gpr16[ src.Id ]; - case 4: return x86_regnames_gpr32[ src.Id ]; - - jNO_DEFAULT - } - - return "oops?"; - } - - template< typename T > - const char* xGetRegName( const xRegisterSIMD& src ) - { - if( src.IsEmpty() ) return "empty"; - - switch( sizeof(T) ) - { - case 8: return x86_regnames_mmx[ src.Id ]; - case 16: return x86_regnames_sse[ src.Id ]; - - jNO_DEFAULT - } - - return "oops?"; - } - - ////////////////////////////////////////////////////////////////////////////////////////// - // x86Register Method Implementations - // - __forceinline xAddressInfo xAddressReg::operator+( const xAddressReg& right ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( *this, right ); - } - - __forceinline xAddressInfo xAddressReg::operator+( const xAddressInfo& right ) const - { - jASSUME( Id != -1 ); - return right + *this; - } - - __forceinline xAddressInfo xAddressReg::operator+( s32 right ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( *this, right ); - } - - __forceinline xAddressInfo xAddressReg::operator+( const void* right ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( *this, (s32)right ); - } - - // ------------------------------------------------------------------------ - __forceinline xAddressInfo xAddressReg::operator-( s32 right ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( *this, -right ); - } - - __forceinline xAddressInfo xAddressReg::operator-( const void* right ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( *this, -(s32)right ); - } - - // ------------------------------------------------------------------------ - __forceinline xAddressInfo xAddressReg::operator*( u32 right ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( Empty, *this, right ); - } - - __forceinline xAddressInfo xAddressReg::operator<<( u32 shift ) const - { - jASSUME( Id != -1 ); - return xAddressInfo( Empty, *this, 1< - xForwardJump::xForwardJump( JccComparisonType cctype ) : - BasePtr( (s8*)xGetPtr() + - ((OperandSize == 1) ? 2 : // j8's are always 2 bytes. - ((cctype==Jcc_Unconditional) ? 5 : 6 )) // j32's are either 5 or 6 bytes - ) - { - jASSUME( cctype != Jcc_Unknown ); - jASSUME( OperandSize == 1 || OperandSize == 4 ); - - if( OperandSize == 1 ) - xWrite8( (cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype) ); - else - { - if( cctype == Jcc_Unconditional ) - xWrite8( 0xe9 ); - else - { - xWrite8( 0x0f ); - xWrite8( 0x80 | cctype ); - } - } - - xAdvancePtr( OperandSize ); - } - - // ------------------------------------------------------------------------ - template< typename OperandType > - void xForwardJump::SetTarget() const - { - jASSUME( BasePtr != NULL ); - - sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr; - if( OperandSize == 1 ) - { - if( !is_s8( displacement ) ) - { - assert( false ); -// Don't ask. --arcum42 -#if !defined(__LINUX__) || !defined(DEBUG) - - Console::Error( "Emitter Error: Invalid short jump displacement = 0x%x", params (int)displacement ); -#endif - } - BasePtr[-1] = (s8)displacement; - } - else - { - // full displacement, no sanity checks needed :D - ((s32*)BasePtr)[-1] = displacement; - } - } - - // ------------------------------------------------------------------------ - // returns the inverted conditional type for this Jcc condition. Ie, JNS will become JS. - // - static __forceinline JccComparisonType xInvertCond( JccComparisonType src ) - { - jASSUME( src != Jcc_Unknown ); - if( Jcc_Unconditional == src ) return Jcc_Unconditional; - - // x86 conditionals are clever! To invert conditional types, just invert the lower bit: - return (JccComparisonType)((int)src ^ 1); - } -} +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2009 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * ix86 core v0.9.0 + * + * Original Authors (v0.6.2 and prior): + * linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + * + * Authors of v0.9.0: + * Jake.Stine(@gmail.com) + * cottonvibes(@gmail.com) + * sudonim(1@gmail.com) + */ + +#pragma once + +// This header module contains functions which, under most circumstances, inline +// nicely with constant propagation from the compiler, resulting in little or +// no actual codegen in the majority of emitter statements. (common forms include: +// RegToReg, PointerToReg, RegToPointer). These cannot be included in the class +// definitions in the .h file because of inter-dependencies with other classes. +// (score one for C++!!) +// +// In order for MSVC to work correctly with __forceinline on class members, +// however, we need to include these methods into all source files which might +// reference them. Without this MSVC generates linker errors. Or, in other words, +// global optimization fails to resolve the externals and junk. +// (score one for MSVC!) + +namespace x86Emitter +{ + extern const char *const x86_regnames_gpr8[8]; + extern const char *const x86_regnames_gpr16[8]; + extern const char *const x86_regnames_gpr32[8]; + + extern const char *const x86_regnames_sse[8]; + extern const char *const x86_regnames_mmx[8]; + + ////////////////////////////////////////////////////////////////////////////////////////// + // Diagnostic -- returns a string representation of this register. + // + template< typename T > + const char* xGetRegName( const xRegister& src ) + { + if( src.IsEmpty() ) return "empty"; + + switch( sizeof(T) ) + { + case 1: return x86_regnames_gpr8[ src.Id ]; + case 2: return x86_regnames_gpr16[ src.Id ]; + case 4: return x86_regnames_gpr32[ src.Id ]; + + jNO_DEFAULT + } + + return "oops?"; + } + + template< typename T > + const char* xGetRegName( const xRegisterSIMD& src ) + { + if( src.IsEmpty() ) return "empty"; + + switch( sizeof(T) ) + { + case 8: return x86_regnames_mmx[ src.Id ]; + case 16: return x86_regnames_sse[ src.Id ]; + + jNO_DEFAULT + } + + return "oops?"; + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // x86Register Method Implementations + // + __forceinline xAddressInfo xAddressReg::operator+( const xAddressReg& right ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( *this, right ); + } + + __forceinline xAddressInfo xAddressReg::operator+( const xAddressInfo& right ) const + { + jASSUME( Id != -1 ); + return right + *this; + } + + __forceinline xAddressInfo xAddressReg::operator+( s32 right ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( *this, right ); + } + + __forceinline xAddressInfo xAddressReg::operator+( const void* right ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( *this, (s32)right ); + } + + // ------------------------------------------------------------------------ + __forceinline xAddressInfo xAddressReg::operator-( s32 right ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( *this, -right ); + } + + __forceinline xAddressInfo xAddressReg::operator-( const void* right ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( *this, -(s32)right ); + } + + // ------------------------------------------------------------------------ + __forceinline xAddressInfo xAddressReg::operator*( u32 right ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( Empty, *this, right ); + } + + __forceinline xAddressInfo xAddressReg::operator<<( u32 shift ) const + { + jASSUME( Id != -1 ); + return xAddressInfo( Empty, *this, 1< + xForwardJump::xForwardJump( JccComparisonType cctype ) : + BasePtr( (s8*)xGetPtr() + + ((OperandSize == 1) ? 2 : // j8's are always 2 bytes. + ((cctype==Jcc_Unconditional) ? 5 : 6 )) // j32's are either 5 or 6 bytes + ) + { + jASSUME( cctype != Jcc_Unknown ); + jASSUME( OperandSize == 1 || OperandSize == 4 ); + + if( OperandSize == 1 ) + xWrite8( (cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype) ); + else + { + if( cctype == Jcc_Unconditional ) + xWrite8( 0xe9 ); + else + { + xWrite8( 0x0f ); + xWrite8( 0x80 | cctype ); + } + } + + xAdvancePtr( OperandSize ); + } + + // ------------------------------------------------------------------------ + template< typename OperandType > + void xForwardJump::SetTarget() const + { + jASSUME( BasePtr != NULL ); + + sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr; + if( OperandSize == 1 ) + { + if( !is_s8( displacement ) ) + { + assert( false ); +// Don't ask. --arcum42 +#if !defined(__LINUX__) || !defined(DEBUG) + + Console::Error( "Emitter Error: Invalid short jump displacement = 0x%x", params (int)displacement ); +#endif + } + BasePtr[-1] = (s8)displacement; + } + else + { + // full displacement, no sanity checks needed :D + ((s32*)BasePtr)[-1] = displacement; + } + } + + // ------------------------------------------------------------------------ + // returns the inverted conditional type for this Jcc condition. Ie, JNS will become JS. + // + static __forceinline JccComparisonType xInvertCond( JccComparisonType src ) + { + jASSUME( src != Jcc_Unknown ); + if( Jcc_Unconditional == src ) return Jcc_Unconditional; + + // x86 conditionals are clever! To invert conditional types, just invert the lower bit: + return (JccComparisonType)((int)src ^ 1); + } +} diff --git a/common/src/Utilities/ThreadTools.cpp b/common/src/Utilities/ThreadTools.cpp index ef7c4c4893..6d1922479c 100644 --- a/common/src/Utilities/ThreadTools.cpp +++ b/common/src/Utilities/ThreadTools.cpp @@ -31,6 +31,8 @@ using namespace Threading; namespace Threading { + static const timespec ts_msec_200 = { 0, 200 * 1000000 }; + static void _pt_callback_cleanup( void* handle ) { ((PersistentThread*)handle)->DoThreadCleanup(); @@ -39,6 +41,7 @@ namespace Threading PersistentThread::PersistentThread() : m_thread() , m_sem_event() + , m_sem_finished() , m_returncode( 0 ) , m_detached( false ) , m_running( false ) @@ -58,7 +61,11 @@ namespace Threading if( !_InterlockedExchange( &m_detached, true ) ) { - pthread_join( m_thread, (void**)&m_returncode ); +#if wxUSE_GUI + m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) ); +#else + m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) ); +#endif m_running = false; } } @@ -109,7 +116,13 @@ namespace Threading pthread_cancel( m_thread ); if( isBlocking ) - pthread_join( m_thread, (void**)&m_returncode ); + { +#if wxUSE_GUI + m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) ); +#else + m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) ); +#endif + } else pthread_detach( m_thread ); @@ -137,7 +150,12 @@ namespace Threading else { DevAssert( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." ); - pthread_join( m_thread, (void**)&m_returncode ); + +#if wxUSE_GUI + m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) ); +#else + m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) ); +#endif return m_returncode; } } @@ -260,11 +278,34 @@ namespace Threading // In order to avoid deadlock we need to make sure we cut some time // to handle messages. I choose 200ms: - static const timespec fail = { 0, 200 * 1000000 }; do { - wxTheApp->ProcessPendingEvents(); - } while( sem_timedwait( &sema, &fail ) == ETIMEDOUT ); + } while( sem_timedwait( &sema, &ts_msec_200 ) == ETIMEDOUT ); + } + } + + bool Semaphore::WaitGui( const wxTimeSpan& timeout ) + { + if( !wxThread::IsMain() || (wxTheApp == NULL) ) + { + return Wait( timeout ); + } + else + { + wxTimeSpan countdown( (timeout) ); + + // In order to avoid deadlock we need to make sure we cut some time + // to handle messages. I choose 200ms: + + static const wxTimeSpan pass( 0, 0, 0, 200 ); + do { + wxTheApp->ProcessPendingEvents(); + if( sem_timedwait( &sema, &ts_msec_200 ) != ETIMEDOUT ) + break; + countdown -= pass; + } while( countdown.GetMilliseconds() > 0 ); + + return countdown.GetMilliseconds() > 0; } } #endif @@ -274,10 +315,10 @@ namespace Threading sem_wait( &sema ); } - void Semaphore::Wait( const wxTimeSpan& timeout ) + bool Semaphore::Wait( const wxTimeSpan& timeout ) { const timespec fail = { timeout.GetSeconds().GetLo(), 0 }; - sem_timedwait( &sema, &fail ); + return sem_timedwait( &sema, &fail ) != ETIMEDOUT; } // Performs an uncancellable wait on a semaphore; restoring the thread's previous cancel state diff --git a/common/src/Utilities/x86/MemcpyFast.S b/common/src/Utilities/x86/MemcpyFast.S index e5e22793e6..a02c044cab 100644 --- a/common/src/Utilities/x86/MemcpyFast.S +++ b/common/src/Utilities/x86/MemcpyFast.S @@ -1,515 +1,515 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2005 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#define TINY_BLOCK_COPY 64 -#define IN_CACHE_COPY 2 * 1024 -#define UNCACHED_COPY 4 * 1024 -#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch -#define CACHEBLOCK 80 - -// Fast assembly routines for x86-64 -// zerofrog(@gmail.com) -// and added to by arcum42@gmail.com -.intel_syntax noprefix -.extern _mmx_backup - -// mmx memcmp implementation, size has to be a multiple of 8 -// returns 0 is equal, nonzero value if not equal -// ~10 times faster than standard memcmp -// (zerofrog) -// u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) -#define MEMCMP_SRC1 edx -#define MEMCMP_SRC2 esi -#define MEMCMP_SIZE ecx - -.global memcmp_mmx -memcmp_mmx: - // make sure mmx regs are stored - // FreezeMMXRegs(1); - //cmp dword ptr [g_EEFreezeRegs], 0 - //je memcmp_mmx_begin - //push 1 - //call FreezeMMXRegs_ - //add esp, 4 - -memcmp_mmx_begin: - push esi - mov MEMCMP_SRC1, dword ptr [esp+8] - mov MEMCMP_SRC2, dword ptr [esp+12] - mov MEMCMP_SIZE, dword ptr [esp+16] - - cmp MEMCMP_SIZE, 32 - jl memcmp_Done4 - - // custom test first 8 to make sure things are ok - movq mm0, [MEMCMP_SRC2] - movq mm1, [MEMCMP_SRC2+8] - pcmpeqd mm0, [MEMCMP_SRC1] - pcmpeqd mm1, [MEMCMP_SRC1+8] - pand mm0, mm1 - movq mm2, [MEMCMP_SRC2+16] - pmovmskb eax, mm0 - movq mm3, [MEMCMP_SRC2+24] - - // check if eq - cmp eax, 0xff - je memcmp_NextComp - mov eax, 1 - jmp memcmp_End - -memcmp_NextComp: - pcmpeqd mm2, [MEMCMP_SRC1+16] - pcmpeqd mm3, [MEMCMP_SRC1+24] - pand mm2, mm3 - pmovmskb eax, mm2 - - sub MEMCMP_SIZE, 32 - add MEMCMP_SRC2, 32 - add MEMCMP_SRC1, 32 - - // check if eq - cmp eax, 0xff - je memcmp_ContinueTest - mov eax, 1 - jmp memcmp_End - - cmp MEMCMP_SIZE, 64 - jl memcmp_Done8 - -memcmp_Cmp8: - movq mm0, [MEMCMP_SRC2] - movq mm1, [MEMCMP_SRC2+8] - movq mm2, [MEMCMP_SRC2+16] - movq mm3, [MEMCMP_SRC2+24] - movq mm4, [MEMCMP_SRC2+32] - movq mm5, [MEMCMP_SRC2+40] - movq mm6, [MEMCMP_SRC2+48] - movq mm7, [MEMCMP_SRC2+56] - pcmpeqd mm0, [MEMCMP_SRC1] - pcmpeqd mm1, [MEMCMP_SRC1+8] - pcmpeqd mm2, [MEMCMP_SRC1+16] - pcmpeqd mm3, [MEMCMP_SRC1+24] - pand mm0, mm1 - pcmpeqd mm4, [MEMCMP_SRC1+32] - pand mm0, mm2 - pcmpeqd mm5, [MEMCMP_SRC1+40] - pand mm0, mm3 - pcmpeqd mm6, [MEMCMP_SRC1+48] - pand mm0, mm4 - pcmpeqd mm7, [MEMCMP_SRC1+56] - pand mm0, mm5 - pand mm0, mm6 - pand mm0, mm7 - pmovmskb eax, mm0 - - // check if eq - cmp eax, 0xff - je memcmp_Continue - mov eax, 1 - jmp memcmp_End - -memcmp_Continue: - sub MEMCMP_SIZE, 64 - add MEMCMP_SRC2, 64 - add MEMCMP_SRC1, 64 -memcmp_ContinueTest: - cmp MEMCMP_SIZE, 64 - jge memcmp_Cmp8 - -memcmp_Done8: - test MEMCMP_SIZE, 0x20 - jz memcmp_Done4 - movq mm0, [MEMCMP_SRC2] - movq mm1, [MEMCMP_SRC2+8] - movq mm2, [MEMCMP_SRC2+16] - movq mm3, [MEMCMP_SRC2+24] - pcmpeqd mm0, [MEMCMP_SRC1] - pcmpeqd mm1, [MEMCMP_SRC1+8] - pcmpeqd mm2, [MEMCMP_SRC1+16] - pcmpeqd mm3, [MEMCMP_SRC1+24] - pand mm0, mm1 - pand mm0, mm2 - pand mm0, mm3 - pmovmskb eax, mm0 - sub MEMCMP_SIZE, 32 - add MEMCMP_SRC2, 32 - add MEMCMP_SRC1, 32 - - // check if eq - cmp eax, 0xff - je memcmp_Done4 - mov eax, 1 - jmp memcmp_End - -memcmp_Done4: - cmp MEMCMP_SIZE, 24 - jne memcmp_Done2 - movq mm0, [MEMCMP_SRC2] - movq mm1, [MEMCMP_SRC2+8] - movq mm2, [MEMCMP_SRC2+16] - pcmpeqd mm0, [MEMCMP_SRC1] - pcmpeqd mm1, [MEMCMP_SRC1+8] - pcmpeqd mm2, [MEMCMP_SRC1+16] - pand mm0, mm1 - pand mm0, mm2 - pmovmskb eax, mm0 - - // check if eq - cmp eax, 0xff - je memcmp_Done - mov eax, 1 - jmp memcmp_End - -memcmp_Done2: - cmp MEMCMP_SIZE, 16 - jne memcmp_Done1 - - movq mm0, [MEMCMP_SRC2] - movq mm1, [MEMCMP_SRC2+8] - pcmpeqd mm0, [MEMCMP_SRC1] - pcmpeqd mm1, [MEMCMP_SRC1+8] - pand mm0, mm1 - pmovmskb eax, mm0 - - // check if eq - cmp eax, 0xff - je memcmp_Done - mov eax, 1 - jmp memcmp_End - -memcmp_Done1: - cmp MEMCMP_SIZE, 8 - jne memcmp_Done - - mov eax, [MEMCMP_SRC2] - mov MEMCMP_SRC2, [MEMCMP_SRC2+4] - cmp eax, [MEMCMP_SRC1] - je memcmp_Next - mov eax, 1 - jmp memcmp_End - -memcmp_Next: - cmp MEMCMP_SRC2, [MEMCMP_SRC1+4] - je memcmp_Done - mov eax, 1 - jmp memcmp_End - -memcmp_Done: - xor eax, eax - -memcmp_End: - emms - pop esi - ret - -// memxor_mmx -#define MEMXOR_SRC1 edx -#define MEMXOR_SRC2 esi -#define MEMXOR_SIZE ecx - -.global memxor_mmx -memxor_mmx: - - push esi - mov MEMXOR_SRC1, dword ptr [esp+8] - mov MEMXOR_SRC2, dword ptr [esp+12] - mov MEMXOR_SIZE, dword ptr [esp+16] - cmp MEMXOR_SIZE, 64 - jl memxor_Setup4 - - movq mm0, [MEMXOR_SRC2] - movq mm1, [MEMXOR_SRC2+8] - movq mm2, [MEMXOR_SRC2+16] - movq mm3, [MEMXOR_SRC2+24] - movq mm4, [MEMXOR_SRC2+32] - movq mm5, [MEMXOR_SRC2+40] - movq mm6, [MEMXOR_SRC2+48] - movq mm7, [MEMXOR_SRC2+56] - sub MEMXOR_SIZE, 64 - add MEMXOR_SRC2, 64 - cmp MEMXOR_SIZE, 64 - jl memxor_End8 - -memxor_Cmp8: - pxor mm0, [MEMXOR_SRC2] - pxor mm1, [MEMXOR_SRC2+8] - pxor mm2, [MEMXOR_SRC2+16] - pxor mm3, [MEMXOR_SRC2+24] - pxor mm4, [MEMXOR_SRC2+32] - pxor mm5, [MEMXOR_SRC2+40] - pxor mm6, [MEMXOR_SRC2+48] - pxor mm7, [MEMXOR_SRC2+56] - - sub MEMXOR_SIZE, 64 - add MEMXOR_SRC2, 64 - cmp MEMXOR_SIZE, 64 - jge memxor_Cmp8 - -memxor_End8: - pxor mm0, mm4 - pxor mm1, mm5 - pxor mm2, mm6 - pxor mm3, mm7 - - cmp MEMXOR_SIZE, 32 - jl memxor_End4 - pxor mm0, [MEMXOR_SRC2] - pxor mm1, [MEMXOR_SRC2+8] - pxor mm2, [MEMXOR_SRC2+16] - pxor mm3, [MEMXOR_SRC2+24] - sub MEMXOR_SIZE, 32 - add MEMXOR_SRC2, 32 - jmp memxor_End4 - -memxor_Setup4: - cmp MEMXOR_SIZE, 32 - jl memxor_Setup2 - - movq mm0, [MEMXOR_SRC2] - movq mm1, [MEMXOR_SRC2+8] - movq mm2, [MEMXOR_SRC2+16] - movq mm3, [MEMXOR_SRC2+24] - sub MEMXOR_SIZE, 32 - add MEMXOR_SRC2, 32 - -memxor_End4: - pxor mm0, mm2 - pxor mm1, mm3 - - cmp MEMXOR_SIZE, 16 - jl memxor_End2 - pxor mm0, [MEMXOR_SRC2] - pxor mm1, [MEMXOR_SRC2+8] - sub MEMXOR_SIZE, 16 - add MEMXOR_SRC2, 16 - jmp memxor_End2 - -memxor_Setup2: - cmp MEMXOR_SIZE, 16 - jl memxor_Setup1 - - movq mm0, [MEMXOR_SRC2] - movq mm1, [MEMXOR_SRC2+8] - sub MEMXOR_SIZE, 16 - add MEMXOR_SRC2, 16 - -memxor_End2: - pxor mm0, mm1 - - cmp MEMXOR_SIZE, 8 - jl memxor_End1 - pxor mm0, [MEMXOR_SRC2] -memxor_End1: - movq [MEMXOR_SRC1], mm0 - jmp memxor_End - -memxor_Setup1: - movq mm0, [MEMXOR_SRC2] - movq [MEMXOR_SRC1], mm0 -memxor_End: - emms - pop esi - ret - -// void __fastcall memcpy_amd_(void *dest, const void *src, size_t n) -.global memcpy_amd_ -memcpy_amd_: - push edi - push esi - - mov edi, ecx // destination - mov esi, edx // source - mov ecx, [esp+12] // number of bytes to copy - mov eax, ecx // keep a copy of count - - cld - cmp eax, TINY_BLOCK_COPY - jb $memcpy_ic_3 // tiny? skip mmx copy - - cmp eax, 32*1024 // don't align between 32k-64k because - jbe $memcpy_do_align // it appears to be slower - cmp eax, 64*1024 - jbe $memcpy_align_done - -$memcpy_do_align: - mov eax, 8 // a trick that's faster than rep movsb... - sub eax, edi // align destination to qword - and eax, 0b111 // get the low bits - sub ecx, eax // update copy count - neg eax // set up to jump into the array - add eax, offset $memcpy_align_done - jmp eax // jump to array of movsb's - -.align 4 - movsb - movsb - movsb - movsb - movsb - movsb - movsb - movsb - -$memcpy_align_done: // destination is dword aligned - mov eax, ecx // number of bytes left to copy - shr eax, 6 // get 64-byte block count - jz $memcpy_ic_2 // finish the last few bytes - - mov edx, offset _mmx_backup // will probably need this to save/restore mmx - cmp eax, IN_CACHE_COPY/64 // too big 4 cache? use uncached copy - jae $memcpy_uc_test - - movq [edx+0x00],mm0 - movq [edx+0x08],mm1 - movq [edx+0x10],mm2 - movq [edx+0x18],mm3 - -// This is small block copy that uses the MMX registers to copy 8 bytes -// at a time. It uses the "unrolled loop" optimization, and also uses -// the software prefetch instruction to get the data into the cache. -.align 16 -$memcpy_ic_1: // 64-byte block copies, in-cache copy - - prefetchnta [esi + (200*64/34+192)] // start reading ahead - - movq mm0, [esi+0] // read 64 bits - movq mm1, [esi+8] - movq [edi+0], mm0 //write 64 bits - movq [edi+8], mm1 // note: the normal movq writes the - movq mm2, [esi+16] // data to cache; a cache line will be - movq mm3, [esi+24] // allocated as needed, to store the data - movq [edi+16], mm2 - movq [edi+24], mm3 - movq mm0, [esi+32] - movq mm1, [esi+40] - movq [edi+32], mm0 - movq [edi+40], mm1 - movq mm2, [esi+48] - movq mm3, [esi+56] - movq [edi+48], mm2 - movq [edi+56], mm3 - - add esi, 64 // update source pointer - add edi, 64 // update destination pointer - dec eax // count down - jnz $memcpy_ic_1 // last 64-byte block? - - movq mm0,[edx+0x00] - movq mm1,[edx+0x08] - movq mm2,[edx+0x10] - movq mm3,[edx+0x18] - -$memcpy_ic_2: - mov eax, ecx // has valid low 6 bits of the byte count -$memcpy_ic_3: - shr eax, 2 // dword count - and eax, 0b1111 // only look at the "remainder" bits - neg eax // set up to jump into the array - add eax, offset $memcpy_last_few - jmp eax // jump to array of movsd's - -$memcpy_uc_test: - or eax, eax // tail end of block prefetch will jump here - jz $memcpy_ic_2 // no more 64-byte blocks left - -// For larger blocks, which will spill beyond the cache, it's faster to -// use the Streaming Store instruction MOVNTQ. This write instruction -// bypasses the cache and writes straight to main memory. This code also -// uses the software prefetch instruction to pre-read the data. - - movq [edx+0x00],mm0 - movq [edx+0x08],mm1 - movq [edx+0x10],mm2 - -.align 16 -$memcpy_uc_1: // 64-byte blocks, uncached copy - - prefetchnta [esi + (200*64/34+192)] // start reading ahead - - movq mm0,[esi+0] // read 64 bits - add edi,64 // update destination pointer - movq mm1,[esi+8] - add esi,64 // update source pointer - movq mm2,[esi-48] - movntq [edi-64], mm0 // write 64 bits, bypassing the cache - movq mm0,[esi-40] // note: movntq also prevents the CPU - movntq [edi-56], mm1 // from READING the destination address - movq mm1,[esi-32] // into the cache, only to be over-written - movntq [edi-48], mm2 // so that also helps performance - movq mm2,[esi-24] - movntq [edi-40], mm0 - movq mm0,[esi-16] - movntq [edi-32], mm1 - movq mm1,[esi-8] - movntq [edi-24], mm2 - movntq [edi-16],mm0 - dec eax - movntq [edi-8], mm1 - jnz $memcpy_uc_1 // last 64-byte block? - - movq mm0,[edx+0x00] - movq mm1,[edx+0x08] - movq mm2,[edx+0x10] - - jmp $memcpy_ic_2 // almost done (not needed because large copy below was removed) - -// For the largest size blocks, a special technique called Block Prefetch -// can be used to accelerate the read operations. Block Prefetch reads -// one address per cache line, for a series of cache lines, in a short loop. -// This is faster than using software prefetch. The technique is great for -// getting maximum read bandwidth, especially in DDR memory systems. - -// Note: Pcsx2 rarely invokes large copies, so this mode has been disabled to -// help keep the code cache footprint of memcpy_fast to a minimum. -// - -// The smallest copy uses the X86 "movsd" instruction, in an optimized -// form which is an "unrolled loop". Then it handles the last few bytes. -.align 16 - movsd - movsd // perform last 1-15 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - movsd - movsd // perform last 1-7 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - -$memcpy_last_few: // dword aligned from before movsd's - and ecx, 0b11 // the last few cows must come home - jz $memcpy_final // no more, let's leave - rep movsb // the last 1, 2, or 3 bytes - -$memcpy_final: - emms // clean up the MMX state - sfence // flush the write buffer - //mov eax, [dest] // ret value = destination pointer - - pop esi - pop edi - +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define TINY_BLOCK_COPY 64 +#define IN_CACHE_COPY 2 * 1024 +#define UNCACHED_COPY 4 * 1024 +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80 + +// Fast assembly routines for x86-64 +// zerofrog(@gmail.com) +// and added to by arcum42@gmail.com +.intel_syntax noprefix +.extern _mmx_backup + +// mmx memcmp implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +// u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +#define MEMCMP_SRC1 edx +#define MEMCMP_SRC2 esi +#define MEMCMP_SIZE ecx + +.global memcmp_mmx +memcmp_mmx: + // make sure mmx regs are stored + // FreezeMMXRegs(1); + //cmp dword ptr [g_EEFreezeRegs], 0 + //je memcmp_mmx_begin + //push 1 + //call FreezeMMXRegs_ + //add esp, 4 + +memcmp_mmx_begin: + push esi + mov MEMCMP_SRC1, dword ptr [esp+8] + mov MEMCMP_SRC2, dword ptr [esp+12] + mov MEMCMP_SIZE, dword ptr [esp+16] + + cmp MEMCMP_SIZE, 32 + jl memcmp_Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [MEMCMP_SRC2] + movq mm1, [MEMCMP_SRC2+8] + pcmpeqd mm0, [MEMCMP_SRC1] + pcmpeqd mm1, [MEMCMP_SRC1+8] + pand mm0, mm1 + movq mm2, [MEMCMP_SRC2+16] + pmovmskb eax, mm0 + movq mm3, [MEMCMP_SRC2+24] + + // check if eq + cmp eax, 0xff + je memcmp_NextComp + mov eax, 1 + jmp memcmp_End + +memcmp_NextComp: + pcmpeqd mm2, [MEMCMP_SRC1+16] + pcmpeqd mm3, [MEMCMP_SRC1+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub MEMCMP_SIZE, 32 + add MEMCMP_SRC2, 32 + add MEMCMP_SRC1, 32 + + // check if eq + cmp eax, 0xff + je memcmp_ContinueTest + mov eax, 1 + jmp memcmp_End + + cmp MEMCMP_SIZE, 64 + jl memcmp_Done8 + +memcmp_Cmp8: + movq mm0, [MEMCMP_SRC2] + movq mm1, [MEMCMP_SRC2+8] + movq mm2, [MEMCMP_SRC2+16] + movq mm3, [MEMCMP_SRC2+24] + movq mm4, [MEMCMP_SRC2+32] + movq mm5, [MEMCMP_SRC2+40] + movq mm6, [MEMCMP_SRC2+48] + movq mm7, [MEMCMP_SRC2+56] + pcmpeqd mm0, [MEMCMP_SRC1] + pcmpeqd mm1, [MEMCMP_SRC1+8] + pcmpeqd mm2, [MEMCMP_SRC1+16] + pcmpeqd mm3, [MEMCMP_SRC1+24] + pand mm0, mm1 + pcmpeqd mm4, [MEMCMP_SRC1+32] + pand mm0, mm2 + pcmpeqd mm5, [MEMCMP_SRC1+40] + pand mm0, mm3 + pcmpeqd mm6, [MEMCMP_SRC1+48] + pand mm0, mm4 + pcmpeqd mm7, [MEMCMP_SRC1+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je memcmp_Continue + mov eax, 1 + jmp memcmp_End + +memcmp_Continue: + sub MEMCMP_SIZE, 64 + add MEMCMP_SRC2, 64 + add MEMCMP_SRC1, 64 +memcmp_ContinueTest: + cmp MEMCMP_SIZE, 64 + jge memcmp_Cmp8 + +memcmp_Done8: + test MEMCMP_SIZE, 0x20 + jz memcmp_Done4 + movq mm0, [MEMCMP_SRC2] + movq mm1, [MEMCMP_SRC2+8] + movq mm2, [MEMCMP_SRC2+16] + movq mm3, [MEMCMP_SRC2+24] + pcmpeqd mm0, [MEMCMP_SRC1] + pcmpeqd mm1, [MEMCMP_SRC1+8] + pcmpeqd mm2, [MEMCMP_SRC1+16] + pcmpeqd mm3, [MEMCMP_SRC1+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub MEMCMP_SIZE, 32 + add MEMCMP_SRC2, 32 + add MEMCMP_SRC1, 32 + + // check if eq + cmp eax, 0xff + je memcmp_Done4 + mov eax, 1 + jmp memcmp_End + +memcmp_Done4: + cmp MEMCMP_SIZE, 24 + jne memcmp_Done2 + movq mm0, [MEMCMP_SRC2] + movq mm1, [MEMCMP_SRC2+8] + movq mm2, [MEMCMP_SRC2+16] + pcmpeqd mm0, [MEMCMP_SRC1] + pcmpeqd mm1, [MEMCMP_SRC1+8] + pcmpeqd mm2, [MEMCMP_SRC1+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je memcmp_Done + mov eax, 1 + jmp memcmp_End + +memcmp_Done2: + cmp MEMCMP_SIZE, 16 + jne memcmp_Done1 + + movq mm0, [MEMCMP_SRC2] + movq mm1, [MEMCMP_SRC2+8] + pcmpeqd mm0, [MEMCMP_SRC1] + pcmpeqd mm1, [MEMCMP_SRC1+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je memcmp_Done + mov eax, 1 + jmp memcmp_End + +memcmp_Done1: + cmp MEMCMP_SIZE, 8 + jne memcmp_Done + + mov eax, [MEMCMP_SRC2] + mov MEMCMP_SRC2, [MEMCMP_SRC2+4] + cmp eax, [MEMCMP_SRC1] + je memcmp_Next + mov eax, 1 + jmp memcmp_End + +memcmp_Next: + cmp MEMCMP_SRC2, [MEMCMP_SRC1+4] + je memcmp_Done + mov eax, 1 + jmp memcmp_End + +memcmp_Done: + xor eax, eax + +memcmp_End: + emms + pop esi + ret + +// memxor_mmx +#define MEMXOR_SRC1 edx +#define MEMXOR_SRC2 esi +#define MEMXOR_SIZE ecx + +.global memxor_mmx +memxor_mmx: + + push esi + mov MEMXOR_SRC1, dword ptr [esp+8] + mov MEMXOR_SRC2, dword ptr [esp+12] + mov MEMXOR_SIZE, dword ptr [esp+16] + cmp MEMXOR_SIZE, 64 + jl memxor_Setup4 + + movq mm0, [MEMXOR_SRC2] + movq mm1, [MEMXOR_SRC2+8] + movq mm2, [MEMXOR_SRC2+16] + movq mm3, [MEMXOR_SRC2+24] + movq mm4, [MEMXOR_SRC2+32] + movq mm5, [MEMXOR_SRC2+40] + movq mm6, [MEMXOR_SRC2+48] + movq mm7, [MEMXOR_SRC2+56] + sub MEMXOR_SIZE, 64 + add MEMXOR_SRC2, 64 + cmp MEMXOR_SIZE, 64 + jl memxor_End8 + +memxor_Cmp8: + pxor mm0, [MEMXOR_SRC2] + pxor mm1, [MEMXOR_SRC2+8] + pxor mm2, [MEMXOR_SRC2+16] + pxor mm3, [MEMXOR_SRC2+24] + pxor mm4, [MEMXOR_SRC2+32] + pxor mm5, [MEMXOR_SRC2+40] + pxor mm6, [MEMXOR_SRC2+48] + pxor mm7, [MEMXOR_SRC2+56] + + sub MEMXOR_SIZE, 64 + add MEMXOR_SRC2, 64 + cmp MEMXOR_SIZE, 64 + jge memxor_Cmp8 + +memxor_End8: + pxor mm0, mm4 + pxor mm1, mm5 + pxor mm2, mm6 + pxor mm3, mm7 + + cmp MEMXOR_SIZE, 32 + jl memxor_End4 + pxor mm0, [MEMXOR_SRC2] + pxor mm1, [MEMXOR_SRC2+8] + pxor mm2, [MEMXOR_SRC2+16] + pxor mm3, [MEMXOR_SRC2+24] + sub MEMXOR_SIZE, 32 + add MEMXOR_SRC2, 32 + jmp memxor_End4 + +memxor_Setup4: + cmp MEMXOR_SIZE, 32 + jl memxor_Setup2 + + movq mm0, [MEMXOR_SRC2] + movq mm1, [MEMXOR_SRC2+8] + movq mm2, [MEMXOR_SRC2+16] + movq mm3, [MEMXOR_SRC2+24] + sub MEMXOR_SIZE, 32 + add MEMXOR_SRC2, 32 + +memxor_End4: + pxor mm0, mm2 + pxor mm1, mm3 + + cmp MEMXOR_SIZE, 16 + jl memxor_End2 + pxor mm0, [MEMXOR_SRC2] + pxor mm1, [MEMXOR_SRC2+8] + sub MEMXOR_SIZE, 16 + add MEMXOR_SRC2, 16 + jmp memxor_End2 + +memxor_Setup2: + cmp MEMXOR_SIZE, 16 + jl memxor_Setup1 + + movq mm0, [MEMXOR_SRC2] + movq mm1, [MEMXOR_SRC2+8] + sub MEMXOR_SIZE, 16 + add MEMXOR_SRC2, 16 + +memxor_End2: + pxor mm0, mm1 + + cmp MEMXOR_SIZE, 8 + jl memxor_End1 + pxor mm0, [MEMXOR_SRC2] +memxor_End1: + movq [MEMXOR_SRC1], mm0 + jmp memxor_End + +memxor_Setup1: + movq mm0, [MEMXOR_SRC2] + movq [MEMXOR_SRC1], mm0 +memxor_End: + emms + pop esi + ret + +// void __fastcall memcpy_amd_(void *dest, const void *src, size_t n) +.global memcpy_amd_ +memcpy_amd_: + push edi + push esi + + mov edi, ecx // destination + mov esi, edx // source + mov ecx, [esp+12] // number of bytes to copy + mov eax, ecx // keep a copy of count + + cld + cmp eax, TINY_BLOCK_COPY + jb $memcpy_ic_3 // tiny? skip mmx copy + + cmp eax, 32*1024 // don't align between 32k-64k because + jbe $memcpy_do_align // it appears to be slower + cmp eax, 64*1024 + jbe $memcpy_align_done + +$memcpy_do_align: + mov eax, 8 // a trick that's faster than rep movsb... + sub eax, edi // align destination to qword + and eax, 0b111 // get the low bits + sub ecx, eax // update copy count + neg eax // set up to jump into the array + add eax, offset $memcpy_align_done + jmp eax // jump to array of movsb's + +.align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: // destination is dword aligned + mov eax, ecx // number of bytes left to copy + shr eax, 6 // get 64-byte block count + jz $memcpy_ic_2 // finish the last few bytes + + mov edx, offset _mmx_backup // will probably need this to save/restore mmx + cmp eax, IN_CACHE_COPY/64 // too big 4 cache? use uncached copy + jae $memcpy_uc_test + + movq [edx+0x00],mm0 + movq [edx+0x08],mm1 + movq [edx+0x10],mm2 + movq [edx+0x18],mm3 + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +.align 16 +$memcpy_ic_1: // 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] // start reading ahead + + movq mm0, [esi+0] // read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 //write 64 bits + movq [edi+8], mm1 // note: the normal movq writes the + movq mm2, [esi+16] // data to cache; a cache line will be + movq mm3, [esi+24] // allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 // update source pointer + add edi, 64 // update destination pointer + dec eax // count down + jnz $memcpy_ic_1 // last 64-byte block? + + movq mm0,[edx+0x00] + movq mm1,[edx+0x08] + movq mm2,[edx+0x10] + movq mm3,[edx+0x18] + +$memcpy_ic_2: + mov eax, ecx // has valid low 6 bits of the byte count +$memcpy_ic_3: + shr eax, 2 // dword count + and eax, 0b1111 // only look at the "remainder" bits + neg eax // set up to jump into the array + add eax, offset $memcpy_last_few + jmp eax // jump to array of movsd's + +$memcpy_uc_test: + or eax, eax // tail end of block prefetch will jump here + jz $memcpy_ic_2 // no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. + + movq [edx+0x00],mm0 + movq [edx+0x08],mm1 + movq [edx+0x10],mm2 + +.align 16 +$memcpy_uc_1: // 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] // start reading ahead + + movq mm0,[esi+0] // read 64 bits + add edi,64 // update destination pointer + movq mm1,[esi+8] + add esi,64 // update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 // write 64 bits, bypassing the cache + movq mm0,[esi-40] // note: movntq also prevents the CPU + movntq [edi-56], mm1 // from READING the destination address + movq mm1,[esi-32] // into the cache, only to be over-written + movntq [edi-48], mm2 // so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16],mm0 + dec eax + movntq [edi-8], mm1 + jnz $memcpy_uc_1 // last 64-byte block? + + movq mm0,[edx+0x00] + movq mm1,[edx+0x08] + movq mm2,[edx+0x10] + + jmp $memcpy_ic_2 // almost done (not needed because large copy below was removed) + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +// Note: Pcsx2 rarely invokes large copies, so this mode has been disabled to +// help keep the code cache footprint of memcpy_fast to a minimum. +// + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +.align 16 + movsd + movsd // perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd // perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: // dword aligned from before movsd's + and ecx, 0b11 // the last few cows must come home + jz $memcpy_final // no more, let's leave + rep movsb // the last 1, 2, or 3 bytes + +$memcpy_final: + emms // clean up the MMX state + sfence // flush the write buffer + //mov eax, [dest] // ret value = destination pointer + + pop esi + pop edi + ret 4 \ No newline at end of file diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 553a958a72..65cf0f1be6 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -247,9 +247,6 @@ public: // when enabled performs bios stub execution, skipping full sony bios + splash screens SkipBiosSplash:1, - // Closes the GS/Video port on escape (good for fullscreen activity) - closeGSonEsc:1, - // enables simulated ejection of memory cards when loading savestates McdEnableEjection:1; }; }; diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index e08388b5bd..d5bba7e736 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -634,6 +634,7 @@ struct GSStatePacket }; // runs the GS +// (this should really be part of the AppGui) void RunGSState( gzLoadingState& f ) { u32 newfield; @@ -679,7 +680,9 @@ void RunGSState( gzLoadingState& f ) *(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield; GSvsync(newfield); - SysUpdate(); + + // fixme : Process pending app messages here. + //SysUpdate(); if( g_SaveGSStream != 3 ) return; diff --git a/pcsx2/GS.h b/pcsx2/GS.h index aeed1b7d2c..ae22b7d731 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -368,5 +368,5 @@ extern gzSavingState* g_fGSSave; #endif -void RunGSState(gzLoadingState& f); +extern void RunGSState(gzLoadingState& f); diff --git a/pcsx2/HostGui.h b/pcsx2/HostGui.h index 05e6506161..087ee832c8 100644 --- a/pcsx2/HostGui.h +++ b/pcsx2/HostGui.h @@ -85,10 +85,6 @@ extern bool States_isSlotUsed(int num); // as keyboard events, menu/status updates, and cpu execution invocation. namespace HostGui { - // Signals the gui with a keystroke. Handle or discard or dispatch, or enjoy its - // pleasant flavor. - extern void __fastcall KeyEvent( keyEvent* ev ); - // For issuing notices to both the status bar and the console at the same time. // Single-line text only please! Multi-line msgs should be directed to the // console directly, thanks. diff --git a/pcsx2/Linux/LnxKeyCodes.cpp b/pcsx2/Linux/LnxKeyCodes.cpp new file mode 100644 index 0000000000..c0450c4574 --- /dev/null +++ b/pcsx2/Linux/LnxKeyCodes.cpp @@ -0,0 +1,278 @@ + +#include "../PrecompiledHeader.h" + +#include +#include +#include +#include + +// Returns a WXK_* keycode, given osome kinda GKT input mess! +u32 TranslateGDKtoWXK( u32 keysym ) +{ + u32 key_code; + + switch ( keysym ) + { + // Shift, Control and Alt don't generate the CHAR events at all + case GDK_Shift_L: + case GDK_Shift_R: + key_code = WXK_SHIFT; + break; + case GDK_Control_L: + case GDK_Control_R: + key_code = WXK_CONTROL; + break; + case GDK_Meta_L: + case GDK_Meta_R: + case GDK_Alt_L: + case GDK_Alt_R: + case GDK_Super_L: + case GDK_Super_R: + key_code = WXK_ALT; + break; + + // neither do the toggle modifies + case GDK_Scroll_Lock: + key_code = WXK_SCROLL; + break; + + case GDK_Caps_Lock: + key_code = WXK_CAPITAL; + break; + + case GDK_Num_Lock: + key_code = WXK_NUMLOCK; + break; + + + // various other special keys + case GDK_Menu: + key_code = WXK_MENU; + break; + + case GDK_Help: + key_code = WXK_HELP; + break; + + case GDK_BackSpace: + key_code = WXK_BACK; + break; + + case GDK_ISO_Left_Tab: + case GDK_Tab: + key_code = WXK_TAB; + break; + + case GDK_Linefeed: + case GDK_Return: + key_code = WXK_RETURN; + break; + + case GDK_Clear: + key_code = WXK_CLEAR; + break; + + case GDK_Pause: + key_code = WXK_PAUSE; + break; + + case GDK_Select: + key_code = WXK_SELECT; + break; + + case GDK_Print: + key_code = WXK_PRINT; + break; + + case GDK_Execute: + key_code = WXK_EXECUTE; + break; + + case GDK_Escape: + key_code = WXK_ESCAPE; + break; + + // cursor and other extended keyboard keys + case GDK_Delete: + key_code = WXK_DELETE; + break; + + case GDK_Home: + key_code = WXK_HOME; + break; + + case GDK_Left: + key_code = WXK_LEFT; + break; + + case GDK_Up: + key_code = WXK_UP; + break; + + case GDK_Right: + key_code = WXK_RIGHT; + break; + + case GDK_Down: + key_code = WXK_DOWN; + break; + + case GDK_Prior: // == GDK_Page_Up + key_code = WXK_PAGEUP; + break; + + case GDK_Next: // == GDK_Page_Down + key_code = WXK_PAGEDOWN; + break; + + case GDK_End: + key_code = WXK_END; + break; + + case GDK_Begin: + key_code = WXK_HOME; + break; + + case GDK_Insert: + key_code = WXK_INSERT; + break; + + + // numpad keys + case GDK_KP_0: + case GDK_KP_1: + case GDK_KP_2: + case GDK_KP_3: + case GDK_KP_4: + case GDK_KP_5: + case GDK_KP_6: + case GDK_KP_7: + case GDK_KP_8: + case GDK_KP_9: + key_code = (isChar ? '0' : WXK_NUMPAD0) + keysym - GDK_KP_0; + break; + + case GDK_KP_Space: + key_code = isChar ? ' ' : WXK_NUMPAD_SPACE; + break; + + case GDK_KP_Tab: + key_code = isChar ? WXK_TAB : WXK_NUMPAD_TAB; + break; + + case GDK_KP_Enter: + key_code = isChar ? WXK_RETURN : WXK_NUMPAD_ENTER; + break; + + case GDK_KP_F1: + key_code = isChar ? WXK_F1 : WXK_NUMPAD_F1; + break; + + case GDK_KP_F2: + key_code = isChar ? WXK_F2 : WXK_NUMPAD_F2; + break; + + case GDK_KP_F3: + key_code = isChar ? WXK_F3 : WXK_NUMPAD_F3; + break; + + case GDK_KP_F4: + key_code = isChar ? WXK_F4 : WXK_NUMPAD_F4; + break; + + case GDK_KP_Home: + key_code = isChar ? WXK_HOME : WXK_NUMPAD_HOME; + break; + + case GDK_KP_Left: + key_code = isChar ? WXK_LEFT : WXK_NUMPAD_LEFT; + break; + + case GDK_KP_Up: + key_code = isChar ? WXK_UP : WXK_NUMPAD_UP; + break; + + case GDK_KP_Right: + key_code = isChar ? WXK_RIGHT : WXK_NUMPAD_RIGHT; + break; + + case GDK_KP_Down: + key_code = isChar ? WXK_DOWN : WXK_NUMPAD_DOWN; + break; + + case GDK_KP_Prior: // == GDK_KP_Page_Up + key_code = isChar ? WXK_PAGEUP : WXK_NUMPAD_PAGEUP; + break; + + case GDK_KP_Next: // == GDK_KP_Page_Down + key_code = isChar ? WXK_PAGEDOWN : WXK_NUMPAD_PAGEDOWN; + break; + + case GDK_KP_End: + key_code = isChar ? WXK_END : WXK_NUMPAD_END; + break; + + case GDK_KP_Begin: + key_code = isChar ? WXK_HOME : WXK_NUMPAD_BEGIN; + break; + + case GDK_KP_Insert: + key_code = isChar ? WXK_INSERT : WXK_NUMPAD_INSERT; + break; + + case GDK_KP_Delete: + key_code = isChar ? WXK_DELETE : WXK_NUMPAD_DELETE; + break; + + case GDK_KP_Equal: + key_code = isChar ? '=' : WXK_NUMPAD_EQUAL; + break; + + case GDK_KP_Multiply: + key_code = isChar ? '*' : WXK_NUMPAD_MULTIPLY; + break; + + case GDK_KP_Add: + key_code = isChar ? '+' : WXK_NUMPAD_ADD; + break; + + case GDK_KP_Separator: + // FIXME: what is this? + key_code = isChar ? '.' : WXK_NUMPAD_SEPARATOR; + break; + + case GDK_KP_Subtract: + key_code = isChar ? '-' : WXK_NUMPAD_SUBTRACT; + break; + + case GDK_KP_Decimal: + key_code = isChar ? '.' : WXK_NUMPAD_DECIMAL; + break; + + case GDK_KP_Divide: + key_code = isChar ? '/' : WXK_NUMPAD_DIVIDE; + break; + + + // function keys + case GDK_F1: + case GDK_F2: + case GDK_F3: + case GDK_F4: + case GDK_F5: + case GDK_F6: + case GDK_F7: + case GDK_F8: + case GDK_F9: + case GDK_F10: + case GDK_F11: + case GDK_F12: + key_code = WXK_F1 + keysym - GDK_F1; + break; + + default: + key_code = 0; + } + + return key_code; +} diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 943d3a1edb..5fc0e136de 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -224,7 +224,6 @@ mtgsThreadObject::~mtgsThreadObject() void mtgsThreadObject::Cancel() { - Console::WriteLn( "MTGS > Closing GS thread..." ); SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 ); SetEvent(); m_sem_Quitter.Wait( wxTimeSpan( 0, 0, 5, 0 ) ); @@ -241,7 +240,7 @@ void mtgsThreadObject::Reset() AtomicExchange( m_RingPos, m_WritePos ); - MTGS_LOG( "MTGS > Sending Reset...\n" ); + MTGS_LOG( "MTGS: Sending Reset..." ); SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 ); SendSimplePacket( GS_RINGTYPE_FRAMESKIP, 0, 0, 0 ); @@ -501,15 +500,13 @@ struct PacketTagType sptr mtgsThreadObject::ExecuteTask() { - Console::WriteLn("MTGS > Thread Started, Opening GS Plugin..."); - memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(PS2MEM_GS) ); GSsetBaseMem( m_gsMem ); GSirqCallback( NULL ); GetPluginManager().Open( PluginId_GS ); - Console::WriteLn( "MTGS > GSopen Finished, return code: 0x%x", params m_returncode ); + DbgCon::WriteLn( "MTGS: GSopen Finished, return code: 0x%x", params m_returncode ); GSCSRr = 0x551B4000; // 0x55190000 m_sem_InitDone.Post(); @@ -642,14 +639,14 @@ sptr mtgsThreadObject::ExecuteTask() } case GS_RINGTYPE_RESET: - MTGS_LOG( "MTGS > Receiving Reset...\n" ); + MTGS_LOG( "MTGS: Receiving Reset..." ); if( GSreset != NULL ) GSreset(); break; case GS_RINGTYPE_SOFTRESET: { int mask = tag.data[0]; - MTGS_LOG( "MTGS > Receiving GIF Soft Reset (mask: %d)\n", mask ); + MTGS_LOG( "MTGS: Receiving GIF Soft Reset (mask: %d)", mask ); GSgifSoftReset( mask ); break; } @@ -1115,7 +1112,7 @@ void mtgsThreadObject::GIFSoftReset( int mask ) if( GSgifSoftReset == NULL ) return; - MTGS_LOG( "MTGS > Sending GIF Soft Reset (mask: %d)\n", mask ); + MTGS_LOG( "MTGS: Sending GIF Soft Reset (mask: %d)", mask ); mtgsThread->SendSimplePacket( GS_RINGTYPE_SOFTRESET, mask, 0, 0 ); } diff --git a/pcsx2/PathUtils.cpp b/pcsx2/PathUtils.cpp index f64f7741d0..bba9ad8cfb 100644 --- a/pcsx2/PathUtils.cpp +++ b/pcsx2/PathUtils.cpp @@ -43,30 +43,6 @@ static bool IsPathSeparator( wxChar src ) #endif } -bool Exists( const wxString& path ) -{ - wxStructStat sbuf; - return wxStat( path.c_str(), &sbuf ) == 0; -} - -// This function returns false if the path does not exist, or if the path exists and -// is a file. -bool IsDirectory( const wxString& path ) -{ - wxStructStat sbuf; - if( wxStat( path.c_str(), &sbuf ) == -1 ) return false; - return !!(sbuf.st_mode & _S_IFDIR); -} - -// This function returns false if the path does not exist, or if the path exists and -// is a directory. -bool IsFile( const wxString& path ) -{ - wxStructStat sbuf; - if( wxStat( path.c_str(), &sbuf ) == -1 ) return false; - return !!(sbuf.st_mode & _S_IFREG); -} - // Returns the length of the file. // returns -1 if the file is not found. int GetFileSize( const wxString& path ) diff --git a/pcsx2/Paths.h b/pcsx2/Paths.h index 42c7a3c531..a45ab90cc5 100644 --- a/pcsx2/Paths.h +++ b/pcsx2/Paths.h @@ -133,9 +133,6 @@ public: namespace Path { extern bool IsRooted( const wxString& path ); - extern bool IsDirectory( const wxString& path ); - extern bool IsFile( const wxString& path ); - extern bool Exists( const wxString& path ); extern int GetFileSize( const wxString& path ); extern wxString Combine( const wxString& srcPath, const wxString& srcFile ); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 4d5276e713..b9b2f7ad57 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -155,7 +155,6 @@ void Pcsx2Config::LoadSave( IniInterface& ini ) IniBitBool( CdvdDumpBlocks ); IniBitBool( EnablePatches ); - IniBitBool( closeGSonEsc ); IniBitBool( McdEnableEjection ); // Process various sub-components: diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 8f152db11d..9f589e990f 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -220,8 +220,10 @@ static const LegacyApi_CommonMethod s_MethMessCommon[] = { "close", NULL }, { "shutdown", NULL }, + { "keyEvent", (vMeth*)fallback_keyEvent }, + { "freeze", (vMeth*)fallback_freeze }, - { "test", (vMeth*)fallback_test }, + { "test", (vMeth*)fallback_test }, { "configure", fallback_configure }, { "about", fallback_about }, @@ -948,6 +950,19 @@ void PluginManager::Freeze( SaveState& state ) Freeze( pi->id, state ); } +bool PluginManager::KeyEvent( const keyEvent& evt ) +{ + const PluginInfo* pi = tbl_PluginInfo-1; + + while( ++pi, pi->shortname != NULL ) + { + if( pi->id != PluginId_PAD ) + m_info[pi->id].CommonBindings.KeyEvent( const_cast(&evt) ); + } + + return false; +} + void PluginManager::Configure( PluginsEnum_t pid ) { m_info[pid].CommonBindings.Configure(); diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index 0afe7caf99..1c3330836e 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -118,6 +118,7 @@ struct LegacyPluginAPI_Common void (CALLBACK* Close)(); void (CALLBACK* Shutdown)(); + void (CALLBACK* KeyEvent)( keyEvent* evt ); s32 (CALLBACK* Freeze)(int mode, freezeData *data); s32 (CALLBACK* Test)(); void (CALLBACK* Configure)(); @@ -167,6 +168,7 @@ public: virtual void Freeze( PluginsEnum_t pid, SaveState& state ) { wxASSERT_MSG( false, L"Null PluginManager!" ); } virtual void Freeze( SaveState& state ) { wxASSERT_MSG( false, L"Null PluginManager!" ); } + virtual bool KeyEvent( const keyEvent& evt ) { return false; } }; ////////////////////////////////////////////////////////////////////////////////////////// @@ -212,7 +214,8 @@ public: void Freeze( PluginsEnum_t pid, int mode, freezeData* data ); void Freeze( PluginsEnum_t pid, SaveState& state ); void Freeze( SaveState& state ); - + + bool KeyEvent( const keyEvent& evt ); void Configure( PluginsEnum_t pid ); friend PluginManager* PluginManager_Create( const wxString (&folders)[PluginId_Count] ); diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 23bc20fe2b..1b3c21982f 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -280,11 +280,6 @@ void SysClearExecutionCache() vuMicroCpuReset(); } -__forceinline void SysUpdate() -{ - HostGui::KeyEvent( PADkeyEvent() ); -} - bool EmulationInProgress() { return (g_EmuThread != NULL) && g_EmuThread->IsRunning(); @@ -319,9 +314,6 @@ void SysExecute( CoreEmuThread* newThread ) // saving states). No assertions or exceptions. void SysEndExecution() { - if( EmuConfig.closeGSonEsc ) - StateRecovery::MakeGsOnly(); - safe_delete( g_EmuThread ); } @@ -338,17 +330,6 @@ void SysResume() } -// Function provided to escape the emulation state, by shutting down plugins and saving -// the GS state. The execution state is effectively preserved, and can be resumed with a -// call to SysExecute. -/*void SysEndExecution() -{ - if( EmuConfig.closeGSonEsc ) - StateRecovery::MakeGsOnly(); - - ClosePlugins( EmuConfig.closeGSonEsc ); -}*/ - void SysRestorableReset() { if( !EmulationInProgress() ) return; diff --git a/pcsx2/System.h b/pcsx2/System.h index 471467d41b..a6d162aad4 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -34,7 +34,6 @@ class CoreEmuThread; extern bool SysInit(); extern void SysDetect(); // Detects cpu type and fills cpuInfo structs. extern void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers. -extern void SysUpdate(); // Called on VBlank (to update i.e. pads) extern void SysExecute( CoreEmuThread* newThread ); extern void SysExecute( CoreEmuThread* newThread, CDVD_SourceType cdvdsrc ); diff --git a/pcsx2/gui/AdvancedDialog.h b/pcsx2/gui/AdvancedDialog.h index fdbc6ac4f5..5e0c976c2e 100644 --- a/pcsx2/gui/AdvancedDialog.h +++ b/pcsx2/gui/AdvancedDialog.h @@ -16,9 +16,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef ADVANCEDDIALOG_H_INCLUDED -#define ADVANCEDDIALOG_H_INCLUDED - - - -#endif // ADVANCEDDIALOG_H_INCLUDED +#ifndef ADVANCEDDIALOG_H_INCLUDED +#define ADVANCEDDIALOG_H_INCLUDED + + + +#endif // ADVANCEDDIALOG_H_INCLUDED diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 48eccba275..6ea31d8aaf 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -287,13 +287,15 @@ public: protected: void ReadUserModeSettings(); bool TryOpenConfigCwd(); - void OnSemaphorePing( wxCommandEvent& evt ); - void OnMessageBox( pxMessageBoxEvent& evt ); void CleanupMess(); void OpenWizardConsole(); void HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const; + void OnSemaphorePing( wxCommandEvent& evt ); + void OnMessageBox( pxMessageBoxEvent& evt ); + void OnKeyDown( wxKeyEvent& evt ); + // ---------------------------------------------------------------------------- // Override wx default exception handling behavior // ---------------------------------------------------------------------------- @@ -313,11 +315,15 @@ protected: // class AppEmuThread : public CoreEmuThread { +protected: + wxKeyEvent m_kevt; + public: AppEmuThread( const wxString& elf_file=wxEmptyString ); virtual ~AppEmuThread() { } virtual void Resume(); + virtual void StateCheck(); protected: sptr ExecuteTask(); @@ -334,3 +340,5 @@ extern void OpenPlugins(); extern wxRect wxGetDisplayArea(); extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos ); + +extern void ProcessFKeys(int fkey, struct KeyModifiers *keymod); \ No newline at end of file diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index 4c3ff666c3..274d15b994 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -333,6 +333,12 @@ void wxDirName::Rmdir() bool wxDirName::Mkdir() { if( Exists() ) return true; + + // Recursively create child directories as needed: + wxDirName recurse( *this ); + recurse.RemoveLastDir(); + if( !recurse.Mkdir() ) return false; + return wxFileName::Mkdir(); } @@ -361,6 +367,7 @@ AppConfig::AppConfig() : , Toolbar_ShowLabels( true ) , McdEnableNTFS( true ) +, CloseGSonEsc( true ) , CurrentIso() , CdvdSource( CDVDsrc_Iso ) diff --git a/pcsx2/gui/AppConfig.h b/pcsx2/gui/AppConfig.h index 326522d457..ef3789183c 100644 --- a/pcsx2/gui/AppConfig.h +++ b/pcsx2/gui/AppConfig.h @@ -1,176 +1,179 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2009 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "CDVD/CDVDaccess.h" - -class IniInterface; - -extern bool UseAdminMode; // dictates if the program uses /home/user or /cwd for the program data - -////////////////////////////////////////////////////////////////////////////////////////// -// Pcsx2 Application Configuration. -// -// -class AppConfig -{ -public: - // ------------------------------------------------------------------------ - struct ConsoleLogOptions - { - bool Visible; - // if true, DisplayPos is ignored and the console is automatically docked to the main window. - bool AutoDock; - // Display position used if AutoDock is false (ignored otherwise) - wxPoint DisplayPosition; - wxSize DisplaySize; - - // Size of the font in points. - int FontSize; - - ConsoleLogOptions(); - void LoadSave( IniInterface& conf, const wxChar* title ); - }; - - // ------------------------------------------------------------------------ - struct FolderOptions - { - BITFIELD32() - bool - UseDefaultPlugins:1, - UseDefaultSettings:1, - UseDefaultBios:1, - UseDefaultSnapshots:1, - UseDefaultSavestates:1, - UseDefaultMemoryCards:1, - UseDefaultLogs:1; - }; }; - - wxDirName - Plugins, - Settings, - Bios, - Snapshots, - Savestates, - MemoryCards, - Logs; - - wxDirName RunIso; // last used location for Iso loading. - - FolderOptions(); - void LoadSave( IniInterface& conf ); - void ApplyDefaults(); - - void Set( FoldersEnum_t folderidx, const wxString& src, bool useDefault ); - - const wxDirName& operator[]( FoldersEnum_t folderidx ) const; - const bool IsDefault( FoldersEnum_t folderidx ) const; - }; - - // ------------------------------------------------------------------------ - struct FilenameOptions - { - wxFileName Bios; - wxFileName Plugins[PluginId_Count]; - - void LoadSave( IniInterface& conf ); - - const wxFileName& operator[]( PluginsEnum_t pluginidx ) const; - }; - - // ------------------------------------------------------------------------ - // Options struct for each memory card. - // - struct McdOptions - { - wxFileName Filename; // user-configured location of this memory card - bool Enabled; // memory card enabled (if false, memcard will not show up in-game) - }; - -public: - wxPoint MainGuiPosition; - - // Because remembering the last used tab on the settings panel is cool (tab is remembered - // by it's UTF/ASCII name). - wxString SettingsTabName; - - // Current language in use (correlates to a wxWidgets wxLANGUAGE specifier) - wxLanguage LanguageId; - - int RecentFileCount; // number of files displayed in the Recent Isos list. - - // String value describing the desktop theme to use for pcsk2 (icons and background images) - // The theme name is used to look up files in the themes folder (relative to the executable). - wxString DeskTheme; - - // Specifies the size of icons used in Listbooks; specifically the PCSX2 Properties dialog box. - // Realistic values range from 96x96 to 24x24. - int Listbook_ImageSize; - - // Specifies the size of each toolbar icon, in pixels (any value >= 2 is valid, but realistically - // values should be between 64 and 16 for usability reasons) - int Toolbar_ImageSize; - - // Enables display of toolbar text labels. - bool Toolbar_ShowLabels; - - // enables automatic ntfs compression of memory cards (Win32 only) - bool McdEnableNTFS; - - wxString CurrentIso; - CDVD_SourceType CdvdSource; - - McdOptions Mcd[2]; - ConsoleLogOptions ProgLogBox; - ConsoleLogOptions Ps2ConBox; - FolderOptions Folders; - FilenameOptions BaseFilenames; - - // PCSX2-core emulation options, which are passed to the emu core prior to initiating - // an emulation session. Note these are the options saved into the GUI ini file and - // which are shown as options in the gui preferences, but *not* necessarily the options - // used by emulation. The gui allows temporary per-game and commandline level overrides. - Pcsx2Config EmuOptions; - -public: - AppConfig(); - - wxString FullpathToBios() const; - wxString FullpathToMcd( uint mcdidx ) const; - wxString FullpathTo( PluginsEnum_t pluginId ) const; - wxString FullPathToConfig() const; - - void LoadSaveUserMode( IniInterface& ini, const wxString& cwdhash ); - - wxString GetDefaultDocumentsFolder(); - -protected: - void Apply(); - void LoadSave( IniInterface& ini ); - void LoadSaveMemcards( IniInterface& ini ); - - friend class Pcsx2App; -}; - -class wxFileConfig; // forward declare. - -extern wxFileConfig* OpenFileConfig( const wxString& filename ); -extern void AppConfig_ReloadGlobalSettings( bool overwrite = false ); - -extern AppConfig* g_Conf; +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2009 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#include "CDVD/CDVDaccess.h" + +class IniInterface; + +extern bool UseAdminMode; // dictates if the program uses /home/user or /cwd for the program data + +////////////////////////////////////////////////////////////////////////////////////////// +// Pcsx2 Application Configuration. +// +// +class AppConfig +{ +public: + // ------------------------------------------------------------------------ + struct ConsoleLogOptions + { + bool Visible; + // if true, DisplayPos is ignored and the console is automatically docked to the main window. + bool AutoDock; + // Display position used if AutoDock is false (ignored otherwise) + wxPoint DisplayPosition; + wxSize DisplaySize; + + // Size of the font in points. + int FontSize; + + ConsoleLogOptions(); + void LoadSave( IniInterface& conf, const wxChar* title ); + }; + + // ------------------------------------------------------------------------ + struct FolderOptions + { + BITFIELD32() + bool + UseDefaultPlugins:1, + UseDefaultSettings:1, + UseDefaultBios:1, + UseDefaultSnapshots:1, + UseDefaultSavestates:1, + UseDefaultMemoryCards:1, + UseDefaultLogs:1; + }; }; + + wxDirName + Plugins, + Settings, + Bios, + Snapshots, + Savestates, + MemoryCards, + Logs; + + wxDirName RunIso; // last used location for Iso loading. + + FolderOptions(); + void LoadSave( IniInterface& conf ); + void ApplyDefaults(); + + void Set( FoldersEnum_t folderidx, const wxString& src, bool useDefault ); + + const wxDirName& operator[]( FoldersEnum_t folderidx ) const; + const bool IsDefault( FoldersEnum_t folderidx ) const; + }; + + // ------------------------------------------------------------------------ + struct FilenameOptions + { + wxFileName Bios; + wxFileName Plugins[PluginId_Count]; + + void LoadSave( IniInterface& conf ); + + const wxFileName& operator[]( PluginsEnum_t pluginidx ) const; + }; + + // ------------------------------------------------------------------------ + // Options struct for each memory card. + // + struct McdOptions + { + wxFileName Filename; // user-configured location of this memory card + bool Enabled; // memory card enabled (if false, memcard will not show up in-game) + }; + +public: + wxPoint MainGuiPosition; + + // Because remembering the last used tab on the settings panel is cool (tab is remembered + // by it's UTF/ASCII name). + wxString SettingsTabName; + + // Current language in use (correlates to a wxWidgets wxLANGUAGE specifier) + wxLanguage LanguageId; + + int RecentFileCount; // number of files displayed in the Recent Isos list. + + // String value describing the desktop theme to use for pcsk2 (icons and background images) + // The theme name is used to look up files in the themes folder (relative to the executable). + wxString DeskTheme; + + // Specifies the size of icons used in Listbooks; specifically the PCSX2 Properties dialog box. + // Realistic values range from 96x96 to 24x24. + int Listbook_ImageSize; + + // Specifies the size of each toolbar icon, in pixels (any value >= 2 is valid, but realistically + // values should be between 64 and 16 for usability reasons) + int Toolbar_ImageSize; + + // Enables display of toolbar text labels. + bool Toolbar_ShowLabels; + + // enables automatic ntfs compression of memory cards (Win32 only) + bool McdEnableNTFS; + + // Closes the GS/Video port on escape (good for fullscreen activity) + bool CloseGSonEsc; + + wxString CurrentIso; + CDVD_SourceType CdvdSource; + + McdOptions Mcd[2]; + ConsoleLogOptions ProgLogBox; + ConsoleLogOptions Ps2ConBox; + FolderOptions Folders; + FilenameOptions BaseFilenames; + + // PCSX2-core emulation options, which are passed to the emu core prior to initiating + // an emulation session. Note these are the options saved into the GUI ini file and + // which are shown as options in the gui preferences, but *not* necessarily the options + // used by emulation. The gui allows temporary per-game and commandline level overrides. + Pcsx2Config EmuOptions; + +public: + AppConfig(); + + wxString FullpathToBios() const; + wxString FullpathToMcd( uint mcdidx ) const; + wxString FullpathTo( PluginsEnum_t pluginId ) const; + wxString FullPathToConfig() const; + + void LoadSaveUserMode( IniInterface& ini, const wxString& cwdhash ); + + wxString GetDefaultDocumentsFolder(); + +protected: + void Apply(); + void LoadSave( IniInterface& ini ); + void LoadSaveMemcards( IniInterface& ini ); + + friend class Pcsx2App; +}; + +class wxFileConfig; // forward declare. + +extern wxFileConfig* OpenFileConfig( const wxString& filename ); +extern void AppConfig_ReloadGlobalSettings( bool overwrite = false ); + +extern AppConfig* g_Conf; diff --git a/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp b/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp index bd5934066b..b2c34b1bf4 100644 --- a/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp +++ b/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp @@ -59,11 +59,13 @@ Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent ) : void Dialogs::ImportSettingsDialog::OnImport_Click( __unused wxCommandEvent& evt ) { AppConfig_ReloadGlobalSettings( false ); // ... and import existing settings + g_Conf->Folders.Bios.Mkdir(); EndModal( wxID_OK ); } void Dialogs::ImportSettingsDialog::OnOverwrite_Click( __unused wxCommandEvent& evt ) { AppConfig_ReloadGlobalSettings( true ); // ... and overwrite any existing settings + g_Conf->Folders.Bios.Mkdir(); EndModal( wxID_OK ); } diff --git a/pcsx2/gui/Dialogs/LogOptionsDialog.h b/pcsx2/gui/Dialogs/LogOptionsDialog.h index 77891cae2d..39cc203470 100644 --- a/pcsx2/gui/Dialogs/LogOptionsDialog.h +++ b/pcsx2/gui/Dialogs/LogOptionsDialog.h @@ -1,75 +1,75 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2009 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#pragma once - -#include -#include - -#include "wxHelpers.h" -#include "CheckedStaticBox.h" - -namespace Dialogs { - -class LogOptionsDialog: public wxDialogWithHelpers -{ -public: - LogOptionsDialog( wxWindow* parent, int id, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize ); - -protected: - - // ---------------------------------------------------------------------------- - class iopLogOptionsPanel : public CheckedStaticBox - { - public: - iopLogOptionsPanel( wxWindow* parent ); - void OnLogChecked(wxCommandEvent &event); - - }; - - // ---------------------------------------------------------------------------- - class eeLogOptionsPanel : public CheckedStaticBox - { - public: - eeLogOptionsPanel( wxWindow* parent ); - void OnLogChecked(wxCommandEvent &event); - - protected: - class DisasmPanel : public CheckedStaticBox - { - public: - DisasmPanel( wxWindow* parent ); - void OnLogChecked(wxCommandEvent &event); - }; - - class HwPanel : public CheckedStaticBox - { - public: - HwPanel( wxWindow* parent ); - void OnLogChecked(wxCommandEvent &event); - }; - }; - - -public: - void LogChecked(wxCommandEvent &event); - -protected: -}; - +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2009 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include "wxHelpers.h" +#include "CheckedStaticBox.h" + +namespace Dialogs { + +class LogOptionsDialog: public wxDialogWithHelpers +{ +public: + LogOptionsDialog( wxWindow* parent, int id, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize ); + +protected: + + // ---------------------------------------------------------------------------- + class iopLogOptionsPanel : public CheckedStaticBox + { + public: + iopLogOptionsPanel( wxWindow* parent ); + void OnLogChecked(wxCommandEvent &event); + + }; + + // ---------------------------------------------------------------------------- + class eeLogOptionsPanel : public CheckedStaticBox + { + public: + eeLogOptionsPanel( wxWindow* parent ); + void OnLogChecked(wxCommandEvent &event); + + protected: + class DisasmPanel : public CheckedStaticBox + { + public: + DisasmPanel( wxWindow* parent ); + void OnLogChecked(wxCommandEvent &event); + }; + + class HwPanel : public CheckedStaticBox + { + public: + HwPanel( wxWindow* parent ); + void OnLogChecked(wxCommandEvent &event); + }; + }; + + +public: + void LogChecked(wxCommandEvent &event); + +protected: +}; + }; // end namespace Dialogs \ No newline at end of file diff --git a/pcsx2/gui/HostGui.cpp b/pcsx2/gui/HostGui.cpp index 3e48809e9d..249b5a2e4b 100644 --- a/pcsx2/gui/HostGui.cpp +++ b/pcsx2/gui/HostGui.cpp @@ -33,12 +33,6 @@ bool renderswitch = false; namespace HostGui { - static const int NUM_STATES = 10; - - static int StatesC = 0; - static int g_Pcsx2Recording = 0; // true 1 if recording video and sound - - // Sets the status bar message without mirroring the output to the console. void SetStatusMsg( const wxString& text ) { @@ -51,124 +45,129 @@ namespace HostGui Console::Status( text.c_str() ); SetStatusMsg( text ); } +} - static wxString GetGSStateFilename() +static const int NUM_STATES = 10; +static int StatesC = 0; +static int g_Pcsx2Recording = 0; // true 1 if recording video and sound + +static wxString GetGSStateFilename() +{ + return Path::Combine( g_Conf->Folders.Savestates, wxsFormat( L"/%8.8X.%d.gs", ElfCRC, StatesC ) ); +} + +void Pcsx2App::OnKeyDown( wxKeyEvent& evt ) +{ + switch( evt.GetKeyCode() ) { - return Path::Combine( g_Conf->Folders.Savestates, wxsFormat( L"/%8.8X.%d.gs", ElfCRC, StatesC ) ); - } - - static void ProcessFKeys(int fkey, struct KeyModifiers *keymod) - { - assert(fkey >= 1 && fkey <= 12 ); - - switch(fkey) - { - case 1: - States_Save( StatesC ); - break; - - case 2: - if( keymod->shift ) - StatesC = (StatesC+NUM_STATES-1) % NUM_STATES; - else - StatesC = (StatesC+1) % NUM_STATES; - - Console::Notice( " > Selected savestate slot %d", params StatesC); - - if( GSchangeSaveState != NULL ) - GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).mb_str()); - break; - - case 3: - States_Load( StatesC ); - break; - - case 4: - // FIXME : Reimplement framelimiting using new oolean system - //CycleFrameLimit(keymod->shift ? -1 : 1); - break; - - // note: VK_F5-VK_F7 are reserved for GS - case 8: - GSmakeSnapshot( g_Conf->Folders.Snapshots.ToAscii().data() ); - break; - - case 9: //gsdx "on the fly" renderer switching - - SysSuspend(); + case WXK_ESCAPE: + if( g_Conf->CloseGSonEsc ) StateRecovery::MakeGsOnly(); - GetPluginManager().Close( PluginId_GS ); - renderswitch = !renderswitch; + SysEndExecution(); + break; + + case WXK_F1: + States_Save( StatesC ); + break; + + case WXK_F2: + if( evt.GetModifiers() & wxMOD_SHIFT ) + StatesC = (StatesC+NUM_STATES-1) % NUM_STATES; + else + StatesC = (StatesC+1) % NUM_STATES; + + Console::Notice( " > Selected savestate slot %d", params StatesC); + + if( GSchangeSaveState != NULL ) + GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).mb_str()); + break; + + case WXK_F3: + States_Load( StatesC ); + break; + + case WXK_F4: + // FIXME : Reimplement framelimiting using new oolean system + //CycleFrameLimit(keymod->shift ? -1 : 1); + break; + + // note: VK_F5-VK_F7 are reserved for GS + case WXK_F8: + GSmakeSnapshot( g_Conf->Folders.Snapshots.ToAscii().data() ); + break; + + case WXK_F9: //gsdx "on the fly" renderer switching + + SysSuspend(); + StateRecovery::MakeGsOnly(); + + GetPluginManager().Close( PluginId_GS ); + renderswitch = !renderswitch; + + StateRecovery::Recover(); + SysResume(); + break; + +#ifdef PCSX2_DEVBUILD + case WXK_F10: + // There's likely a better way to implement this, but this seemed useful. + // I might add turning EE, VU0, and VU1 recs on and off by hotkey at some point, too. + // --arcum42 + enableLogging = !enableLogging; + + if (enableLogging) + GSprintf(10, "Logging Enabled."); + else + GSprintf(10,"Logging Disabled."); - StateRecovery::Recover(); - SysResume(); break; - - #ifdef PCSX2_DEVBUILD - case 10: - // There's likely a better way to implement this, but this seemed useful. - // I might add turning EE, VU0, and VU1 recs on and off by hotkey at some point, too. - // --arcum42 - enableLogging = !enableLogging; - if (enableLogging) - GSprintf(10, "Logging Enabled."); - else - GSprintf(10,"Logging Disabled."); + case WXK_F11: + Console::Notice( "Cannot make gsstates in MTGS mode" ); - break; + // fixme : fix up gsstate mess and make it mtgs compatible -- air +#ifdef _STGS_GSSTATE_CODE + wxString Text; + if( strgametitle[0] != 0 ) + { + // only take the first two words + wxString gsText; - case 11: - Console::Notice( "Cannot make gsstates in MTGS mode" ); + wxStringTokenizer parts( strgametitle, L" " ); - // fixme : fix up gsstate mess and make it mtgs compatible -- air - #ifdef _STGS_GSSTATE_CODE - wxString Text; - if( strgametitle[0] != 0 ) - { - // only take the first two words - wxString gsText; + wxString name( parts.GetNextToken() ); // first part + wxString part2( parts.GetNextToken() ); - wxStringTokenizer parts( strgametitle, L" " ); + if( !!part2 ) + name += L"_" + part2; - wxString name( parts.GetNextToken() ); // first part - wxString part2( parts.GetNextToken() ); + gsText.Printf( L"%s.%d.gs", name.c_str(), StatesC ); + Text = Path::Combine( g_Conf->Folders.Savestates, gsText ); + } + else + { + Text = GetGSStateFilename(); + } + break; +#endif +#endif - if( !!part2 ) - name += L"_" + part2; + case WXK_F12: + if( evt.GetModifiers() & wxMOD_SHIFT ) + { +#ifdef PCSX2_DEVBUILD + iDumpRegisters(cpuRegs.pc, 0); + Console::Notice("hardware registers dumped EE:%x, IOP:%x\n", params cpuRegs.pc, psxRegs.pc); +#endif + } + else + { + g_Pcsx2Recording ^= 1; - gsText.Printf( L"%s.%d.gs", name.c_str(), StatesC ); - Text = Path::Combine( g_Conf->Folders.Savestates, gsText ); - } - else - { - Text = GetGSStateFilename(); - } - break; - #endif - #endif - - case 12: - if( keymod->shift ) - { - #ifdef PCSX2_DEVBUILD - iDumpRegisters(cpuRegs.pc, 0); - Console::Notice("hardware registers dumped EE:%x, IOP:%x\n", params cpuRegs.pc, psxRegs.pc); - #endif - } - else - { - g_Pcsx2Recording ^= 1; - - mtgsThread->SendSimplePacket(GS_RINGTYPE_RECORD, g_Pcsx2Recording, 0, 0); - if( SPU2setupRecording != NULL ) SPU2setupRecording(g_Pcsx2Recording, NULL); - } - break; - } - } - - void __fastcall KeyEvent( keyEvent* ev ) - { + mtgsThread->SendSimplePacket(GS_RINGTYPE_RECORD, g_Pcsx2Recording, 0, 0); + if( SPU2setupRecording != NULL ) SPU2setupRecording(g_Pcsx2Recording, NULL); + } + break; } } diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h index cfc11f0345..c51c800f8d 100644 --- a/pcsx2/gui/MainFrame.h +++ b/pcsx2/gui/MainFrame.h @@ -102,6 +102,8 @@ protected: void Menu_ShowConsole(wxCommandEvent &event); void Menu_ShowAboutBox(wxCommandEvent &event); + bool _DoSelectIsoBrowser(); + // ------------------------------------------------------------------------ // MainEmuFram Internal API for Populating Main Menu Contents // ------------------------------------------------------------------------ diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index 7cd209198c..43733ae280 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -1,192 +1,198 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2009 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "PrecompiledHeader.h" -#include "HostGui.h" -#include "CDVD/CDVD.h" - -#include "MainFrame.h" -#include "Dialogs/ModalPopups.h" -#include "Dialogs/ConfigurationDialog.h" -#include "Dialogs/LogOptionsDialog.h" - -using namespace Dialogs; - - -void MainEmuFrame::Menu_ConfigSettings_Click(wxCommandEvent &event) -{ - if( Dialogs::ConfigurationDialog( this ).ShowModal() ) - { - wxGetApp().SaveSettings(); - } -} - -void MainEmuFrame::Menu_SelectBios_Click(wxCommandEvent &event) -{ - if( Dialogs::BiosSelectorDialog( this ).ShowModal() ) - { - wxGetApp().SaveSettings(); - } -} - -void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event ) -{ - switch( event.GetId() ) - { - case MenuId_Src_Iso: g_Conf->CdvdSource = CDVDsrc_Iso; break; - case MenuId_Src_Plugin: g_Conf->CdvdSource = CDVDsrc_Plugin; break; - case MenuId_Src_NoDisc: g_Conf->CdvdSource = CDVDsrc_NoDisc; break; - - jNO_DEFAULT - } - UpdateIsoSrcSelection(); - wxGetApp().SaveSettings(); -} - -void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event ) -{ - if( EmulationInProgress() ) - { - SysSuspend(); - - // [TODO] : Add one of 'dems checkboxes that read like "[x] don't show this stupid shit again, kthx." - bool result = Msgbox::OkCancel( pxE( ".Popup:ConfirmEmuReset", L"This will reset the emulator and your current emulation session will be lost. Are you sure?") ); - - if( !result ) - { - SysResume(); - return; - } - } - - SysEndExecution(); - InitPlugins(); - - CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso ); - SysExecute( new AppEmuThread(), g_Conf->CdvdSource ); -} - -static const wxChar* isoFilterTypes = - L"All Supported (.iso .mdf .nrg .bin .img .dump)|*.iso;*.mdf;*.nrg;*.bin;*.img;*.dump|" - L"Disc Images (.iso .mdf .nrg .bin .img)|*.iso;*.mdf;*.nrg;*.bin;*.img|" - L"Blockdumps (.dump)|*.dump|" - L"All Files (*.*)|*.*"; - - -void MainEmuFrame::Menu_IsoBrowse_Click( wxCommandEvent &event ) -{ - SysSuspend(); - - wxFileDialog ctrl( this, _("Select CDVD source iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString, - isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); - - if( ctrl.ShowModal() != wxID_CANCEL ) - { - g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath(); - g_Conf->CurrentIso = ctrl.GetPath(); - wxGetApp().SaveSettings(); - - UpdateIsoSrcFile(); - } - - SysResume(); -} - -void MainEmuFrame::Menu_RunIso_Click( wxCommandEvent &event ) -{ - SysSuspend(); - - wxFileDialog ctrl( this, _("Run PS2 Iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString, - isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); - - if( ctrl.ShowModal() == wxID_CANCEL ) - { - SysResume(); - return; - } - - SysEndExecution(); - - g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath(); - g_Conf->CurrentIso = ctrl.GetPath(); - wxGetApp().SaveSettings(); - - UpdateIsoSrcFile(); - - wxString elf_file; - if( EmuConfig.SkipBiosSplash ) - { - // Fetch the ELF filename and CD type from the CDVD provider. - wxString ename( g_Conf->CurrentIso ); - int result = GetPS2ElfName( ename ); - switch( result ) - { - case 0: - Msgbox::Alert( _("Boot failed: CDVD image is not a PS1 or PS2 game.") ); - return; - - case 1: - Msgbox::Alert( _("Boot failed: PCSX2 does not support emulation of PS1 games.") ); - return; - - case 2: - // PS2 game. Valid! - elf_file = ename; - break; - - jNO_DEFAULT - } - } - - InitPlugins(); - SysExecute( new AppEmuThread( elf_file ), CDVDsrc_Iso ); -} - -/*void MainEmuFrame::Menu_RunWithoutDisc_Click(wxCommandEvent &event) -{ - if( EmulationInProgress() ) - { - SysSuspend(); - - // [TODO] : Add one of 'dems checkboxes that read like "[x] don't show this stupid shit again, kthx." - bool result = Msgbox::OkCancel( pxE( ".Popup:ConfirmEmuReset", L"This will reset the emulator and your current emulation session will be lost. Are you sure?") ); - - if( !result ) - { - SysResume(); - return; - } - } - - SysEndExecution(); - InitPlugins(); - SysExecute( new AppEmuThread(), CDVDsrc_NoDisc ); -}*/ - -void MainEmuFrame::Menu_IsoRecent_Click(wxCommandEvent &event) -{ - //Console::Status( "%d", params event.GetId() - g_RecentIsoList->GetBaseId() ); - //Console::WriteLn( Color_Magenta, g_RecentIsoList->GetHistoryFile( event.GetId() - g_RecentIsoList->GetBaseId() ) ); -} - -void MainEmuFrame::Menu_OpenELF_Click(wxCommandEvent &event) -{ -} +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2009 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "PrecompiledHeader.h" +#include "HostGui.h" +#include "CDVD/CDVD.h" + +#include "MainFrame.h" +#include "Dialogs/ModalPopups.h" +#include "Dialogs/ConfigurationDialog.h" +#include "Dialogs/LogOptionsDialog.h" + +using namespace Dialogs; + + +void MainEmuFrame::Menu_ConfigSettings_Click(wxCommandEvent &event) +{ + if( Dialogs::ConfigurationDialog( this ).ShowModal() ) + { + wxGetApp().SaveSettings(); + } +} + +void MainEmuFrame::Menu_SelectBios_Click(wxCommandEvent &event) +{ + if( Dialogs::BiosSelectorDialog( this ).ShowModal() ) + { + wxGetApp().SaveSettings(); + } +} + +void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event ) +{ + switch( event.GetId() ) + { + case MenuId_Src_Iso: g_Conf->CdvdSource = CDVDsrc_Iso; break; + case MenuId_Src_Plugin: g_Conf->CdvdSource = CDVDsrc_Plugin; break; + case MenuId_Src_NoDisc: g_Conf->CdvdSource = CDVDsrc_NoDisc; break; + + jNO_DEFAULT + } + UpdateIsoSrcSelection(); + wxGetApp().SaveSettings(); +} + +// Returns FALSE if the user cancelled the action. +bool MainEmuFrame::_DoSelectIsoBrowser() +{ + static const wxChar* isoFilterTypes = + L"All Supported (.iso .mdf .nrg .bin .img .dump)|*.iso;*.mdf;*.nrg;*.bin;*.img;*.dump|" + L"Disc Images (.iso .mdf .nrg .bin .img)|*.iso;*.mdf;*.nrg;*.bin;*.img|" + L"Blockdumps (.dump)|*.dump|" + L"All Files (*.*)|*.*"; + + wxFileDialog ctrl( this, _("Select CDVD source iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString, + isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); + + if( ctrl.ShowModal() != wxID_CANCEL ) + { + g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath(); + g_Conf->CurrentIso = ctrl.GetPath(); + wxGetApp().SaveSettings(); + + UpdateIsoSrcFile(); + return true; + } + + return false; +} + +void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event ) +{ + SysSuspend(); + + if( !wxFileExists( g_Conf->CurrentIso ) ) + { + if( !_DoSelectIsoBrowser() ) + { + SysResume(); + return; + } + } + + if( EmulationInProgress() ) + { + // [TODO] : Add one of 'dems checkboxes that read like "[x] don't show this stupid shit again, kthx." + bool result = Msgbox::OkCancel( pxE( ".Popup:ConfirmEmuReset", L"This will reset the emulator and your current emulation session will be lost. Are you sure?") ); + + if( !result ) + { + SysResume(); + return; + } + } + + SysEndExecution(); + InitPlugins(); + + CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso ); + SysExecute( new AppEmuThread(), g_Conf->CdvdSource ); +} + +void MainEmuFrame::Menu_IsoBrowse_Click( wxCommandEvent &event ) +{ + SysSuspend(); + _DoSelectIsoBrowser(); + SysResume(); +} + +void MainEmuFrame::Menu_RunIso_Click( wxCommandEvent &event ) +{ + SysSuspend(); + + if( !_DoSelectIsoBrowser() ) + { + SysResume(); + return; + } + + SysEndExecution(); + + wxString elf_file; + if( EmuConfig.SkipBiosSplash ) + { + // Fetch the ELF filename and CD type from the CDVD provider. + wxString ename( g_Conf->CurrentIso ); + int result = GetPS2ElfName( ename ); + switch( result ) + { + case 0: + Msgbox::Alert( _("Boot failed: CDVD image is not a PS1 or PS2 game.") ); + return; + + case 1: + Msgbox::Alert( _("Boot failed: PCSX2 does not support emulation of PS1 games.") ); + return; + + case 2: + // PS2 game. Valid! + elf_file = ename; + break; + + jNO_DEFAULT + } + } + + InitPlugins(); + SysExecute( new AppEmuThread( elf_file ), CDVDsrc_Iso ); +} + +/*void MainEmuFrame::Menu_RunWithoutDisc_Click(wxCommandEvent &event) +{ + if( EmulationInProgress() ) + { + SysSuspend(); + + // [TODO] : Add one of 'dems checkboxes that read like "[x] don't show this stupid shit again, kthx." + bool result = Msgbox::OkCancel( pxE( ".Popup:ConfirmEmuReset", L"This will reset the emulator and your current emulation session will be lost. Are you sure?") ); + + if( !result ) + { + SysResume(); + return; + } + } + + SysEndExecution(); + InitPlugins(); + SysExecute( new AppEmuThread(), CDVDsrc_NoDisc ); +}*/ + +void MainEmuFrame::Menu_IsoRecent_Click(wxCommandEvent &event) +{ + //Console::Status( "%d", params event.GetId() - g_RecentIsoList->GetBaseId() ); + //Console::WriteLn( Color_Magenta, g_RecentIsoList->GetHistoryFile( event.GetId() - g_RecentIsoList->GetBaseId() ) ); +} + +void MainEmuFrame::Menu_OpenELF_Click(wxCommandEvent &event) +{ +} void MainEmuFrame::Menu_LoadStates_Click(wxCommandEvent &event) { @@ -199,82 +205,82 @@ void MainEmuFrame::Menu_SaveStates_Click(wxCommandEvent &event) int id = event.GetId() - MenuId_State_Save01 - 1; Console::WriteLn("If this were hooked up, it would save slot %d.", params id); } - -void MainEmuFrame::Menu_LoadStateOther_Click(wxCommandEvent &event) + +void MainEmuFrame::Menu_LoadStateOther_Click(wxCommandEvent &event) { - Console::WriteLn("If this were hooked up, it would load a savestate file."); -} - -void MainEmuFrame::Menu_SaveStateOther_Click(wxCommandEvent &event) + Console::WriteLn("If this were hooked up, it would load a savestate file."); +} + +void MainEmuFrame::Menu_SaveStateOther_Click(wxCommandEvent &event) { - Console::WriteLn("If this were hooked up, it would save a savestate file."); -} - -void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event) -{ - SysReset(); - Close(); -} - -void MainEmuFrame::Menu_EmuClose_Click(wxCommandEvent &event) -{ - SysReset(); - GetMenuBar()->Check( MenuId_Emu_Pause, false ); -} - -void MainEmuFrame::Menu_EmuPause_Click(wxCommandEvent &event) -{ - if( event.IsChecked() ) - SysSuspend(); - else - SysResume(); -} - -void MainEmuFrame::Menu_EmuReset_Click(wxCommandEvent &event) -{ - bool wasRunning = EmulationInProgress(); - SysReset(); - - GetMenuBar()->Check( MenuId_Emu_Pause, false ); - - if( !wasRunning ) return; - InitPlugins(); - SysExecute( new AppEmuThread() ); -} - -void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent &event) -{ - typedef void (CALLBACK* PluginConfigureFnptr)(); - const PluginsEnum_t pid = (PluginsEnum_t)( event.GetId() - MenuId_Config_GS ); - - LoadPlugins(); - ScopedWindowDisable disabler( this ); - g_plugins->Configure( pid ); -} - -void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent &event) -{ -} - -void MainEmuFrame::Menu_Debug_MemoryDump_Click(wxCommandEvent &event) -{ -} - -void MainEmuFrame::Menu_Debug_Logging_Click(wxCommandEvent &event) -{ - LogOptionsDialog( this, wxID_ANY ).ShowModal(); -} - -void MainEmuFrame::Menu_ShowConsole(wxCommandEvent &event) -{ - // Use messages to relay open/close commands (thread-safe) - - g_Conf->ProgLogBox.Visible = event.IsChecked(); - wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED, g_Conf->ProgLogBox.Visible ? wxID_OPEN : wxID_CLOSE ); - wxGetApp().ProgramLog_PostEvent( evt ); -} - -void MainEmuFrame::Menu_ShowAboutBox(wxCommandEvent &event) -{ - AboutBoxDialog( this, wxID_ANY ).ShowModal(); -} + Console::WriteLn("If this were hooked up, it would save a savestate file."); +} + +void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event) +{ + SysReset(); + Close(); +} + +void MainEmuFrame::Menu_EmuClose_Click(wxCommandEvent &event) +{ + SysReset(); + GetMenuBar()->Check( MenuId_Emu_Pause, false ); +} + +void MainEmuFrame::Menu_EmuPause_Click(wxCommandEvent &event) +{ + if( event.IsChecked() ) + SysSuspend(); + else + SysResume(); +} + +void MainEmuFrame::Menu_EmuReset_Click(wxCommandEvent &event) +{ + bool wasRunning = EmulationInProgress(); + SysReset(); + + GetMenuBar()->Check( MenuId_Emu_Pause, false ); + + if( !wasRunning ) return; + InitPlugins(); + SysExecute( new AppEmuThread() ); +} + +void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent &event) +{ + typedef void (CALLBACK* PluginConfigureFnptr)(); + const PluginsEnum_t pid = (PluginsEnum_t)( event.GetId() - MenuId_Config_GS ); + + LoadPlugins(); + ScopedWindowDisable disabler( this ); + g_plugins->Configure( pid ); +} + +void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent &event) +{ +} + +void MainEmuFrame::Menu_Debug_MemoryDump_Click(wxCommandEvent &event) +{ +} + +void MainEmuFrame::Menu_Debug_Logging_Click(wxCommandEvent &event) +{ + LogOptionsDialog( this, wxID_ANY ).ShowModal(); +} + +void MainEmuFrame::Menu_ShowConsole(wxCommandEvent &event) +{ + // Use messages to relay open/close commands (thread-safe) + + g_Conf->ProgLogBox.Visible = event.IsChecked(); + wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED, g_Conf->ProgLogBox.Visible ? wxID_OPEN : wxID_CLOSE ); + wxGetApp().ProgramLog_PostEvent( evt ); +} + +void MainEmuFrame::Menu_ShowAboutBox(wxCommandEvent &event) +{ + AboutBoxDialog( this, wxID_ANY ).ShowModal(); +} diff --git a/pcsx2/gui/Panels/DirPickerPanel.cpp b/pcsx2/gui/Panels/DirPickerPanel.cpp index dbaebdede8..c21d6bcc28 100644 --- a/pcsx2/gui/Panels/DirPickerPanel.cpp +++ b/pcsx2/gui/Panels/DirPickerPanel.cpp @@ -116,6 +116,9 @@ Panels::DirPickerPanel::DirPickerPanel( wxWindow* parent, FoldersEnum_t folderid Connect( m_checkCtrl->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DirPickerPanel::UseDefaultPath_Click ) ); + // wx warns when paths don't exist, but this is typically normal when the wizard + // creates its child controls. So let's ignore them. + wxDoNotLogInThisScope please; Reset(); // forces default settings based on g_Conf } diff --git a/pcsx2/gui/Panels/MiscPanelStuff.cpp b/pcsx2/gui/Panels/MiscPanelStuff.cpp index 1668c3686b..076aec8022 100644 --- a/pcsx2/gui/Panels/MiscPanelStuff.cpp +++ b/pcsx2/gui/Panels/MiscPanelStuff.cpp @@ -1,197 +1,197 @@ -/* Pcsx2 - Pc Ps2 Emulator - * Copyright (C) 2002-2009 Pcsx2 Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "PrecompiledHeader.h" -#include "ConfigurationPanels.h" - -#include "App.h" - -#include "ps2/BiosTools.h" -#include - -using namespace wxHelpers; - -Panels::StaticApplyState Panels::g_ApplyState; - -// ----------------------------------------------------------------------- -// This method should be called by the parent dalog box of a configuration -// on dialog destruction. It asserts if the ApplyList hasn't been cleaned up -// and then cleans it up forcefully. -// -void Panels::StaticApplyState::DoCleanup() -{ - wxASSERT_MSG( PanelList.size() != 0, L"PanelList list hasn't been cleaned up." ); - PanelList.clear(); - ParentBook = NULL; -} - -void Panels::StaticApplyState::StartBook( wxBookCtrlBase* book ) -{ - DevAssert( ParentBook == NULL, "An ApplicableConfig session is already in progress." ); - ParentBook = book; -} - -void Panels::StaticApplyState::StartWizard() -{ - DevAssert( ParentBook == NULL, "An ApplicableConfig session is already in progress." ); -} - -// ----------------------------------------------------------------------- -// -// Parameters: -// pageid - identifier of the page to apply settings for. All other pages will be -// skipped. If pageid is negative (-1) then all pages are applied. -// -// Returns false if one of the panels fails input validation (in which case dialogs -// should not be closed, etc). -// -bool Panels::StaticApplyState::ApplyPage( int pageid, bool saveOnSuccess ) -{ - bool retval = true; - try - { - AppConfig confcopy( *g_Conf ); - - g_ApplyState.UseAdminMode = UseAdminMode; - - PanelApplyList_t::iterator yay = PanelList.begin(); - while( yay != PanelList.end() ) - { - //DbgCon::Status( L"Writing settings for: " + (*yay)->GetLabel() ); - if( (pageid < 0) || (*yay)->IsOnPage( pageid ) ) - (*yay)->Apply( confcopy ); - yay++; - } - - // If an exception is thrown above, this code below won't get run. - // (conveniently skipping any option application! :D) - - *g_Conf = confcopy; - UseAdminMode = g_ApplyState.UseAdminMode; - wxGetApp().ApplySettings(); - if( saveOnSuccess ) - wxGetApp().SaveSettings(); - } - catch( Exception::CannotApplySettings& ex ) - { - wxMessageBox( ex.FormatDisplayMessage(), _("Cannot apply settings...") ); - - if( ex.GetPanel() != NULL ) - ex.GetPanel()->SetFocusToMe(); - - retval = false; - } - - return retval; -} - -// Returns false if one of the panels fails input validation (in which case dialogs -// should not be closed, etc). -bool Panels::StaticApplyState::ApplyAll( bool saveOnSuccess ) -{ - return ApplyPage( -1, saveOnSuccess ); -} - -// ----------------------------------------------------------------------- -Panels::UsermodeSelectionPanel::UsermodeSelectionPanel( wxWindow& parent, int idealWidth, bool isFirstTime ) : - BaseApplicableConfigPanel( &parent, idealWidth ) -, m_radio_user( NULL ) -, m_radio_cwd( NULL ) -{ - const wxString usermodeExplained( pxE( ".Panels:Usermode:Explained", - L"Please select your preferred default location for PCSX2 user-level documents below " - L"(includes memory cards, screenshots, settings, and savestates). " - L"These folder locations can be overridden at any time using the Core Settings panel." - ) ); - - const wxString usermodeWarning( pxE( ".Panels:Usermode:Warning", - L"You can change the preferred default location for PCSX2 user-level documents here " - L"(includes memory cards, screenshots, settings, and savestates). " - L"This option only affects Standard Paths which are set to use the installation default value." - ) ); - - wxStaticBoxSizer& s_boxer = *new wxStaticBoxSizer( wxVERTICAL, this, _( "Usermode Selection" ) ); - AddStaticText( s_boxer, isFirstTime ? usermodeExplained : usermodeWarning ); - - m_radio_user = &AddRadioButton( s_boxer, _("User Documents (recommended)"), _("Location: ") + wxStandardPaths::Get().GetDocumentsDir() ); - s_boxer.AddSpacer( 4 ); - m_radio_cwd = &AddRadioButton( s_boxer, _("Current working folder (intended for developer use only)"), _("Location: ") + wxGetCwd(), - _("This setting requires administration privileges from your operating system.") ); - - s_boxer.AddSpacer( 4 ); - SetSizer( &s_boxer ); -} - -void Panels::UsermodeSelectionPanel::Apply( AppConfig& conf ) -{ - if( !m_radio_cwd->GetValue() && !m_radio_user->GetValue() ) - throw Exception::CannotApplySettings( this, wxLt( "You must select one of the available user modes before proceeding." ) ); - - g_ApplyState.UseAdminMode = m_radio_cwd->GetValue(); -} - -// ----------------------------------------------------------------------- -Panels::LanguageSelectionPanel::LanguageSelectionPanel( wxWindow& parent, int idealWidth ) : - BaseApplicableConfigPanel( &parent, idealWidth ) -, m_langs() -, m_picker( NULL ) -{ - i18n_EnumeratePackages( m_langs ); - - int size = m_langs.size(); - int cursel = 0; - wxString* compiled = new wxString[size]; - wxString configLangName( wxLocale::GetLanguageName( wxLANGUAGE_DEFAULT ) ); - - for( int i=0; iSetSelection( cursel ); - - wxBoxSizer& s_lang = *new wxBoxSizer( wxHORIZONTAL ); - AddStaticText( s_lang, _("Select a language: "), wxALIGN_CENTRE_VERTICAL ); - s_lang.AddSpacer( 5 ); - s_lang.Add( m_picker, SizerFlags::StdSpace() ); - - SetSizer( &s_lang ); -} - -void Panels::LanguageSelectionPanel::Apply( AppConfig& conf ) -{ - // The combo box's order is sorted and may not match our m_langs order, so - // we have to do a string comparison to find a match: - - wxString sel( m_picker->GetString( m_picker->GetSelection() ) ); - - conf.LanguageId = wxLANGUAGE_DEFAULT; // use this if no matches found - int size = m_langs.size(); - for( int i=0; i + +using namespace wxHelpers; + +Panels::StaticApplyState Panels::g_ApplyState; + +// ----------------------------------------------------------------------- +// This method should be called by the parent dalog box of a configuration +// on dialog destruction. It asserts if the ApplyList hasn't been cleaned up +// and then cleans it up forcefully. +// +void Panels::StaticApplyState::DoCleanup() +{ + wxASSERT_MSG( PanelList.size() != 0, L"PanelList list hasn't been cleaned up." ); + PanelList.clear(); + ParentBook = NULL; +} + +void Panels::StaticApplyState::StartBook( wxBookCtrlBase* book ) +{ + DevAssert( ParentBook == NULL, "An ApplicableConfig session is already in progress." ); + ParentBook = book; +} + +void Panels::StaticApplyState::StartWizard() +{ + DevAssert( ParentBook == NULL, "An ApplicableConfig session is already in progress." ); +} + +// ----------------------------------------------------------------------- +// +// Parameters: +// pageid - identifier of the page to apply settings for. All other pages will be +// skipped. If pageid is negative (-1) then all pages are applied. +// +// Returns false if one of the panels fails input validation (in which case dialogs +// should not be closed, etc). +// +bool Panels::StaticApplyState::ApplyPage( int pageid, bool saveOnSuccess ) +{ + bool retval = true; + try + { + AppConfig confcopy( *g_Conf ); + + g_ApplyState.UseAdminMode = UseAdminMode; + + PanelApplyList_t::iterator yay = PanelList.begin(); + while( yay != PanelList.end() ) + { + //DbgCon::Status( L"Writing settings for: " + (*yay)->GetLabel() ); + if( (pageid < 0) || (*yay)->IsOnPage( pageid ) ) + (*yay)->Apply( confcopy ); + yay++; + } + + // If an exception is thrown above, this code below won't get run. + // (conveniently skipping any option application! :D) + + *g_Conf = confcopy; + UseAdminMode = g_ApplyState.UseAdminMode; + wxGetApp().ApplySettings(); + if( saveOnSuccess ) + wxGetApp().SaveSettings(); + } + catch( Exception::CannotApplySettings& ex ) + { + wxMessageBox( ex.FormatDisplayMessage(), _("Cannot apply settings...") ); + + if( ex.GetPanel() != NULL ) + ex.GetPanel()->SetFocusToMe(); + + retval = false; + } + + return retval; +} + +// Returns false if one of the panels fails input validation (in which case dialogs +// should not be closed, etc). +bool Panels::StaticApplyState::ApplyAll( bool saveOnSuccess ) +{ + return ApplyPage( -1, saveOnSuccess ); +} + +// ----------------------------------------------------------------------- +Panels::UsermodeSelectionPanel::UsermodeSelectionPanel( wxWindow& parent, int idealWidth, bool isFirstTime ) : + BaseApplicableConfigPanel( &parent, idealWidth ) +, m_radio_user( NULL ) +, m_radio_cwd( NULL ) +{ + const wxString usermodeExplained( pxE( ".Panels:Usermode:Explained", + L"Please select your preferred default location for PCSX2 user-level documents below " + L"(includes memory cards, screenshots, settings, and savestates). " + L"These folder locations can be overridden at any time using the Core Settings panel." + ) ); + + const wxString usermodeWarning( pxE( ".Panels:Usermode:Warning", + L"You can change the preferred default location for PCSX2 user-level documents here " + L"(includes memory cards, screenshots, settings, and savestates). " + L"This option only affects Standard Paths which are set to use the installation default value." + ) ); + + wxStaticBoxSizer& s_boxer = *new wxStaticBoxSizer( wxVERTICAL, this, _( "Usermode Selection" ) ); + AddStaticText( s_boxer, isFirstTime ? usermodeExplained : usermodeWarning ); + + m_radio_user = &AddRadioButton( s_boxer, _("User Documents (recommended)"), _("Location: ") + wxStandardPaths::Get().GetDocumentsDir() ); + s_boxer.AddSpacer( 4 ); + m_radio_cwd = &AddRadioButton( s_boxer, _("Current working folder (intended for developer use only)"), _("Location: ") + wxGetCwd(), + _("This setting requires administration privileges from your operating system.") ); + + s_boxer.AddSpacer( 4 ); + SetSizer( &s_boxer ); +} + +void Panels::UsermodeSelectionPanel::Apply( AppConfig& conf ) +{ + if( !m_radio_cwd->GetValue() && !m_radio_user->GetValue() ) + throw Exception::CannotApplySettings( this, wxLt( "You must select one of the available user modes before proceeding." ) ); + + g_ApplyState.UseAdminMode = m_radio_cwd->GetValue(); +} + +// ----------------------------------------------------------------------- +Panels::LanguageSelectionPanel::LanguageSelectionPanel( wxWindow& parent, int idealWidth ) : + BaseApplicableConfigPanel( &parent, idealWidth ) +, m_langs() +, m_picker( NULL ) +{ + i18n_EnumeratePackages( m_langs ); + + int size = m_langs.size(); + int cursel = 0; + wxString* compiled = new wxString[size]; + wxString configLangName( wxLocale::GetLanguageName( wxLANGUAGE_DEFAULT ) ); + + for( int i=0; iSetSelection( cursel ); + + wxBoxSizer& s_lang = *new wxBoxSizer( wxHORIZONTAL ); + AddStaticText( s_lang, _("Select a language: "), wxALIGN_CENTRE_VERTICAL ); + s_lang.AddSpacer( 5 ); + s_lang.Add( m_picker, SizerFlags::StdSpace() ); + + SetSizer( &s_lang ); +} + +void Panels::LanguageSelectionPanel::Apply( AppConfig& conf ) +{ + // The combo box's order is sorted and may not match our m_langs order, so + // we have to do a string comparison to find a match: + + wxString sel( m_picker->GetString( m_picker->GetSelection() ) ); + + conf.LanguageId = wxLANGUAGE_DEFAULT; // use this if no matches found + int size = m_langs.size(); + for( int i=0; ikey == 0) ) return; + + GetPluginManager().KeyEvent( *ev ); + + m_kevt.SetEventType( ( ev->evt == KEYPRESS ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ); + m_kevt.SetId( pxID_Window_GS ); + + const bool isDown = (ev->evt == KEYPRESS); + + #ifdef __WXMSW__ + const int vkey = wxCharCodeMSWToWX( ev->key ); + #elif defined( __WXGTK__ ) + const int vkey = TranslateGDKtoWXK( ev->key ); + #else + # error Unsupported Target Platform. + #endif + + switch (vkey) + { + case WXK_SHIFT: m_kevt.m_shiftDown = isDown; return; + case WXK_CONTROL: m_kevt.m_controlDown = isDown; return; + case WXK_MENU: m_kevt.m_altDown = isDown; return; + } + + // fixme: when the GS is wx-controlled, we should send the message to the GS window + // instead. + + if( isDown ) + { + m_kevt.m_keyCode = vkey; + wxGetApp().AddPendingEvent( m_kevt ); + } +} + sptr AppEmuThread::ExecuteTask() { try @@ -120,6 +173,7 @@ sptr AppEmuThread::ExecuteTask() // ---------------------------------------------------------------------------- // [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? @@ -144,7 +198,7 @@ void Pcsx2App::OpenWizardConsole() static bool m_ForceWizard = false; -// User mode settings can't be stores in the CWD for two reasons: +// User mode settings can't be stored in the CWD for two reasons: // (a) the user may not have permission to do so (most obvious) // (b) it would result in sloppy usermode.ini found all over a hard drive if people runs the // exe from many locations (ugh). @@ -159,7 +213,10 @@ void Pcsx2App::ReadUserModeSettings() wxDirName usrlocaldir( wxStandardPaths::Get().GetUserLocalDataDir() ); if( !usrlocaldir.Exists() ) + { + Console::Status( L"Creating UserLocalData folder: " + usrlocaldir.ToString() ); usrlocaldir.Mkdir(); + } wxFileName usermodefile( FilenameDefs::GetUsermodeConfig() ); usermodefile.SetPath( usrlocaldir.ToString() ); @@ -211,7 +268,7 @@ void Pcsx2App::ReadUserModeSettings() void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser ) { - parser.SetLogo( L" >> Pcsx2 -- A Playstation2 Emulator for the PC\n"); + parser.SetLogo( L" >> PCSX2 -- A Playstation2 Emulator for the PC\n"); parser.AddParam( L"CDVD/ELF", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL ); @@ -269,6 +326,8 @@ bool Pcsx2App::OnInit() Connect( pxEVT_CallStackBox, pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) ); Connect( pxEVT_SemaphorePing, wxCommandEventHandler( Pcsx2App::OnSemaphorePing ) ); + Connect( pxID_Window_GS, wxEVT_KEY_DOWN, wxKeyEventHandler( Pcsx2App::OnKeyDown ) ); + // User/Admin Mode Dual Setup: // Pcsx2 now supports two fundamental modes of operation. The default is Classic mode, // which uses the Current Working Directory (CWD) for all user data files, and requires @@ -282,8 +341,8 @@ bool Pcsx2App::OnInit() try { - ReadUserModeSettings(); delete wxLog::SetActiveTarget( new pxLogConsole() ); + ReadUserModeSettings(); AppConfig_ReloadGlobalSettings(); diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index d0c3502147..d19524e556 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -567,60 +567,28 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + @@ -2573,12 +2545,8 @@ - - @@ -2588,6 +2556,38 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +