Emulation options (speedhacks, CPU, etc) should work now, and fixed a few memleaks on exit, and crash-on-close bugs caused by more mis-used pthreads timedwait parameters.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1800 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-09-09 14:08:15 +00:00
parent f02c04cb3b
commit 8eb8f1bcea
10 changed files with 116 additions and 63 deletions

View File

@ -29,7 +29,7 @@ using namespace Threading;
namespace Threading namespace Threading
{ {
static const timespec ts_msec_200 = { 0, 200 * 1000000 }; static const wxTimeSpan ts_msec_250( 0, 0, 0, 250 );
static void _pt_callback_cleanup( void* handle ) static void _pt_callback_cleanup( void* handle )
{ {
@ -275,11 +275,11 @@ namespace Threading
else else
{ {
// In order to avoid deadlock we need to make sure we cut some time // In order to avoid deadlock we need to make sure we cut some time
// to handle messages. I choose 200ms: // to handle messages.
do { do {
wxTheApp->ProcessPendingEvents(); wxTheApp->ProcessPendingEvents();
} while( (sem_timedwait( &sema, &ts_msec_200 ) == -1) && (errno == ETIMEDOUT) ); } while( !Wait( ts_msec_250 ) );
} }
} }
@ -294,14 +294,12 @@ namespace Threading
wxTimeSpan countdown( (timeout) ); wxTimeSpan countdown( (timeout) );
// In order to avoid deadlock we need to make sure we cut some time // In order to avoid deadlock we need to make sure we cut some time
// to handle messages. I choose 200ms: // to handle messages.
static const wxTimeSpan pass( 0, 0, 0, 200 );
do { do {
wxTheApp->ProcessPendingEvents(); wxTheApp->ProcessPendingEvents();
if( (sem_timedwait( &sema, &ts_msec_200 ) == -1) && (errno == ETIMEDOUT) ) if( Wait( ts_msec_250 ) ) break;
break; countdown -= ts_msec_250;
countdown -= pass;
} while( countdown.GetMilliseconds() > 0 ); } while( countdown.GetMilliseconds() > 0 );
return countdown.GetMilliseconds() > 0; return countdown.GetMilliseconds() > 0;
@ -316,7 +314,8 @@ namespace Threading
bool Semaphore::Wait( const wxTimeSpan& timeout ) bool Semaphore::Wait( const wxTimeSpan& timeout )
{ {
const timespec fail = { timeout.GetSeconds().GetLo(), 0 }; wxDateTime megafail( wxDateTime::UNow() + timeout );
const timespec fail = { megafail.GetTicks(), megafail.GetMillisecond() * 1000000 };
return sem_timedwait( &sema, &fail ) != -1; return sem_timedwait( &sema, &fail ) != -1;
} }

View File

@ -70,31 +70,22 @@ static int mg_BIToffset(u8 *buffer)
return ofs + 0x20; return ofs + 0x20;
} }
FILE *_cdvdOpenMechaVer() { FILE *_cdvdOpenMechaVer()
char *ptr; {
int i;
char file[g_MaxPath];
FILE* fd; FILE* fd;
// get the name of the bios file // get the name of the bios file
// use the bios filename to get the name of the mecha ver file wxFileName mecfile(EmuConfig.BiosFilename);
// [TODO] : Upgrade this to use wxstring! mecfile.SetExt( L"mec" );
wxCharBuffer file( mecfile.GetFullPath().ToUTF8() );
strcpy(file, g_Conf->FullpathToBios().ToAscii().data() );
ptr = file;
i = (int)strlen(file);
while (i > 0) { if (ptr[i] == '.') break; i--; }
ptr[i+1] = '\0';
strcat(file, "MEC");
// if file doesnt exist, create empty one // if file doesnt exist, create empty one
fd = fopen(file, "r+b"); fd = fopen(file.data(), "r+b");
if (fd == NULL) { if (fd == NULL)
{
Console::Notice("MEC File Not Found , Creating Blank File"); Console::Notice("MEC File Not Found , Creating Blank File");
fd = fopen(file, "wb"); fd = fopen(file.data(), "wb");
if (fd == NULL) if (fd == NULL)
{ {
Console::Error( "\tMEC File Creation failed!" ); Console::Error( "\tMEC File Creation failed!" );
@ -121,38 +112,26 @@ s32 cdvdGetMechaVer(u8* ver)
return 0; return 0;
} }
FILE *_cdvdOpenNVM() { FILE *_cdvdOpenNVM()
char *ptr; {
int i;
char file[g_MaxPath];
FILE* fd; FILE* fd;
// get the name of the bios file wxFileName nvmfile(EmuConfig.BiosFilename);
nvmfile.SetExt( L"nvm" );
// use the bios filename to get the name of the nvm file wxCharBuffer file( nvmfile.GetFullPath().ToUTF8() );
// [TODO] : Upgrade this to use wxString!
strcpy( file, g_Conf->FullpathToBios().ToAscii().data() );
ptr = file;
i = (int)strlen(file);
while (i > 0) { if (ptr[i] == '.') break; i--; }
ptr[i+1] = '\0';
strcat(file, "NVM");
// if file doesnt exist, create empty one // if file doesnt exist, create empty one
fd = fopen(file, "r+b"); fd = fopen(file.data(), "r+b");
if (fd == NULL) { if (fd == NULL)
{
Console::Notice("NVM File Not Found , Creating Blank File"); Console::Notice("NVM File Not Found , Creating Blank File");
fd = fopen(file, "wb"); fd = fopen(file.data(), "wb");
if (fd == NULL) if (fd == NULL)
{ {
Console::Error( "\tMEC File Creation failed!" );
throw Exception::CreateStream( file ); throw Exception::CreateStream( file );
//Msgbox::Alert("_cdvdOpenNVM: Error creating %s", file);
//exit(1);
} }
for (i=0; i<1024; i++) fputc(0, fd); for (int i=0; i<1024; i++) fputc(0, fd);
} }
return fd; return fd;
} }

View File

@ -173,6 +173,25 @@ public:
VideoOptions(); VideoOptions();
void LoadSave( IniInterface& conf ); void LoadSave( IniInterface& conf );
bool operator ==( const VideoOptions& right ) const
{
return
OpEqu( EnableFrameSkipping ) &&
OpEqu( EnableFrameLimiting ) &&
OpEqu( DefaultRegionMode ) &&
OpEqu( FpsTurbo ) &&
OpEqu( FpsLimit ) &&
OpEqu( FpsSkip ) &&
OpEqu( ConsecutiveFrames ) &&
OpEqu( ConsecutiveSkip );
}
bool operator !=( const VideoOptions& right ) const
{
return !this->operator ==( right );
}
}; };
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -255,6 +274,8 @@ public:
GamefixOptions Gamefixes; GamefixOptions Gamefixes;
ProfilerOptions Profiler; ProfilerOptions Profiler;
wxFileName BiosFilename;
Pcsx2Config(); Pcsx2Config();
void LoadSave( IniInterface& ini ); void LoadSave( IniInterface& ini );
@ -262,6 +283,23 @@ public:
void Load( const wxInputStream& srcstream ); void Load( const wxInputStream& srcstream );
void Save( const wxString& dstfile ); void Save( const wxString& dstfile );
void Save( const wxOutputStream& deststream ); void Save( const wxOutputStream& deststream );
bool operator ==( const Pcsx2Config& right ) const
{
return
OpEqu( bitset ) &&
OpEqu( Cpu ) &&
OpEqu( Video ) &&
OpEqu( Speedhacks ) &&
OpEqu( Gamefixes ) &&
OpEqu( Profiler ) &&
OpEqu( BiosFilename );
}
bool operator !=( const Pcsx2Config& right ) const
{
return !this->operator ==( right );
}
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -235,18 +235,19 @@ void SysAllocateDynarecs()
} }
////////////////////////////////////////////////////////////////////////////////////////// // This should be called last thing before PCSX2 exits.
// This should be called last thing before Pcsx2 exits.
// //
void SysShutdownMem() void SysShutdownMem()
{ {
if( sysInitialized )
SysShutdown();
vuMicroMemShutdown(); vuMicroMemShutdown();
psxMemShutdown(); psxMemShutdown();
memShutdown(); memShutdown();
vtlb_Core_Shutdown(); vtlb_Core_Shutdown();
} }
//////////////////////////////////////////////////////////////////////////////////////////
// This should generally be called right before calling SysShutdownMem(), although you can optionally // This should generally be called right before calling SysShutdownMem(), although you can optionally
// use it in conjunction with SysAllocDynarecs to allocate/free the dynarec resources on the fly (as // use it in conjunction with SysAllocDynarecs to allocate/free the dynarec resources on the fly (as
// risky as it might be, since dynarecs could very well fail on the second attempt). // risky as it might be, since dynarecs could very well fail on the second attempt).
@ -255,12 +256,25 @@ void SysShutdownDynarecs()
// Special SuperVU "complete" terminator. // Special SuperVU "complete" terminator.
SuperVUDestroy( -1 ); SuperVUDestroy( -1 );
VU0micro::recShutdown();
VU1micro::recShutdown();
psxRec.Shutdown(); psxRec.Shutdown();
recCpu.Shutdown(); recCpu.Shutdown();
} }
void SysShutdown()
{
sysInitialized = false;
Console::Status( "Shutting down PS2 virtual machine..." );
SysEndExecution();
safe_delete( g_plugins );
SysShutdownDynarecs();
SysShutdownMem();
}
//////////////////////////////////////////////////////////////////////////////////////////
// Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition. // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
// This can be called at any time outside the context of a Cpu->Execute() block without // This can be called at any time outside the context of a Cpu->Execute() block without
// bad things happening (recompilers will slow down for a brief moment since rec code blocks // bad things happening (recompilers will slow down for a brief moment since rec code blocks
@ -312,6 +326,7 @@ void SysExecute( CoreEmuThread* newThread )
void SysEndExecution() void SysEndExecution()
{ {
safe_delete( g_EmuThread ); safe_delete( g_EmuThread );
GetPluginManager().Shutdown();
} }
void SysSuspend() void SysSuspend()
@ -359,12 +374,12 @@ void SysLoadState( const wxString& file )
GSsetGameCRC(ElfCRC, g_ZeroGSOptions); GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
} }
void SysShutdown() void SysReset()
{ {
Console::Status( "Resetting..." ); Console::Status( "Resetting PS2 virtual machine..." );
safe_delete( g_EmuThread ); SysShutdown();
GetPluginManager().Shutdown(); StateRecovery::Clear();
ElfCRC = 0; ElfCRC = 0;
// Note : No need to call cpuReset() here. It gets called automatically before the // Note : No need to call cpuReset() here. It gets called automatically before the
@ -413,8 +428,10 @@ bool SysInit()
if( sysInitialized ) return true; if( sysInitialized ) return true;
sysInitialized = true; sysInitialized = true;
PCSX2_MEM_PROTECT_BEGIN();
SysDetect(); SysDetect();
PCSX2_MEM_PROTECT_BEGIN();
Console::Status( "Initializing PS2 virtual machine..." );
if( !SysAllocateMem() ) if( !SysAllocateMem() )
return false; // critical memory allocation failure; return false; // critical memory allocation failure;

View File

@ -30,7 +30,7 @@ class CoreEmuThread;
extern bool SysInit(); extern bool SysInit();
extern void SysDetect(); // Detects cpu type and fills cpuInfo structs. extern void SysDetect(); // Detects cpu type and fills cpuInfo structs.
extern void SysShutdown(); // Resets the various PS2 cpus, sub-systems, and recompilers. extern void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
extern void SysExecute( CoreEmuThread* newThread ); extern void SysExecute( CoreEmuThread* newThread );
extern void SysExecute( CoreEmuThread* newThread, CDVD_SourceType cdvdsrc ); extern void SysExecute( CoreEmuThread* newThread, CDVD_SourceType cdvdsrc );
@ -43,6 +43,7 @@ extern bool SysAllocateMem(); // allocates memory for all PS2 systems; returns
extern void SysAllocateDynarecs(); // allocates memory for all dynarecs, and force-disables any failures. extern void SysAllocateDynarecs(); // allocates memory for all dynarecs, and force-disables any failures.
extern void SysShutdownDynarecs(); extern void SysShutdownDynarecs();
extern void SysShutdownMem(); extern void SysShutdownMem();
extern void SysShutdown();
extern void SysLoadState( const wxString& file ); extern void SysLoadState( const wxString& file );
extern void SysRestorableReset(); // Saves the current emulation state prior to spu reset. extern void SysRestorableReset(); // Saves the current emulation state prior to spu reset.

View File

@ -234,6 +234,8 @@ public:
bool OnInit(); bool OnInit();
int OnExit(); int OnExit();
void CleanUp();
void OnInitCmdLine( wxCmdLineParser& parser ); void OnInitCmdLine( wxCmdLineParser& parser );
bool OnCmdLineParsed( wxCmdLineParser& parser ); bool OnCmdLineParsed( wxCmdLineParser& parser );
bool OnCmdLineError( wxCmdLineParser& parser ); bool OnCmdLineError( wxCmdLineParser& parser );

View File

@ -457,6 +457,8 @@ void AppConfig::Apply()
Folders.Savestates.Mkdir(); Folders.Savestates.Mkdir();
Folders.Snapshots.Mkdir(); Folders.Snapshots.Mkdir();
g_Conf->EmuOptions.BiosFilename = g_Conf->FullpathToBios();
// Update the compression attribute on the Memcards folder. // Update the compression attribute on the Memcards folder.
// Memcards generally compress very well via NTFS compression. // Memcards generally compress very well via NTFS compression.

View File

@ -192,7 +192,7 @@ void MainEmuFrame::Menu_SaveStateOther_Click(wxCommandEvent &event)
void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event)
{ {
SysShutdown(); SysReset();
Close(); Close();
} }
@ -213,7 +213,7 @@ void MainEmuFrame::Menu_EmuPause_Click(wxCommandEvent &event)
void MainEmuFrame::Menu_EmuReset_Click(wxCommandEvent &event) void MainEmuFrame::Menu_EmuReset_Click(wxCommandEvent &event)
{ {
bool wasRunning = EmulationInProgress(); bool wasRunning = EmulationInProgress();
SysShutdown(); SysReset();
GetMenuBar()->Check( MenuId_Emu_Pause, false ); GetMenuBar()->Check( MenuId_Emu_Pause, false );

View File

@ -75,6 +75,8 @@ void AppEmuThread::Resume()
m_kevt.m_controlDown = false; m_kevt.m_controlDown = false;
m_kevt.m_altDown = false; m_kevt.m_altDown = false;
ApplySettings( g_Conf->EmuOptions );
CoreEmuThread::Resume(); CoreEmuThread::Resume();
} }
@ -464,13 +466,22 @@ void Pcsx2App::OnMessageBox( pxMessageBoxEvent& evt )
Msgbox::OnEvent( evt ); Msgbox::OnEvent( evt );
} }
#include <wx/intl.h>
void Pcsx2App::CleanupMess() void Pcsx2App::CleanupMess()
{ {
SysShutdown();
safe_delete( m_Bitmap_Logo ); safe_delete( m_Bitmap_Logo );
safe_delete( g_Conf ); safe_delete( g_Conf );
} }
// This cleanup procedure is issued by wxWidgets prior to destroying base windows and window
// classes.
void Pcsx2App::CleanUp()
{
SysShutdown();
wxApp::CleanUp();
}
void Pcsx2App::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const void Pcsx2App::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const
{ {
try try
@ -531,6 +542,8 @@ Pcsx2App::Pcsx2App() :
Pcsx2App::~Pcsx2App() Pcsx2App::~Pcsx2App()
{ {
CleanupMess(); CleanupMess();
while( wxGetLocale() != NULL )
delete wxGetLocale();
} }

View File

@ -263,6 +263,8 @@ void CoreEmuThread::Suspend( bool isBlocking )
// is determined by comparing the current settings against the new settings. // is determined by comparing the current settings against the new settings.
void CoreEmuThread::ApplySettings( const Pcsx2Config& src ) void CoreEmuThread::ApplySettings( const Pcsx2Config& src )
{ {
if( src == EmuConfig ) return;
const bool isRunning = IsRunning(); const bool isRunning = IsRunning();
Suspend(); Suspend();