diff --git a/3rdparty/w32pthreads/include/pthread.h b/3rdparty/w32pthreads/include/pthread.h
index 12b4a169b5..dfa5c44bda 100644
--- a/3rdparty/w32pthreads/include/pthread.h
+++ b/3rdparty/w32pthreads/include/pthread.h
@@ -570,19 +570,14 @@ typedef struct _ptw32_handle_t {
#ifdef __cplusplus
// Added support for various operators so that the struct is
// more pthreads-compliant in behavior. (air)
- const bool operator ==( const void* rightside )
+ const bool operator ==( const struct _ptw32_handle_t rightside ) const
{
- return p == rightside;
+ return p == rightside.p;
}
- const bool operator !=( const void* rightside )
+ const bool operator !=( const struct _ptw32_handle_t rightside ) const
{
- return p != rightside;
- }
-
- bool operator =( void* rightside )
- {
- p = rightside;
+ return p != rightside.p;
}
#endif
diff --git a/3rdparty/w32pthreads/pthreads_2008.vcproj b/3rdparty/w32pthreads/pthreads_2008.vcproj
index b18a1e9b32..2183445150 100644
--- a/3rdparty/w32pthreads/pthreads_2008.vcproj
+++ b/3rdparty/w32pthreads/pthreads_2008.vcproj
@@ -44,7 +44,6 @@
ExceptionHandling="2"
UsePrecompiledHeader="0"
WarningLevel="3"
- CompileAs="1"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
DaZ, FtZ, "chop"
+#define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop"
+
/////////////////////////////////////////////////////////////////////////////////////////
// Pcsx2Config
//
@@ -50,28 +58,56 @@ class Pcsx2Config
public:
struct ProfilerOptions
{
- bool
- Enabled:1, // universal toggle for the profiler.
- RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented]
- RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented]
- RecBlocks_VU0:1, // Enables per-block profiling for the VU0 recompiler [unimplemented]
- RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented]
+ union
+ {
+ struct
+ {
+ bool
+ Enabled:1, // universal toggle for the profiler.
+ RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented]
+ RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented]
+ RecBlocks_VU0:1, // Enables per-block profiling for the VU0 recompiler [unimplemented]
+ RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented]
+ };
+ u8 bits;
+ };
+
+ ProfilerOptions() : bits( 0 ) {}
void LoadSave( IniInterface& conf );
+
+ bool operator ==( const ProfilerOptions& right ) const
+ {
+ return OpEqu( bits );
+ }
+
+ bool operator !=( const ProfilerOptions& right ) const
+ {
+ return !this->operator ==( right );
+ }
};
// ------------------------------------------------------------------------
struct RecompilerOptions
{
- bool
- EnableEE:1,
- EnableIOP:1,
- EnableVU0:1,
- EnableVU1:1;
-
- bool
- UseMicroVU0:1,
- UseMicroVU1:1;
+ union
+ {
+ struct
+ {
+ bool
+ EnableEE:1,
+ EnableIOP:1,
+ EnableVU0:1,
+ EnableVU1:1;
+
+ bool
+ UseMicroVU0:1,
+ UseMicroVU1:1;
+ };
+ u8 bits;
+ };
+
+ RecompilerOptions() : bits( 0 ) { }
void Load( const wxString& srcfile );
void Load( const wxInputStream& srcstream );
@@ -80,29 +116,64 @@ public:
void LoadSave( IniInterface& conf );
+ bool operator ==( const RecompilerOptions& right ) const
+ {
+ return OpEqu( bits );
+ }
+
+ bool operator !=( const RecompilerOptions& right ) const
+ {
+ return !this->operator ==( right );
+ }
+
} Recompiler;
// ------------------------------------------------------------------------
struct CpuOptions
{
+ RecompilerOptions Recompiler;
+
u32 sseMXCSR;
u32 sseVUMXCSR;
- bool
- vuOverflow:1,
- vuExtraOverflow:1,
- vuSignOverflow:1,
- vuUnderflow:1;
-
- bool
- fpuOverflow:1,
- fpuExtraOverflow:1,
- fpuFullMode:1;
+ struct
+ {
+ union
+ {
+ bool
+ vuOverflow:1,
+ vuExtraOverflow:1,
+ vuSignOverflow:1,
+ vuUnderflow:1;
+
+ bool
+ fpuOverflow:1,
+ fpuExtraOverflow:1,
+ fpuFullMode:1;
+ };
+ u8 bits;
+ };
- ProfilerOptions Profiler;
- RecompilerOptions Recompiler;
+ CpuOptions() :
+ sseMXCSR( DEFAULT_sseMXCSR )
+ , sseVUMXCSR( DEFAULT_sseVUMXCSR )
+ , bits( 0 )
+ {
+ }
void LoadSave( IniInterface& conf );
+
+ bool operator ==( const CpuOptions& right ) const
+ {
+ return
+ OpEqu( sseMXCSR ) && OpEqu( sseVUMXCSR ) &&
+ OpEqu( bits ) && OpEqu( Recompiler );
+ }
+
+ bool operator !=( const CpuOptions& right ) const
+ {
+ return !this->operator ==( right );
+ }
};
// ------------------------------------------------------------------------
@@ -128,36 +199,77 @@ public:
// ------------------------------------------------------------------------
struct GamefixOptions
{
- bool
- VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU ADDI opcode to be bit-accurate.
- VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
- FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
- FpuMulHack:1, // Fix for Tales of Destiny hangs.
- XgKickHack:1; // Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics, but breaks Tri-ace games and others.
+ union
+ {
+ struct
+ {
+ bool
+ VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU ADDI opcode to be bit-accurate.
+ VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
+ FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
+ FpuMulHack:1, // Fix for Tales of Destiny hangs.
+ XgKickHack:1; // Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics, but breaks Tri-ace games and others.
+ };
+ u8 bits;
+ };
+
+ GamefixOptions() : bits( 0 ) {}
void LoadSave( IniInterface& conf );
+
+ bool operator ==( const GamefixOptions& right ) const
+ {
+ return OpEqu( bits );
+ }
+
+ bool operator !=( const GamefixOptions& right ) const
+ {
+ return !this->operator ==( right );
+ }
};
// ------------------------------------------------------------------------
struct SpeedhackOptions
{
- int
- EECycleRate:2, // EE cyclerate selector (1.0, 1.5, 2.0)
- VUCycleSteal:3, // VU Cycle Stealer factor (0, 1, 2, or 3)
- IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate
- IntcStat:1, // tells Pcsx2 to fast-forward through intc_stat waits.
- BIFC0:1, // enables BIFC0 detection and fast-forwarding
-
- vuMinMax:1, // microVU specific MinMax hack; Can cause SPS, Black Screens, etc...
- vuFlagHack:1; // MicroVU specific flag hack; Can cause Infinite loops, SPS, etc...
+ union
+ {
+ struct
+ {
+ int
+ EECycleRate:2, // EE cyclerate selector (1.0, 1.5, 2.0)
+ VUCycleSteal:3, // VU Cycle Stealer factor (0, 1, 2, or 3)
+ IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate
+ IntcStat:1, // tells Pcsx2 to fast-forward through intc_stat waits.
+ BIFC0:1, // enables BIFC0 detection and fast-forwarding
+
+ vuMinMax:1, // microVU specific MinMax hack; Can cause SPS, Black Screens, etc...
+ vuFlagHack:1; // MicroVU specific flag hack; Can cause Infinite loops, SPS, etc...
+ };
+ u16 bits;
+ };
+
+ SpeedhackOptions() : bits( 0 ) {}
void LoadSave( IniInterface& conf );
+
+ bool operator ==( const SpeedhackOptions& right ) const
+ {
+ return OpEqu( bits );
+ }
+
+ bool operator !=( const SpeedhackOptions& right ) const
+ {
+ return !this->operator ==( right );
+ }
};
public:
bool CdvdVerboseReads:1; // enables cdvd read activity verbosely dumped to the console
- bool CdvdDumpBlocks:1;
- bool EnablePatches:1;
+ bool CdvdDumpBlocks:1; // enables cdvd block dumping
+ bool EnablePatches:1; // enables patch detection and application
+
+ // when enabled performs bios stub execution, skipping full sony bios + splash screens
+ bool SkipBiosSplash:1;
// Closes the GS/Video port on escape (good for fullscreen activity)
bool closeGSonEsc:1;
@@ -169,6 +281,7 @@ public:
VideoOptions Video;
SpeedhackOptions Speedhacks;
GamefixOptions Gamefixes;
+ ProfilerOptions Profiler;
void Load( const wxString& srcfile );
void Load( const wxInputStream& srcstream );
@@ -178,21 +291,6 @@ public:
void LoadSave( IniInterface& ini );
};
-// Pauses the emulation state at the next PS2 vsync, and returns control to the calling
-// thread; or does nothing if the core is already suspended. Calling this thread from the
-// Core thread will result in deadlock.
-extern void Core_Suspend();
-
-// Applies a full suite of new settings, which will automatically facilitate the necessary
-// resets of the core and components (including plugins, if needed). The scope of resetting
-// is determined by comparing the current settings against the new settings.
-extern void Core_ApplySettings( const Pcsx2Config& src );
-
-// Resumes the core execution state, or does nothing is the core is already running. If
-// settings were changed, resets will be performed as needed and emulation state resumed from
-// memory savestates.
-extern void Core_Resume();
-
//////////////////////////////////////////////////////////////////////////
// Session Configuration Override Flags
//
@@ -244,10 +342,6 @@ extern SessionOverrideFlags g_Session;
#define CHECK_FPU_EXTRA_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions
#define CHECK_FPU_FULL (EmuConfig.Cpu.fpuFullMode)
-//------------ DEFAULT sseMXCSR VALUES!!! ---------------
-#define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop"
-#define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop"
-
//------------ EE Recompiler defines - Comment to disable a recompiler ---------------
#define SHIFT_RECOMPILE // Speed majorly reduced if disabled
diff --git a/pcsx2/Elfheader.cpp b/pcsx2/Elfheader.cpp
index 6da1d2d825..be490eb953 100644
--- a/pcsx2/Elfheader.cpp
+++ b/pcsx2/Elfheader.cpp
@@ -505,28 +505,27 @@ u32 loadElfCRC( const char* filename )
return crcval;
}
-int loadElfFile(const wxString& filename)
+// Loads the elf binary data from the specified file into PS2 memory, and injects the ELF's
+// starting execution point into cpuRegs.pc. If the filename is a cdrom URI in the form
+// of "cdrom0:" or "cdrom1:" then the CDVD is used as the source; otherwise the ELF is loaded
+// from the host filesystem.
+//
+// If the specified filename is empty then no action is taken (PS2 will continue booting
+// normally as if it has no CD
+//
+// Throws exception on error:
+//
+void loadElfFile(const wxString& filename)
{
- // Reset all recompilers prior to initiating a BIOS or new ELF. The cleaner the
- // slate, the happier the recompiler!
-
- SysClearExecutionCache();
-
- if( filename.IsEmpty() )
- {
- Console::Notice( "Running the PS2 BIOS..." );
- return -1;
- }
-
- // We still need to run the BIOS stub, so that all the EE hardware gets initialized correctly.
- cpuExecuteBios();
-
+ if( filename.IsEmpty() ) return;
+
int elfsize;
Console::Status( wxsFormat( L"loadElfFile: %s", filename.c_str() ) );
const wxCharBuffer buffer( filename.ToAscii() );
const char* fnptr = buffer.data();
-
+ bool useCdvdSource=false;
+
if( !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) )
{
// Loading from a file (or non-cd image)
@@ -536,23 +535,25 @@ int loadElfFile(const wxString& filename)
else
{
// Loading from a CD rom or CD image.
+ useCdvdSource = true;
TocEntry toc;
IsoFS_init( );
if ( IsoFS_findFile( fnptr + strlen( "cdromN:" ), &toc ) == -1 )
- return -1;
+ throw Exception::FileNotFound( filename, wxLt("ELF file was not found on the CDVD source media.") );
elfsize = toc.fileSize;
}
Console::Status( wxsFormat(L"loadElfFile: %d", elfsize) );
- if( elfsize == 0 ) return -1;
+ if( elfsize == 0 )
+ throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") );
ElfObject elfobj( filename, elfsize );
if( elfobj.proghead == NULL )
{
- throw Exception::CpuStateShutdown(
- wxsFormat( L"Invalid ELF header encountered in file:\n\t%s", elfobj.filename.c_str() ),
- wxsFormat( L"Invalid ELF header, file: %s", elfobj.filename.c_str() )
+ throw Exception::BadStream( filename, useCdvdSource ?
+ wxLt("Invalid ELF file header. The CD-Rom may be damaged, or the ISO image corrupted.") :
+ wxLt("Invalid ELF file.")
);
}
@@ -583,6 +584,6 @@ int loadElfFile(const wxString& filename)
ElfApplyPatches();
- return 0;
+ return;
}
diff --git a/pcsx2/Elfheader.h b/pcsx2/Elfheader.h
index 6a7a3b94b0..8900a0d8ae 100644
--- a/pcsx2/Elfheader.h
+++ b/pcsx2/Elfheader.h
@@ -24,9 +24,9 @@ extern char args[256]; //to be filled by GUI
extern unsigned int args_ptr;
//-------------------
-int loadElfFile(const wxString& filename);
-u32 loadElfCRC(const char *filename);
-void ElfApplyPatches();
+extern void loadElfFile(const wxString& filename);
+extern u32 loadElfCRC(const char *filename);
+extern void ElfApplyPatches();
extern u32 ElfCRC;
diff --git a/pcsx2/GS.h b/pcsx2/GS.h
index 4914ce00ca..a02a9a7263 100644
--- a/pcsx2/GS.h
+++ b/pcsx2/GS.h
@@ -154,7 +154,7 @@ enum GS_RINGTYPE
, GS_RINGTYPE_QUIT
};
-class mtgsThreadObject : public Threading::Thread
+class mtgsThreadObject : public Threading::PersistentThread
{
friend class SaveState;
@@ -225,7 +225,7 @@ public:
virtual ~mtgsThreadObject();
void Start();
- void Close();
+ void Cancel();
void Reset();
void GIFSoftReset( int mask );
@@ -276,7 +276,7 @@ protected:
uint _PrepForSimplePacket();
void _FinishSimplePacket( uint future_writepos );
- int Callback();
+ sptr ExecuteTask();
};
extern mtgsThreadObject* mtgsThread;
diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp
index 56f6dc293f..5ed9716121 100644
--- a/pcsx2/MTGS.cpp
+++ b/pcsx2/MTGS.cpp
@@ -177,7 +177,7 @@ typedef void (*GIFRegHandler)(const u32* data);
static GIFRegHandler s_GSHandlers[3] = { RegHandlerSIGNAL, RegHandlerFINISH, RegHandlerLABEL };
mtgsThreadObject::mtgsThreadObject() :
- Thread()
+ PersistentThread()
, m_RingPos( 0 )
, m_WritePos( 0 )
@@ -204,7 +204,7 @@ mtgsThreadObject::mtgsThreadObject() :
void mtgsThreadObject::Start()
{
- Thread::Start();
+ PersistentThread::Start();
// Wait for the thread to finish initialization (it runs GSopen, which can take
// some time since it's creating a new window and all), and then check for errors.
@@ -217,10 +217,10 @@ void mtgsThreadObject::Start()
mtgsThreadObject::~mtgsThreadObject()
{
- Close();
+ Cancel();
}
-void mtgsThreadObject::Close()
+void mtgsThreadObject::Cancel()
{
Console::WriteLn( "MTGS > Closing GS thread..." );
SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 );
@@ -499,7 +499,7 @@ struct PacketTagType
#ifndef __LINUX__
extern bool renderswitch;
#endif
-int mtgsThreadObject::Callback()
+sptr mtgsThreadObject::ExecuteTask()
{
Console::WriteLn("MTGS > Thread Started, Opening GS Plugin...");
diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp
index 99d7bc76d5..081c93261f 100644
--- a/pcsx2/Memory.cpp
+++ b/pcsx2/Memory.cpp
@@ -805,7 +805,7 @@ void memReset()
wxString Bios( g_Conf->FullpathToBios() );
long filesize = Path::GetFileSize( Bios );
- if( filesize <= 0 )
+ if( filesize > 0 )
{
wxFile fp( Bios.c_str() );
fp.Read( PS2MEM_ROM, min( (long)Ps2MemSize::Rom, filesize ) );
@@ -813,7 +813,14 @@ void memReset()
else
{
// Translated: Bios file not found or not specified ... A bios is required for Pcsx2 to run!
- throw Exception::FileNotFound( Bios, wxLt("Bios not found") );
+ throw Exception::FileNotFound( Bios,
+ L"Configured Bios file does not exist",
+ pxE( ".Error:BiosNotFound",
+ L"The configured BIOS file does not exist, or no BIOS has been configured.\n\n"
+ L"PCSX2 requires a PS2 BIOS to run; and the BIOS *must* be obtained from an actual PS2 unit\n"
+ L"that you own (borrowing doesn't count). Please consult the FAQs and Guides for further instructions."
+ )
+ );
}
BiosVersion = GetBiosVersion();
diff --git a/pcsx2/Misc.cpp b/pcsx2/Misc.cpp
index 8e33b5d5f2..c6c0dc1e20 100644
--- a/pcsx2/Misc.cpp
+++ b/pcsx2/Misc.cpp
@@ -237,6 +237,10 @@ bool IsBIOS(const wxString& filename, wxString& description)
return false; //fail quietly
}
+// return value:
+// 0 - Invalid or unknown disc.
+// 1 - PS1 CD
+// 2 - PS2 CD
int GetPS2ElfName( wxString& name )
{
int f;
@@ -262,7 +266,7 @@ int GetPS2ElfName( wxString& name )
if (pos==NULL){
pos=strstr(buffer, "BOOT");
if (pos==NULL) {
- Console::Error("Boot Error > This is not a PS2 game!");
+ Console::Error("Boot failed: This is not a Playstation or PS2 game!");
return 0;
}
return 1;
@@ -453,7 +457,7 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
wxsFormat( L"Error! Could not load from saveslot %d\n", StatesC ) + ex.LogMessage(),
// translated message:
- wxsFormat( L"Error loading saveslot %d. Emulator reset.", StatesC )
+ wxsFormat( _("Error loading saveslot %d. Emulator reset."), StatesC )
);
}
break;
diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp
index e0ad336429..d0768a0345 100644
--- a/pcsx2/Pcsx2Config.cpp
+++ b/pcsx2/Pcsx2Config.cpp
@@ -76,7 +76,6 @@ void Pcsx2Config::CpuOptions::LoadSave( IniInterface& ini )
IniBitBool( fpuFullMode, false );
Recompiler.LoadSave( ini );
- Profiler.LoadSave( ini );
ini.SetPath( L".." );
}
@@ -112,6 +111,7 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
Cpu.LoadSave( ini );
Video.LoadSave( ini );
Gamefixes.LoadSave( ini );
+ Profiler.LoadSave( ini );
ini.SetPath( L".." );
ini.Flush();
diff --git a/pcsx2/Plugins.cpp b/pcsx2/Plugins.cpp
index 2fd07ec9a8..be81deb3ce 100644
--- a/pcsx2/Plugins.cpp
+++ b/pcsx2/Plugins.cpp
@@ -720,14 +720,7 @@ void InitPlugins()
return 0;*/
}
-// ----------------------------------------------------------------------------
-// Opens all plugins and initializes the CDVD plugin to use the given filename. If the filename is null
-// then the cdvd plugin uses whatever file it has been configured to use. If plugin have not been
-// initialized by an explicit call to InitializePlugins, this method will do so for you.
-//
-// fixme: the cdvd filename really should be passed to the cdvd plugin as a separate API call. >_<
-//
-void OpenPlugins(const char* cdvdFilename)
+void OpenPlugins()
{
/*if (!plugins_initialized)
{
diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h
index 54efe73b1d..54924566b7 100644
--- a/pcsx2/Plugins.h
+++ b/pcsx2/Plugins.h
@@ -113,7 +113,7 @@ extern PluginManager* g_plugins;
void LoadPlugins();
void ReleasePlugins();
-void OpenPlugins(const char* pTitleFilename);
+void OpenPlugins();
void ClosePlugins( bool closegs );
void CloseGS();
diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp
index 0a3183aab2..d1cb5f5093 100644
--- a/pcsx2/R5900.cpp
+++ b/pcsx2/R5900.cpp
@@ -47,7 +47,7 @@ PCSX2_ALIGNED16(fpuRegisters fpuRegs);
PCSX2_ALIGNED16(tlbs tlb[48]);
R5900cpu *Cpu = NULL;
-u32 bExecBIOS = 0; // set if the BIOS has already been executed
+bool g_ExecBiosHack = false; // set if the BIOS has already been executed
static bool cpuIsInitialized = false;
static const uint eeWaitCycles = 3072;
@@ -556,21 +556,27 @@ __forceinline void cpuTestHwInts() {
// memory and hardware. It forcefully breaks execution when the stub is finished, prior
// to the PS2 logos being displayed. This allows us to "shortcut" right into a game
// without having to wait through the logos or endure game/bios localization checks.
+//
+// Use of this function must be followed by the proper injection of the elf header's code
+// execution entry point into cpuRegs.pc. Failure to modify cpuRegs.pc will result in the
+// bios continuing its normal unimpeeded splashscreen execution.
+//
void cpuExecuteBios()
{
// Set the video mode to user's default request:
gsSetRegionMode( (GS_RegionMode)EmuConfig.Video.DefaultRegionMode );
- Console::Notice( "* PCSX2 *: ExecuteBios" );
+ Console::Status( "Executing Bios Stub..." );
- bExecBIOS = TRUE;
- while (cpuRegs.pc != 0x00200008 &&
- cpuRegs.pc != 0x00100008) {
+ g_ExecBiosHack = true;
+ while( cpuRegs.pc != 0x00200008 &&
+ cpuRegs.pc != 0x00100008 )
+ {
g_nextBranchCycle = cpuRegs.cycle;
Cpu->ExecuteBlock();
}
+ g_ExecBiosHack = false;
- bExecBIOS = FALSE;
// {
// FILE* f = fopen("eebios.bin", "wb");
// fwrite(PSM(0x80000000), 0x100000, 1, f);
@@ -586,12 +592,12 @@ void cpuExecuteBios()
// REC_CLEARM(0x00100008);
// REC_CLEARM(cpuRegs.pc);
- // Reset the EErecs here, because the bios generates "slow" blocks that have hacky
- // bBiosEnd checks in them and stuff. This deletes them so that the recs replace them
+ // Reset the EErecs here, because the bios generates "slow" blocks that have
+ // g_ExecBiosHack checks in them. This deletes them so that the recs replace them
// with new faster versions:
Cpu->Reset();
- Console::Notice("* PCSX2 *: ExecuteBios Complete");
+ Console::Notice("Execute Bios Stub Complete");
//GSprintf(5, "PCSX2 " PCSX2_VERSION "\nExecuteBios Complete\n");
}
diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h
index 7dedb6c329..a6f06bbd96 100644
--- a/pcsx2/R5900.h
+++ b/pcsx2/R5900.h
@@ -28,7 +28,7 @@ extern const char* const bios[256];
extern s32 EEsCycle;
extern u32 EEoCycle;
-extern u32 bExecBIOS;
+extern bool g_ExecBiosHack;
union GPR_reg { // Declare union type GPR register
u64 UD[2]; //128 bits
diff --git a/pcsx2/RecoverySystem.cpp b/pcsx2/RecoverySystem.cpp
index 0a87479df4..0c8664e575 100644
--- a/pcsx2/RecoverySystem.cpp
+++ b/pcsx2/RecoverySystem.cpp
@@ -80,7 +80,7 @@ namespace StateRecovery {
void Recover()
{
// Just in case they weren't initialized earlier (no harm in calling this multiple times)
- OpenPlugins(NULL);
+ OpenPlugins();
if( g_RecoveryState != NULL )
{
diff --git a/pcsx2/Saveslots.cpp b/pcsx2/Saveslots.cpp
index 83bef20545..9284352209 100644
--- a/pcsx2/Saveslots.cpp
+++ b/pcsx2/Saveslots.cpp
@@ -48,7 +48,7 @@ static void _loadStateOrExcept( const wxString& file )
// Make sure the cpu and plugins are ready to be state-ified!
cpuReset();
- OpenPlugins( NULL );
+ OpenPlugins();
joe.FreezeAll();
diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp
index 9db1d9862c..202296a223 100644
--- a/pcsx2/System.cpp
+++ b/pcsx2/System.cpp
@@ -33,7 +33,7 @@
using namespace std;
-Pcsx2Config EmuConfig = {0};
+Pcsx2Config EmuConfig;
// disable all session overrides by default...
SessionOverrideFlags g_Session = {false};
@@ -334,54 +334,6 @@ void SysEndExecution()
g_ReturnToGui = true;
}
-// Runs an ELF image directly (ISO or ELF program or BIN)
-// Used by Run::FromCD, and Run->Execute when no active emulation state is present.
-// elf_file - if NULL, the CDVD plugin is queried for the ELF file.
-// use_bios - forces the game to boot through the PS2 bios, instead of bypassing it.
-void SysPrepareExecution( const wxString& elf_file, bool use_bios )
-{
- if( !g_EmulationInProgress )
- {
- try
- {
- cpuReset();
- }
- catch( Exception::BaseException& ex )
- {
- Msgbox::Alert( ex.DisplayMessage() );
- return;
- }
-
- //g_Startup.BootMode = (elf_file) ? BootMode_Elf : BootMode_Normal;
-
- OpenPlugins(NULL);
-
- if( elf_file.IsEmpty() )
- {
- if( !StateRecovery::HasState() )
- {
- // Not recovering a state, so need to execute the bios and load the ELF information.
- // (note: gsRecoveries are done from ExecuteCpu)
-
- wxString ename;
- if( !use_bios )
- GetPS2ElfName( ename );
-
- loadElfFile( ename );
- }
- }
- else
- {
- // Custom ELF specified (not using CDVD).
- // Run the BIOS and load the ELF.
- loadElfFile( elf_file );
- }
- }
-
- StateRecovery::Recover();
- HostGui::BeginExecution();
-}
-
void SysRestorableReset()
{
if( !g_EmulationInProgress ) return;
diff --git a/pcsx2/System.h b/pcsx2/System.h
index e52e7aa5f0..6bff8ca2d2 100644
--- a/pcsx2/System.h
+++ b/pcsx2/System.h
@@ -35,8 +35,7 @@ extern void SysShutdownMem();
extern void SysRestorableReset(); // Saves the current emulation state prior to spu reset.
extern void SysClearExecutionCache(); // clears recompiled execution caches!
-extern void SysEndExecution(); // terminates plugins, saves GS state (if enabled), and signals emulation loop to end.
-extern void SysPrepareExecution( const wxString& elf_file, bool use_bios=false );
+extern void SysEndExecution(); // terminates plugins, saves GS state (if enabled), and signals emulation loop to end.
// initiates high-speed execution of the emulation state. This function is currently
// designed to be run from an event loop, but will eventually be re-tooled with threading
@@ -82,6 +81,8 @@ extern void vSyncDebugStuff( uint frame );
//
namespace Msgbox
{
+ extern void OnEvent( wxCommandEvent& evt );
+
// Pops up an alert Dialog Box with a singular "OK" button.
// Always returns false. Replacement for SysMessage.
extern bool Alert( const wxString& text );
@@ -91,3 +92,4 @@ namespace Msgbox
extern bool OkCancel( const wxString& text );
}
+DECLARE_EVENT_TYPE( pxEVT_MSGBOX, -1 );
diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h
index f8c13d88eb..04ded9a56b 100644
--- a/pcsx2/gui/App.h
+++ b/pcsx2/gui/App.h
@@ -45,11 +45,11 @@ static const bool EnableThreadedLoggingTest = false; //true;
// ConsoleThreadTest -- useful class for unit testing the thread safety and general performance
// of the console logger.
//
-class ConsoleTestThread : public Thread
+class ConsoleTestThread : public PersistentThread
{
protected:
volatile bool m_done;
- int Callback();
+ sptr ExecuteTask();
public:
ConsoleTestThread() :
@@ -275,6 +275,7 @@ public:
protected:
void ReadUserModeSettings();
bool TryOpenConfigCwd();
+ void OnMessageBox( wxCommandEvent& evt );
};
DECLARE_APP(Pcsx2App)
diff --git a/pcsx2/gui/ConsoleLogger.cpp b/pcsx2/gui/ConsoleLogger.cpp
index be181c6a7b..530d22097a 100644
--- a/pcsx2/gui/ConsoleLogger.cpp
+++ b/pcsx2/gui/ConsoleLogger.cpp
@@ -45,7 +45,7 @@ DEFINE_EVENT_TYPE(wxEVT_SemaphoreWait);
using Console::Colors;
// ----------------------------------------------------------------------------
-int ConsoleTestThread::Callback()
+sptr ConsoleTestThread::ExecuteTask()
{
static int numtrack = 0;
@@ -602,17 +602,72 @@ namespace Console
}
}
+#define wxEVT_BOX_ALERT 78
+
+using namespace Threading;
+
+DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
+
namespace Msgbox
{
+ struct InstanceData
+ {
+ Semaphore WaitForMe;
+ int result;
+
+ InstanceData() :
+ WaitForMe(), result( 0 )
+ {
+ }
+ };
+
+ // parameters:
+ // flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
+ //
+ static int ThreadedMessageBox( int flags, const wxString& text )
+ {
+ // must pass the message to the main gui thread, and then stall this thread, to avoid
+ // threaded chaos where our thread keeps running while the popup is awaiting input.
+
+ InstanceData instdat;
+ wxCommandEvent tevt( pxEVT_MSGBOX );
+ tevt.SetString( text );
+ tevt.SetClientData( &instdat );
+ tevt.SetExtraLong( flags );
+ wxGetApp().AddPendingEvent( tevt );
+ instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
+ return instdat.result;
+ }
+
+ void OnEvent( wxCommandEvent& evt )
+ {
+ // Must be called from the GUI thread ONLY.
+ wxASSERT( wxThread::IsMain() );
+
+ int result = Alert( evt.GetString() );
+ InstanceData* instdat = (InstanceData*)evt.GetClientData();
+ instdat->result = result;
+ instdat->WaitForMe.Post();
+ }
+
bool Alert( const wxString& text )
{
- wxMessageBox( text, L"Pcsx2 Message", wxOK, wxGetApp().GetTopWindow() );
+ if( wxThread::IsMain() )
+ wxMessageBox( text, L"Pcsx2 Message", wxOK, wxGetApp().GetTopWindow() );
+ else
+ ThreadedMessageBox( wxOK, text );
return false;
}
bool OkCancel( const wxString& text )
{
- int result = wxMessageBox( text, L"Pcsx2 Message", wxOK | wxCANCEL, wxGetApp().GetTopWindow() );
- return result == wxOK;
+ if( wxThread::IsMain() )
+ {
+ return wxOK == wxMessageBox( text, L"Pcsx2 Message", wxOK | wxCANCEL, wxGetApp().GetTopWindow() );
+ }
+ else
+ {
+ return wxOK == ThreadedMessageBox( wxOK | wxCANCEL, text );
+ }
}
}
diff --git a/pcsx2/gui/HostGui.cpp b/pcsx2/gui/HostGui.cpp
index 112fd9d272..5aeb98a5af 100644
--- a/pcsx2/gui/HostGui.cpp
+++ b/pcsx2/gui/HostGui.cpp
@@ -17,7 +17,7 @@
*/
#include "PrecompiledHeader.h"
-#include "App.h"
+#include "Mainframe.h"
// This API is likely obsolete for the most part, so I've just included a few dummies
// to keep things compiling until I can get to the point of tying up loose ends.
@@ -44,6 +44,8 @@ namespace HostGui
void BeginExecution()
{
+ wxASSERT( g_EmuThread != NULL );
+ g_EmuThread->Resume();
}
void __fastcall KeyEvent( keyEvent* ev )
diff --git a/pcsx2/gui/MainFrame.cpp b/pcsx2/gui/MainFrame.cpp
index f0f9f438f3..44cf164c18 100644
--- a/pcsx2/gui/MainFrame.cpp
+++ b/pcsx2/gui/MainFrame.cpp
@@ -167,8 +167,7 @@ void MainEmuFrame::ConnectMenus()
ConnectMenu( Menu_RunELF, Menu_OpenELF_Click );
ConnectMenu( Menu_Run_Exit, Menu_Exit_Click );
- ConnectMenu( Menu_SuspendExec, Menu_Suspend_Click );
- ConnectMenu( Menu_ResumeExec, Menu_Resume_Click );
+ ConnectMenu( Menu_PauseExec, Menu_Pause_Click );
ConnectMenu( Menu_Reset, Menu_Reset_Click );
ConnectMenu( Menu_State_LoadOther, Menu_LoadStateOther_Click );
@@ -224,7 +223,9 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
m_LoadStatesSubmenu( *MakeStatesSubMenu( Menu_State_Load01 ) ),
m_SaveStatesSubmenu( *MakeStatesSubMenu( Menu_State_Save01 ) ),
- m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, Menu_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) )
+ m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, Menu_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) ),
+
+ m_IsPaused( false )
{
// ------------------------------------------------------------------------
// Initial menubar setup. This needs to be done first so that the menu bar's visible size
@@ -275,15 +276,14 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
m_menuRun.Append(Menu_RunIso, _("Run ISO"), MakeIsoMenu() );
m_menuRun.Append(Menu_BootCDVD, _("Run CDVD"), MakeCdvdMenu() );
- m_menuRun.Append(Menu_RunWithoutDisc,_("Run without Disc"), _("Use this to access the PS2 system configuration menu"));
- m_menuRun.Append(Menu_RunELF, _("Run ELF File..."), _("For running raw PS2 binaries."));
+ m_menuRun.Append(Menu_SkipBiosToggle,_("ELF Injection Hack"), _("Skips PS2 splash screens when booting from Iso or CDVD media"));
m_menuRun.AppendSeparator();
- m_menuRun.Append(Menu_SkipBiosToggle,_("Skip Bios on Boot"), _("Enable this to skip PS2 bootup screens (may hurt compat)"));
+ m_menuRun.Append(Menu_RunWithoutDisc,_("Boot without Disc"), _("Use this to access the PS2 system configuration menu"));
+ m_menuRun.Append(Menu_RunELF, _("Run ELF File..."), _("For running raw binaries"));
m_menuRun.AppendSeparator();
- m_menuRun.Append(Menu_SuspendExec, _("Suspend"), _("Stops emulation dead in its tracks"));
- m_menuRun.Append(Menu_ResumeExec, _("Resume"), _("Resumes suspended emulation"));
+ m_menuRun.Append(Menu_PauseExec, _("Pause"), _("Stops emulation dead in its tracks"));
m_menuRun.Append(Menu_States, _("States"), MakeStatesMenu(), wxEmptyString);
m_menuRun.Append(Menu_Reset, _("Reset"), _("Resets emulation state and reloads plugins"));
@@ -337,4 +337,3 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
Connect( wxEVT_MOVE, wxMoveEventHandler (MainEmuFrame::OnMoveAround) );
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler(MainEmuFrame::OnCloseWindow) );
}
-
diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h
index 4085c469ff..a9f5679b44 100644
--- a/pcsx2/gui/MainFrame.h
+++ b/pcsx2/gui/MainFrame.h
@@ -23,6 +23,9 @@
#include
#include "App.h"
+#include "PS2/CoreEmuThread.h"
+
+extern CoreEmuThread* g_EmuThread;
//////////////////////////////////////////////////////////////////////////////////////////
//
@@ -50,8 +53,7 @@ protected:
Menu_RunELF,
Menu_SkipBiosToggle, // enables the Bios Skip speedhack
Menu_EnableSkipBios, // check marked menu that toggles Skip Bios boot feature.
- Menu_SuspendExec, // suspends active emulation
- Menu_ResumeExec, // restores active emulation
+ Menu_PauseExec, // suspends/resumes active emulation
Menu_Reset, // Issues a complete reset.
Menu_States, // Opens states submenu
Menu_Run_Exit = wxID_EXIT,
@@ -134,6 +136,8 @@ protected:
wxMenuItem& m_MenuItem_Console;
+ bool m_IsPaused;
+
// ------------------------------------------------------------------------
// MainEmuFrame Constructors and Member Methods
// ------------------------------------------------------------------------
@@ -142,6 +146,8 @@ public:
MainEmuFrame(wxWindow* parent, const wxString& title);
void OnLogBoxHidden();
+ bool IsPaused() const { return m_IsPaused; }
+
protected:
void InitLogBoxPosition( AppConfig::ConsoleLogOptions& conf );
@@ -160,8 +166,7 @@ protected:
void Menu_SaveStateOther_Click(wxCommandEvent &event);
void Menu_Exit_Click(wxCommandEvent &event);
- void Menu_Suspend_Click(wxCommandEvent &event);
- void Menu_Resume_Click(wxCommandEvent &event);
+ void Menu_Pause_Click(wxCommandEvent &event);
void Menu_Reset_Click(wxCommandEvent &event);
void Menu_Debug_Open_Click(wxCommandEvent &event);
diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp
index 4a6a729c8b..8dd01d440d 100644
--- a/pcsx2/gui/MainMenuClicks.cpp
+++ b/pcsx2/gui/MainMenuClicks.cpp
@@ -17,6 +17,7 @@
*/
#include "PrecompiledHeader.h"
+#include "HostGui.h"
#include "CDVD/CDVD.h"
#include "MainFrame.h"
@@ -37,20 +38,63 @@ static const wxChar* isoFilterTypes =
void MainEmuFrame::Menu_RunIso_Click(wxCommandEvent &event)
{
+ g_EmuThread->Suspend();
+
Console::Status( L"Default Folder: " + g_Conf->Folders.RunIso.ToString() );
wxFileDialog ctrl( this, _("Run PS2 Iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString,
isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( ctrl.ShowModal() == wxID_CANCEL ) return;
g_Conf->Folders.RunIso = ctrl.GetPath();
-
+
//g_Conf->Save();
+
+ if( EmuConfig.SkipBiosSplash )
+ {
+ // Fetch the ELF filename and CD type from the CDVD provider.
+ wxString ename( ctrl.GetFilename() );
+ int result = GetPS2ElfName( ename );
+ g_EmuThread->SetElfFile( wxEmptyString );
+ 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!
+ g_EmuThread->SetElfFile( ename );
+ break;
+ }
+ }
}
void MainEmuFrame::Menu_RunWithoutDisc_Click(wxCommandEvent &event)
{
+ if( g_EmuThread->IsRunning() )
+ {
+ g_EmuThread->Suspend();
+
+ // [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 )
+ {
+ if( !IsPaused() )
+ g_EmuThread->Resume();
+ return;
+ }
+ }
+
+ g_EmuThread->Reset();
CDVDsys_ChangeSource( CDVDsrc_NoDisc );
- SysPrepareExecution( wxEmptyString, true );
+ g_EmuThread->Resume();
+
+ //HostGui::BeginExecution();
}
void MainEmuFrame::Menu_IsoRecent_Click(wxCommandEvent &event)
@@ -76,11 +120,7 @@ void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event)
Close();
}
-void MainEmuFrame::Menu_Suspend_Click(wxCommandEvent &event)
-{
-}
-
-void MainEmuFrame::Menu_Resume_Click(wxCommandEvent &event)
+void MainEmuFrame::Menu_Pause_Click(wxCommandEvent &event)
{
}
diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h
index 7f2bf8008a..debb6cdc9a 100644
--- a/pcsx2/gui/Panels/ConfigurationPanels.h
+++ b/pcsx2/gui/Panels/ConfigurationPanels.h
@@ -306,7 +306,7 @@ namespace Panels
}
};
- class EnumThread : public Threading::Thread
+ class EnumThread : public Threading::PersistentThread
{
public:
EnumeratedPluginInfo* Results; // array of plugin results.
@@ -317,10 +317,10 @@ namespace Panels
public:
virtual ~EnumThread();
EnumThread( PluginSelectorPanel& master );
- void Close();
+ void Cancel();
protected:
- int Callback();
+ sptr ExecuteTask();
};
// This panel contains all of the plugin combo boxes. We stick them
diff --git a/pcsx2/gui/Panels/PluginSelectorPanel.cpp b/pcsx2/gui/Panels/PluginSelectorPanel.cpp
index 7d5b1167ef..8580e45d3d 100644
--- a/pcsx2/gui/Panels/PluginSelectorPanel.cpp
+++ b/pcsx2/gui/Panels/PluginSelectorPanel.cpp
@@ -337,7 +337,7 @@ void Panels::PluginSelectorPanel::OnProgress( wxCommandEvent& evt )
// EnumThread Method Implementations
Panels::PluginSelectorPanel::EnumThread::EnumThread( PluginSelectorPanel& master ) :
- Thread()
+ PersistentThread()
, Results( new EnumeratedPluginInfo[master.FileCount()] )
, m_master( master )
, m_cancel( false )
@@ -347,17 +347,17 @@ Panels::PluginSelectorPanel::EnumThread::EnumThread( PluginSelectorPanel& master
Panels::PluginSelectorPanel::EnumThread::~EnumThread()
{
safe_delete_array( Results );
- Close();
+ Cancel();
}
-void Panels::PluginSelectorPanel::EnumThread::Close()
+void Panels::PluginSelectorPanel::EnumThread::Cancel()
{
m_cancel = true;
Threading::Sleep( 1 );
- Thread::Close();
+ PersistentThread::Cancel();
}
-int Panels::PluginSelectorPanel::EnumThread::Callback()
+sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask()
{
for( int curidx=0; curidx < m_master.FileCount() && !m_cancel; ++curidx )
{
diff --git a/pcsx2/gui/main.cpp b/pcsx2/gui/main.cpp
index b658c407fb..598cc27aad 100644
--- a/pcsx2/gui/main.cpp
+++ b/pcsx2/gui/main.cpp
@@ -30,11 +30,12 @@ IMPLEMENT_APP(Pcsx2App)
AppConfig* g_Conf = NULL;
wxFileHistory* g_RecentIsoList = NULL;
+CoreEmuThread* g_EmuThread = NULL;
namespace Exception
{
// --------------------------------------------------------------------------
- // Exception used to perfom an "errorless" termination of the app during OnInit
+ // Exception used to perform an "errorless" termination of the app during OnInit
// procedures. This happens when a user cancels out of startup prompts/wizards.
//
class StartupAborted : public BaseException
@@ -166,6 +167,7 @@ bool Pcsx2App::OnInit()
wxApp::OnInit();
g_Conf = new AppConfig();
+ g_EmuThread = new CoreEmuThread();
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
@@ -231,10 +233,17 @@ bool Pcsx2App::OnInit()
{
Dialogs::ConfigurationDialog( m_MainFrame ).ShowModal();
}*/
+
+ Connect( pxEVT_MSGBOX, wxCommandEventHandler( Pcsx2App::OnMessageBox ) );
return true;
}
+void Pcsx2App::OnMessageBox( wxCommandEvent& evt )
+{
+ Msgbox::OnEvent( evt );
+}
+
// Common exit handler which can be called from any event (though really it should
// be called only from CloseWindow handlers since that's the more appropriate way
// to handle window closures)
diff --git a/pcsx2/ps2/CoreEmuThread.cpp b/pcsx2/ps2/CoreEmuThread.cpp
new file mode 100644
index 0000000000..487783a2b0
--- /dev/null
+++ b/pcsx2/ps2/CoreEmuThread.cpp
@@ -0,0 +1,212 @@
+/* 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 "System.h"
+#include "SaveState.h"
+#include "ElfHeader.h"
+#include "Plugins.h"
+#include "CoreEmuThread.h"
+
+#include "R5900.h"
+#include "R3000A.h"
+#include "VUmicro.h"
+
+sptr CoreEmuThread::ExecuteTask()
+{
+ while( !m_Done && (m_ExecMode != ExecMode_Running) )
+ {
+ m_ResumeEvent.Wait();
+ }
+
+ try
+ {
+ cpuReset();
+ SysClearExecutionCache();
+ OpenPlugins();
+
+ if( StateRecovery::HasState() )
+ {
+ // no need to boot bios or detect CDs when loading savestates.
+ // [TODO] : It might be useful to detect game SLUS/CRC and compare it against
+ // the savestate info, and issue a warning to the user since, chances are, they
+ // don't really want to run a game with the wrong ISO loaded into the emu.
+ StateRecovery::Recover();
+ }
+ else
+ {
+ ScopedLock lock( m_lock_elf_file );
+ if( !m_elf_file.IsEmpty() )
+ {
+ // Skip Bios Hack -- Runs the PS2 BIOS stub, and then manually loads the ELF
+ // executable data, and injects the cpuRegs.pc with the address of the
+ // execution start point.
+ //
+ // This hack is necessary for non-CD ELF files, and is optional for game CDs
+ // (though not recommended for games because of rare ill side effects).
+
+ cpuExecuteBios();
+ loadElfFile( m_elf_file );
+ }
+ }
+ }
+ catch( Exception::BaseException& ex )
+ {
+ Msgbox::Alert( ex.DisplayMessage() );
+ }
+
+ StateCheck();
+
+ return 0;
+}
+
+void CoreEmuThread::StateCheck()
+{
+ {
+ ScopedLock locker( m_lock_ExecMode );
+
+ switch( m_ExecMode )
+ {
+ case ExecMode_Idle:
+ // threads should never have an idle execution state set while the
+ // thread is in any way active or alive.
+ DevAssert( false, "Invalid execution state detected." );
+ break;
+
+ // These are not the case statements you're looking for. Move along.
+ case ExecMode_Running: break;
+ case ExecMode_Suspended: break;
+
+ case ExecMode_Suspending:
+ m_ExecMode = ExecMode_Suspended;
+ m_SuspendEvent.Post();
+ break;
+ }
+ }
+
+ while( (m_ExecMode == ExecMode_Suspended) && !m_Done )
+ {
+ m_ResumeEvent.Wait();
+ }
+}
+
+void CoreEmuThread::Start()
+{
+ if( IsRunning() ) return;
+
+ m_running = false;
+ m_ExecMode = ExecMode_Idle;
+ m_Done = false;
+ m_resetProfilers = false;
+ m_resetRecompilers = false;
+ m_elf_file = wxEmptyString;
+
+ m_ResumeEvent.Reset();
+ m_SuspendEvent.Reset();
+ PersistentThread::Start();
+
+ pthread_detach( m_thread );
+}
+
+void CoreEmuThread::Reset()
+{
+ Cancel();
+ StateRecovery::Clear();
+}
+
+// Resumes the core execution state, or does nothing is the core is already running. If
+// settings were changed, resets will be performed as needed and emulation state resumed from
+// memory savestates.
+void CoreEmuThread::Resume()
+{
+ Start();
+
+ {
+ ScopedLock locker( m_lock_ExecMode );
+
+ if( m_ExecMode == ExecMode_Running )
+ return;
+
+ if( m_ExecMode == ExecMode_Suspending )
+ {
+ // if there are resets to be done, then we need to make sure and wait for the
+ // emuThread to enter a fully suspended state before continuing...
+
+ if( m_resetRecompilers || m_resetProfilers )
+ {
+ locker.Unlock(); // no deadlocks please, thanks. :)
+ m_SuspendEvent.Wait();
+ }
+ else
+ {
+ m_ExecMode = ExecMode_Running;
+ return;
+ }
+ }
+
+ DevAssert( (m_ExecMode == ExecMode_Suspended) || (m_ExecMode == ExecMode_Idle),
+ "EmuCoreThread is not in a suspended or idle state? wtf!" );
+ }
+
+ if( m_resetRecompilers || m_resetProfilers )
+ {
+ SysClearExecutionCache();
+ m_resetRecompilers = false;
+ m_resetProfilers = false;
+ }
+
+ m_ExecMode = ExecMode_Running;
+ m_ResumeEvent.Post();
+}
+
+// Pauses the emulation state at the next PS2 vsync, and returns control to the calling
+// thread; or does nothing if the core is already suspended. Calling this thread from the
+// Core thread will result in deadlock.
+//
+// Parameters:
+// isNonblocking - if set to true then the function will not block for emulation suspension.
+// Defaults to false if parameter is not specified. Performing non-blocking suspension
+// is mostly useful for starting certain non-Emu related gui activities (improves gui
+// responsiveness).
+//
+void CoreEmuThread::Suspend( bool isBlocking )
+{
+ {
+ ScopedLock locker( m_lock_ExecMode );
+
+ if( (m_ExecMode == ExecMode_Suspended) || (m_ExecMode == ExecMode_Idle) )
+ return;
+
+ if( m_ExecMode == ExecMode_Running )
+ m_ExecMode = ExecMode_Suspending;
+
+ DevAssert( m_ExecMode == ExecMode_Suspending, "ExecMode should be nothing other than Suspended..." );
+ }
+
+ m_SuspendEvent.Wait();
+}
+
+// Applies a full suite of new settings, which will automatically facilitate the necessary
+// resets of the core and components (including plugins, if needed). The scope of resetting
+// is determined by comparing the current settings against the new settings.
+void CoreEmuThread::ApplySettings( const Pcsx2Config& src )
+{
+ m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
+ m_resetProfilers = (src.Profiler != EmuConfig.Profiler );
+ EmuConfig = src;
+}
diff --git a/pcsx2/ps2/CoreEmuThread.h b/pcsx2/ps2/CoreEmuThread.h
new file mode 100644
index 0000000000..e1e931c40c
--- /dev/null
+++ b/pcsx2/ps2/CoreEmuThread.h
@@ -0,0 +1,86 @@
+/* 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 "Utilities/Threading.h"
+
+using namespace Threading;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CoreEmuThread
+//
+class CoreEmuThread : public PersistentThread
+{
+public:
+ enum ExecutionMode
+ {
+ ExecMode_Idle,
+ ExecMode_Running,
+ ExecMode_Suspending,
+ ExecMode_Suspended
+ };
+
+protected:
+ volatile ExecutionMode m_ExecMode;
+ volatile bool m_Done;
+
+ Semaphore m_ResumeEvent;
+ Semaphore m_SuspendEvent;
+
+ bool m_resetRecompilers;
+ bool m_resetProfilers;
+
+ wxString m_elf_file;
+
+ MutexLock m_lock_elf_file;
+ MutexLock m_lock_ExecMode;
+
+public:
+ CoreEmuThread() :
+ m_ExecMode( ExecMode_Idle )
+ , m_Done( false )
+ , m_ResumeEvent()
+ , m_SuspendEvent()
+ , m_resetRecompilers( false )
+ , m_resetProfilers( false )
+
+ , m_elf_file()
+ , m_lock_elf_file()
+ , m_lock_ExecMode()
+ {
+ }
+
+ void SetElfFile( const wxString& text )
+ {
+ ScopedLock lock( m_lock_elf_file );
+ m_elf_file = text;
+ }
+
+ void Start();
+ void Reset();
+
+ bool IsSuspended() const { return (m_ExecMode == ExecMode_Suspended); }
+ void Suspend( bool isBlocking = true );
+ void Resume();
+ void ApplySettings( const Pcsx2Config& src );
+
+protected:
+ sptr ExecuteTask();
+ void StateCheck();
+};
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index ae9c6e60f4..9c9a033cd8 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -262,62 +262,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1098,6 +1042,14 @@
RelativePath="..\..\x86\BaseblockEx.h"
>
+
+
+
+
@@ -1974,10 +1926,6 @@
RelativePath="..\..\gui\i18n.cpp"
>
-
-
diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp
index 58dbc2e729..d67392ef38 100644
--- a/pcsx2/x86/ix86-32/iR5900-32.cpp
+++ b/pcsx2/x86/ix86-32/iR5900-32.cpp
@@ -1043,7 +1043,7 @@ static u32 eeScaleBlockCycles()
// setting "branch = 2";
static void iBranchTest(u32 newpc, bool noDispatch)
{
- if( bExecBIOS ) CheckForBIOSEnd();
+ if( g_ExecBiosHack ) CheckForBIOSEnd();
// Check the Event scheduler if our "cycle target" has been reached.
// Equiv code to: