Files
ARMSX2/pcsx2/System/SysCoreThread.cpp
T
Avi Halachmi (:avih) cff8cb137c patches: simplify by unifying patches/cheats (effectively no-op)
patches and cheats are exactly the same (pnach style patch line) but we
stored two sets of them depending on their source: "patches" for
GameIndex.dbf patches, and "cheats" for all the rest (cheats, widescreen,
etc).

Unify patches and cheats and keep only "patches", cleanup and rename the
public API at Patch.h, and add documentation.

Also: add some console messages on invalid "place" value, and when we skip
searching cheats_ws.zip because a pnach file was found at cheats_ws dir.

Also: removed checks before applying different kinds of patches/cheats
because we don't need them (we didn't have disabled patches loaded anyway).

The checks removal _shouldn't_ have any effect, except that the checks were
wrong and accidentally prevented loading widescreen hacks which have a place
value of 0. No one probably noticed it since all the widescreen patches
which I looked at have a place value of 1. So now ws patches with place=0
would load correctly too. If we'll ever have such.
2016-07-27 18:15:17 +03:00

306 lines
8.4 KiB
C++

/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include "gui/App.h"
#include "IopBios.h"
#include "Counters.h"
#include "GS.h"
#include "Elfheader.h"
#include "Patch.h"
#include "SysThreads.h"
#include "MTVU.h"
#include "../DebugTools/MIPSAnalyst.h"
#include "../DebugTools/SymbolMap.h"
#include "Utilities/PageFaultSource.h"
#include "Utilities/TlsVariable.inl"
#ifdef __WXMSW__
# include <wx/msw/wrapwin.h>
#endif
#include "x86emitter/x86_intrin.h"
// --------------------------------------------------------------------------------------
// SysCoreThread *External Thread* Implementations
// (Called from outside the context of this thread)
// --------------------------------------------------------------------------------------
SysCoreThread::SysCoreThread()
{
m_name = L"EE Core";
m_resetRecompilers = true;
m_resetProfilers = true;
m_resetVsyncTimers = true;
m_resetVirtualMachine = true;
m_hasActiveMachine = false;
}
SysCoreThread::~SysCoreThread() throw()
{
try {
SysCoreThread::Cancel();
}
DESTRUCTOR_CATCHALL
}
void SysCoreThread::Cancel( bool isBlocking )
{
m_hasActiveMachine = false;
_parent::Cancel();
}
bool SysCoreThread::Cancel( const wxTimeSpan& span )
{
m_hasActiveMachine = false;
if( _parent::Cancel( span ) )
return true;
return false;
}
void SysCoreThread::OnStart()
{
_parent::OnStart();
}
void SysCoreThread::Start()
{
if( !GetCorePlugins().AreLoaded() ) return;
GetCorePlugins().Init();
_parent::Start();
}
// 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.
//
// Exceptions (can occur on first call only):
// PluginInitError - thrown if a plugin fails init (init is performed on the current thread
// on the first time the thread is resumed from it's initial idle state)
// ThreadCreationError - Insufficient system resources to create thread.
//
void SysCoreThread::OnResumeReady()
{
if( m_resetVirtualMachine )
m_hasActiveMachine = false;
if( !m_hasActiveMachine )
m_resetRecompilers = true;
}
// This function *will* reset the emulator in order to allow the specified elf file to
// take effect. This is because it really doesn't make sense to change the elf file outside
// the context of a reset/restart.
void SysCoreThread::SetElfOverride( const wxString& elf )
{
//pxAssertDev( !m_hasValidMachine, "Thread synchronization error while assigning ELF override." );
m_elf_override = elf;
Hle_SetElfPath(elf.ToUTF8());
}
// Performs a quicker reset that does not deallocate memory associated with PS2 virtual machines
// or cpu providers (recompilers).
void SysCoreThread::ResetQuick()
{
Suspend();
m_resetVirtualMachine = true;
m_hasActiveMachine = false;
}
void SysCoreThread::Reset()
{
ResetQuick();
GetVmMemory().DecommitAll();
SysClearExecutionCache();
sApp.PostAppMethod( &Pcsx2App::leaveDebugMode );
g_FrameCount = 0;
}
// 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, so that only
// real differences are applied.
void SysCoreThread::ApplySettings( const Pcsx2Config& src )
{
if( src == EmuConfig ) return;
if( !pxAssertDev( IsPaused(), "CoreThread is not paused; settings cannot be applied." ) ) return;
m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
m_resetProfilers = ( src.Profiler != EmuConfig.Profiler );
m_resetVsyncTimers = ( src.GS != EmuConfig.GS );
const_cast<Pcsx2Config&>(EmuConfig) = src;
}
void SysCoreThread::UploadStateCopy( const VmStateBuffer& copy )
{
if( !pxAssertDev( IsPaused(), "CoreThread is not paused; new VM state cannot be uploaded." ) ) return;
memLoadingState loadme( copy );
loadme.FreezeAll();
m_resetVirtualMachine = false;
}
// --------------------------------------------------------------------------------------
// SysCoreThread *Worker* Implementations
// (Called from the context of this thread only)
// --------------------------------------------------------------------------------------
bool SysCoreThread::HasPendingStateChangeRequest() const
{
return !m_hasActiveMachine || GetMTGS().HasPendingException() || _parent::HasPendingStateChangeRequest();
}
void SysCoreThread::_reset_stuff_as_needed()
{
// Note that resetting recompilers along with the virtual machine is only really needed
// because of changes to the TLB. We don't actually support the TLB, however, so rec
// resets aren't in fact *needed* ... yet. But might as well, no harm. --air
GetVmMemory().CommitAll();
if( m_resetVirtualMachine || m_resetRecompilers || m_resetProfilers )
{
SysClearExecutionCache();
memBindConditionalHandlers();
SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR );
m_resetRecompilers = false;
m_resetProfilers = false;
}
if( m_resetVirtualMachine )
{
DoCpuReset();
m_resetVirtualMachine = false;
m_resetVsyncTimers = false;
ForgetLoadedPatches();
}
if( m_resetVsyncTimers )
{
UpdateVSyncRate();
frameLimitReset();
m_resetVsyncTimers = false;
}
}
void SysCoreThread::DoCpuReset()
{
AffinityAssert_AllowFromSelf( pxDiagSpot );
cpuReset();
}
// This is called from the PS2 VM at the start of every vsync (either 59.94 or 50 hz by PS2
// clock scale, which does not correlate to the actual host machine vsync).
//
// Default tasks: Updates PADs and applies vsync patches. Derived classes can override this
// to change either PAD and/or Patching behaviors.
//
// [TODO]: Should probably also handle profiling and debugging updates, once those are
// re-implemented.
//
void SysCoreThread::VsyncInThread()
{
ApplyLoadedPatches(PPT_CONTINUOUSLY);
}
void SysCoreThread::GameStartingInThread()
{
GetMTGS().SendGameCRC(ElfCRC);
MIPSAnalyst::ScanForFunctions(ElfTextRange.first,ElfTextRange.first+ElfTextRange.second,true);
symbolMap.UpdateActiveSymbols();
sApp.PostAppMethod(&Pcsx2App::resetDebugger);
ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
}
bool SysCoreThread::StateCheckInThread()
{
GetMTGS().RethrowException();
return _parent::StateCheckInThread() && (_reset_stuff_as_needed(), true);
}
// Runs CPU cycles indefinitely, until the user or another thread requests execution to break.
// Rationale: This very short function allows an override point and solves an SEH
// "exception-type boundary" problem (can't mix SEH and C++ exceptions in the same function).
void SysCoreThread::DoCpuExecute()
{
m_hasActiveMachine = true;
UI_EnableSysActions();
Cpu->Execute();
}
void SysCoreThread::ExecuteTaskInThread()
{
Threading::EnableHiresScheduler(); // Note that *something* in SPU2-X and GSdx also set the timer resolution to 1ms.
m_sem_event.WaitWithoutYield();
m_mxcsr_saved.bitmask = _mm_getcsr();
PCSX2_PAGEFAULT_PROTECT {
while(true) {
StateCheckInThread();
DoCpuExecute();
}
} PCSX2_PAGEFAULT_EXCEPT;
}
void SysCoreThread::OnSuspendInThread()
{
GetCorePlugins().Close();
}
void SysCoreThread::OnResumeInThread( bool isSuspended )
{
GetCorePlugins().Open();
}
// Invoked by the pthread_exit or pthread_cancel.
void SysCoreThread::OnCleanupInThread()
{
m_ExecMode = ExecMode_Closing;
m_hasActiveMachine = false;
m_resetVirtualMachine = true;
// FIXME: temporary workaround for deadlock on exit, which actually should be a crash
vu1Thread.WaitVU();
GetCorePlugins().Close();
GetCorePlugins().Shutdown();
_mm_setcsr( m_mxcsr_saved.bitmask );
Threading::DisableHiresScheduler();
_parent::OnCleanupInThread();
m_ExecMode = ExecMode_NoThreadYet;
}