* Fixing automatic patch application (again!) -- random crashes could occur on some games due to in-execution recompiler resets when gamefix options were changed by the GameDB.

* Implemented --gamefixes to the command line.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3289 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-06-24 16:04:27 +00:00
parent 23d88fa21e
commit 35b05e3836
6 changed files with 59 additions and 51 deletions

View File

@ -337,8 +337,8 @@ static __forceinline void frameLimit()
static __forceinline void VSyncStart(u32 sCycle)
{
Cpu->CheckExecutionState();
GetCoreThread().VsyncInThread();
Cpu->CheckExecutionState();
EECNT_LOG( "///////// EE COUNTER VSYNC START (frame: %6d) \\\\\\\\\\\\\\\\\\\\ ", g_FrameCount );

View File

@ -583,6 +583,10 @@ void __fastcall eeGameStarting()
Console.WriteLn( Color_Green, "(R5900) ELF Entry point! [addr=0x%08X]", ElfEntry );
g_GameStarted = true;
GetCoreThread().GameStartingInThread();
// GameStartingInThread may issue a reset of the cpu and/or recompilers. Check for and
// handle such things here:
Cpu->CheckExecutionState();
}
else
{

View File

@ -305,7 +305,7 @@ public:
// Note that gamefixes in this array should only be honored if the
// "HasCustomGamefixes" boolean is also enabled.
bool UseGamefix[GamefixId_COUNT];
Pcsx2Config::GamefixOptions Gamefixes;
bool ApplyCustomGamefixes;
GsWindowMode_t GsWindowMode;

View File

@ -173,11 +173,8 @@ void AppCoreThread::OnResumeReady()
// Load Game Settings found in database
// (game fixes, round modes, clamp modes, etc...)
// Returns number of gamefixes set
static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) {
if (!gameDB) gameDB = wxGetApp().GetGameDatabase();
Game_Data game;
if (!gameDB->findGame(game, SysGetDiscID())) return 0;
static int loadGameSettings(Pcsx2Config& dest, const Game_Data& game) {
if( !game.IsOk() ) return 0;
int gf = 0;
@ -229,7 +226,7 @@ static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) {
if (game.keyExists(key))
{
bool enableIt = game.getBool(key);
dest.Gamefixes.Set(id, enableIt );
dest.Gamefixes.Set(id, enableIt);
Console.WriteLn(L"(GameDB) %s Gamefix: " + key, enableIt ? L"Enabled" : L"Disabled" );
gf++;
}
@ -240,8 +237,28 @@ static int loadGameSettings(Pcsx2Config& dest, IGameDatabase* gameDB) {
void AppCoreThread::ApplySettings( const Pcsx2Config& src )
{
// 'fixup' is the EmuConfig we're going to upload to the emulator, which very well may
// differ from the user-configured EmuConfig settings. So we make a copy here and then
// we apply the commandline overrides and database gamefixes, and then upload 'fixup'
// to the global EmuConfig.
//
// Note: It's important that we apply the commandline overrides *before* database fixes.
// The database takes precedence (if enabled).
Pcsx2Config fixup( src );
const CommandlineOverrides& overrides( wxGetApp().Overrides );
if( overrides.DisableSpeedhacks || !g_Conf->EnableSpeedHacks )
fixup.Speedhacks = Pcsx2Config::SpeedhackOptions();
if( overrides.ApplyCustomGamefixes )
{
for (GamefixId id=GamefixId_FIRST; id < pxEnumEnd; ++id)
fixup.Gamefixes.Set( id, overrides.Gamefixes.Get(id) );
}
else if( !g_Conf->EnableGameFixes )
fixup.Gamefixes = Pcsx2Config::GamefixOptions();
wxString gameCRC;
wxString gameSerial;
wxString gamePatch;
@ -269,7 +286,7 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
if (int patches = InitPatches(gameCRC, game)) {
gamePatch.Printf(L" [%d Patches]", patches);
}
if (int fixes = loadGameSettings(fixup, GameDB)) {
if (int fixes = loadGameSettings(fixup, game)) {
gameFixes.Printf(L" [%d Fixes]", fixes);
}
}
@ -283,18 +300,6 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
Console.SetTitle(gameName+gameSerial+gameCompat+gameFixes+gamePatch+gameCheats);
const CommandlineOverrides& overrides( wxGetApp().Overrides );
if( overrides.DisableSpeedhacks || !g_Conf->EnableSpeedHacks )
fixup.Speedhacks = Pcsx2Config::SpeedhackOptions();
if( overrides.ApplyCustomGamefixes )
{
for (GamefixId id=GamefixId_FIRST; id < pxEnumEnd; ++id)
fixup.Gamefixes.Set( id, overrides.UseGamefix[id] );
}
else if( !g_Conf->EnableGameFixes )
fixup.Gamefixes = Pcsx2Config::GamefixOptions();
// Re-entry guard protects against cases where code wants to manually set core settings
// which are not part of g_Conf. The subsequent call to apply g_Conf settings (which is
// usually the desired behavior) will be ignored.

View File

@ -357,9 +357,9 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
parser.AddSwitch( wxEmptyString,L"nodisc", _("boots an empty dvd tray; use to enter the PS2 system menu") );
parser.AddSwitch( wxEmptyString,L"usecd", _("boots from the CDVD plugin (overrides IsoFile parameter)") );
parser.AddSwitch( wxEmptyString,L"fullboot", _("disables fast booting") );
parser.AddSwitch( wxEmptyString,L"nohacks", _("disables all speedhacks") );
parser.AddSwitch( wxEmptyString,L"gamefixes", _("use the specified comma or pipe-delimited list of gamefixes.") + fixlist );
parser.AddOption( wxEmptyString,L"gamefixes", _("use the specified comma or pipe-delimited list of gamefixes.") + fixlist, wxCMD_LINE_VAL_STRING );
parser.AddSwitch( wxEmptyString,L"fullboot", _("disables fast booting") );
parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING );
parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use"), wxCMD_LINE_VAL_STRING );
@ -398,6 +398,12 @@ bool Pcsx2App::ParseOverrides( wxCmdLineParser& parser )
Overrides.DisableSpeedhacks = parser.Found(L"nohacks");
if (parser.Found(L"gamefixes", &dest))
{
Overrides.ApplyCustomGamefixes = true;
Overrides.Gamefixes.Set( dest, true );
}
if (parser.Found(L"fullscreen")) Overrides.GsWindowMode = GsWinMode_Fullscreen;
if (parser.Found(L"windowed")) Overrides.GsWindowMode = GsWinMode_Windowed;

View File

@ -450,16 +450,14 @@ static DynGenFunc* _DynGen_EnterRecompiledCode()
// for the duration of our function, and is used to restore the original
// esp before returning from the function
// Optimization: We "allocate" 0x10 bytes of stack ahead of time here, which we can
// use for supplying parameters to cdecl functions.
xPUSH( ebp );
xMOV( ebp, esp );
xAND( esp, -0x10 );
// First 0x10 is for esi, edi, etc. Second 0x10 is for the return address and ebp. The
// third 0x10 is for C-style CDECL calls we might make from the recompiler
// (parameters for those calls can be stored there!)
// third 0x10 is an optimization for C-style CDECL calls we might make from the recompiler
// (parameters for those calls can be stored there!) [currently no cdecl functions are
// used -- we do everything through __fastcall)
xSUB( esp, 0x30 );
@ -616,11 +614,12 @@ struct ManualPageTracking
static __aligned16 u16 manual_page[Ps2MemSize::Base >> 12];
static __aligned16 u8 manual_counter[Ps2MemSize::Base >> 12];
static u32 eeRecIsReset = 0;
static u32 eeRecIsReset = false;
////////////////////////////////////////////////////
void recResetEE( void )
{
//AtomicExchange( eeRecNeedsReset, false );
if( AtomicExchange( eeRecIsReset, true ) ) return;
Console.WriteLn( Color_StrongBlack, "Issuing EE/iR5900-32 Recompiler Reset" );
@ -707,22 +706,25 @@ void recStep( void )
static jmp_buf m_SetJmp_StateCheck;
static void recExitExecution()
{
#if PCSX2_SEH
throw Exception::ExitCpuExecute();
#else
// Without SEH we'll need to hop to a safehouse point outside the scope of recompiled
// code. C++ exceptions can't cross the mighty chasm in the stackframe that the recompiler
// creates. However, the longjump is slow so we only want to do one when absolutely
// necessary:
longjmp( m_SetJmp_StateCheck, 1 );
#endif
}
static void recCheckExecutionState()
{
pxAssert( !eeRecIsReset ); // should only be changed during suspended thread states
if( GetCoreThread().HasPendingStateChangeRequest() )
if( eeRecIsReset || GetCoreThread().HasPendingStateChangeRequest() )
{
#if PCSX2_SEH
throw Exception::ExitCpuExecute();
#else
// Without SEH we'll need to hop to a safehouse point outside the scope of recompiled
// code. C++ exceptions can't cross the mighty chasm in the stackframe that the recompiler
// creates. However, the longjump is slow so we only want to do one when absolutely
// necessary:
longjmp( m_SetJmp_StateCheck, 1 );
#endif
recExitExecution();
}
}
@ -867,15 +869,6 @@ void recClear(u32 addr, u32 size)
}
static void recExitExecution()
{
#if PCSX2_SEH
throw Exception::ExitCpuExecute();
#else
longjmp( m_SetJmp_StateCheck, 1 );
#endif
}
static int *s_pCode;
void SetBranchReg( u32 reg )