mirror of https://github.com/PCSX2/pcsx2.git
mtgs: switching to a plugin-less architecture
This commit is contained in:
parent
f04f941dbb
commit
160117ffbb
|
@ -340,7 +340,7 @@ public:
|
|||
int m_CopyDataTally;
|
||||
|
||||
Semaphore m_sem_OpenDone;
|
||||
std::atomic<bool> m_PluginOpened;
|
||||
std::atomic<bool> m_Opened;
|
||||
|
||||
// These vars maintain instance data for sending Data Packets.
|
||||
// Only one data packet can be constructed and uploaded at a time.
|
||||
|
@ -376,11 +376,11 @@ public:
|
|||
void SetEvent();
|
||||
void PostVsyncStart();
|
||||
|
||||
bool IsPluginOpened() const { return m_PluginOpened; }
|
||||
bool IsGSOpened() const { return m_Opened; }
|
||||
|
||||
protected:
|
||||
void OpenPlugin();
|
||||
void ClosePlugin();
|
||||
void OpenGS();
|
||||
void CloseGS();
|
||||
|
||||
void OnStart();
|
||||
void OnResumeReady();
|
||||
|
|
|
@ -70,7 +70,7 @@ SysMtgsThread::SysMtgsThread()
|
|||
|
||||
void SysMtgsThread::OnStart()
|
||||
{
|
||||
m_PluginOpened = false;
|
||||
m_Opened = false;
|
||||
|
||||
m_ReadPos = 0;
|
||||
m_WritePos = 0;
|
||||
|
@ -199,33 +199,21 @@ static void dummyIrqCallback()
|
|||
// (and zerogs does >_<)
|
||||
}
|
||||
|
||||
void SysMtgsThread::OpenPlugin()
|
||||
void SysMtgsThread::OpenGS()
|
||||
{
|
||||
|
||||
if (m_PluginOpened)
|
||||
if (m_Opened)
|
||||
return;
|
||||
|
||||
memcpy(RingBuffer.Regs, PS2MEM_GS, sizeof(PS2MEM_GS));
|
||||
GSsetBaseMem(RingBuffer.Regs);
|
||||
GSirqCallback(dummyIrqCallback);
|
||||
|
||||
int result;
|
||||
|
||||
if (GSopen2 != NULL)
|
||||
result = GSopen2((void*)pDsp, 1 | (renderswitch ? 4 : 0));
|
||||
else
|
||||
result = GSopen((void*)pDsp, "PCSX2", renderswitch ? 2 : 1);
|
||||
|
||||
pxAssert(GSopen2((void*)pDsp, 1 | (renderswitch ? 4 : 0)) != 0);
|
||||
|
||||
GSsetVsync(EmuConfig.GS.GetVsync());
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
DevCon.WriteLn("GSopen Failed: return code: 0x%x", result);
|
||||
throw Exception::PluginOpenError(PluginId_GS);
|
||||
}
|
||||
|
||||
m_PluginOpened = true;
|
||||
m_Opened = true;
|
||||
m_sem_OpenDone.Post();
|
||||
|
||||
GSsetGameCRC(ElfCRC, 0);
|
||||
|
@ -335,13 +323,13 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
if (endpos >= RingBufferSize)
|
||||
{
|
||||
uint firstcopylen = RingBufferSize - datapos;
|
||||
GSgifTransfer((u32*)data, firstcopylen);
|
||||
GSgifTransfer((u8*)data, firstcopylen);
|
||||
datapos = endpos & RingBufferMask;
|
||||
GSgifTransfer((u32*)RingBuffer.m_Ring, datapos);
|
||||
GSgifTransfer((u8*)RingBuffer.m_Ring, datapos);
|
||||
}
|
||||
else
|
||||
{
|
||||
GSgifTransfer((u32*)data, qsize);
|
||||
GSgifTransfer((u8*)data, qsize);
|
||||
}
|
||||
|
||||
ringposinc += qsize;
|
||||
|
@ -404,7 +392,7 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
u32 offset = tag.data[0];
|
||||
u32 size = tag.data[1];
|
||||
if (offset != ~0u)
|
||||
GSgifTransfer((u32*)&path.buffer[offset], size / 16);
|
||||
GSgifTransfer((u8*)&path.buffer[offset], size / 16);
|
||||
path.readAmount.fetch_sub(size, std::memory_order_acq_rel);
|
||||
break;
|
||||
}
|
||||
|
@ -420,7 +408,7 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
Gif_Path& path = gifUnit.gifPath[GIF_PATH_1];
|
||||
GS_Packet gsPack = path.GetGSPacketMTVU(); // Get vu1 program's xgkick packet(s)
|
||||
if (gsPack.size)
|
||||
GSgifTransfer((u32*)&path.buffer[gsPack.offset], gsPack.size / 16);
|
||||
GSgifTransfer((u8*)&path.buffer[gsPack.offset], gsPack.size / 16);
|
||||
path.readAmount.fetch_sub(gsPack.size + gsPack.readAmount, std::memory_order_acq_rel);
|
||||
path.PopGSPacketMTVU(); // Should be done last, for proper Gif_MTGS_Wait()
|
||||
break;
|
||||
|
@ -478,8 +466,7 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
|
||||
case GS_RINGTYPE_RESET:
|
||||
MTGS_LOG("(MTGS Packet Read) ringtype=Reset");
|
||||
if (GSreset != NULL)
|
||||
GSreset();
|
||||
GSreset();
|
||||
break;
|
||||
|
||||
case GS_RINGTYPE_SOFTRESET:
|
||||
|
@ -500,14 +487,12 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
|
||||
case GS_RINGTYPE_INIT_READ_FIFO1:
|
||||
MTGS_LOG("(MTGS Packet Read) ringtype=Fifo1");
|
||||
if (GSinitReadFIFO)
|
||||
GSinitReadFIFO((u64*)tag.pointer);
|
||||
GSinitReadFIFO((u8*)tag.pointer);
|
||||
break;
|
||||
|
||||
case GS_RINGTYPE_INIT_READ_FIFO2:
|
||||
MTGS_LOG("(MTGS Packet Read) ringtype=Fifo2, size=%d", tag.data[0]);
|
||||
if (GSinitReadFIFO2)
|
||||
GSinitReadFIFO2((u64*)tag.pointer, tag.data[0]);
|
||||
GSinitReadFIFO2((u8*)tag.pointer, tag.data[0]);
|
||||
break;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
@ -566,31 +551,31 @@ void SysMtgsThread::ExecuteTaskInThread()
|
|||
}
|
||||
}
|
||||
|
||||
void SysMtgsThread::ClosePlugin()
|
||||
void SysMtgsThread::CloseGS()
|
||||
{
|
||||
if (!m_PluginOpened)
|
||||
if (!m_Opened)
|
||||
return;
|
||||
m_PluginOpened = false;
|
||||
m_Opened = false;
|
||||
GetCorePlugins().Close(PluginId_GS);
|
||||
}
|
||||
|
||||
void SysMtgsThread::OnSuspendInThread()
|
||||
{
|
||||
ClosePlugin();
|
||||
CloseGS();
|
||||
_parent::OnSuspendInThread();
|
||||
}
|
||||
|
||||
void SysMtgsThread::OnResumeInThread(bool isSuspended)
|
||||
{
|
||||
if (isSuspended)
|
||||
OpenPlugin();
|
||||
OpenGS();
|
||||
|
||||
_parent::OnResumeInThread(isSuspended);
|
||||
}
|
||||
|
||||
void SysMtgsThread::OnCleanupInThread()
|
||||
{
|
||||
ClosePlugin();
|
||||
CloseGS();
|
||||
_parent::OnCleanupInThread();
|
||||
}
|
||||
|
||||
|
@ -873,7 +858,7 @@ void SysMtgsThread::SendGameCRC(u32 crc)
|
|||
|
||||
void SysMtgsThread::WaitForOpen()
|
||||
{
|
||||
if (m_PluginOpened)
|
||||
if (m_Opened)
|
||||
return;
|
||||
Resume();
|
||||
|
||||
|
@ -893,9 +878,7 @@ void SysMtgsThread::WaitForOpen()
|
|||
// Not opened yet, and no exceptions. Weird? You decide!
|
||||
// [TODO] : implement a user confirmation to cancel the action and exit the
|
||||
// emulator forcefully, or to continue waiting on the GS.
|
||||
|
||||
throw Exception::PluginOpenError(PluginId_GS)
|
||||
.SetBothMsgs(pxLt("The MTGS thread has become unresponsive while waiting for the GS plugin to open."));
|
||||
pxAssert(_("The MTGS thread has become unresponsive while waiting for the GS plugin to open."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <wx/filename.h>
|
||||
#include "Utilities/pxStreams.h"
|
||||
#include "Utilities/Console.h"
|
||||
#include "App.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
|
|
@ -75,86 +75,6 @@ std::unique_ptr<AppConfig> g_Conf;
|
|||
AspectRatioType iniAR;
|
||||
bool switchAR;
|
||||
|
||||
static bool HandlePluginError( BaseException& ex )
|
||||
{
|
||||
if (!pxDialogExists(L"Dialog:" + Dialogs::ComponentsConfigDialog::GetNameStatic()))
|
||||
{
|
||||
if( !Msgbox::OkCancel( ex.FormatDisplayMessage() +
|
||||
_("\n\nPress Ok to go to the Plugin Configuration Panel.")
|
||||
) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Msgbox::Alert(ex.FormatDisplayMessage());
|
||||
}
|
||||
|
||||
g_Conf->ComponentsTabName = L"Plugins";
|
||||
|
||||
// TODO: Send a message to the panel to select the failed plugin.
|
||||
|
||||
return AppOpenModalDialog<Dialogs::ComponentsConfigDialog>(L"Plugins") != wxID_CANCEL;
|
||||
}
|
||||
|
||||
class PluginErrorEvent : public pxExceptionEvent
|
||||
{
|
||||
typedef pxExceptionEvent _parent;
|
||||
|
||||
public:
|
||||
PluginErrorEvent( BaseException* ex=NULL ) : _parent( ex ) {}
|
||||
PluginErrorEvent( const BaseException& ex ) : _parent( ex ) {}
|
||||
|
||||
virtual ~PluginErrorEvent() = default;
|
||||
virtual PluginErrorEvent *Clone() const { return new PluginErrorEvent(*this); }
|
||||
|
||||
protected:
|
||||
void InvokeEvent();
|
||||
};
|
||||
|
||||
class PluginInitErrorEvent : public pxExceptionEvent
|
||||
{
|
||||
typedef pxExceptionEvent _parent;
|
||||
|
||||
public:
|
||||
PluginInitErrorEvent( BaseException* ex=NULL ) : _parent( ex ) {}
|
||||
PluginInitErrorEvent( const BaseException& ex ) : _parent( ex ) {}
|
||||
|
||||
virtual ~PluginInitErrorEvent() = default;
|
||||
virtual PluginInitErrorEvent *Clone() const { return new PluginInitErrorEvent(*this); }
|
||||
|
||||
protected:
|
||||
void InvokeEvent();
|
||||
|
||||
};
|
||||
|
||||
void PluginErrorEvent::InvokeEvent()
|
||||
{
|
||||
if( !m_except ) return;
|
||||
|
||||
ScopedExcept deleteMe( m_except );
|
||||
m_except = NULL;
|
||||
|
||||
if( !HandlePluginError( *deleteMe ) )
|
||||
{
|
||||
Console.Error( L"User-canceled plugin configuration; Plugins not loaded!" );
|
||||
Msgbox::Alert( _("Warning! System plugins have not been loaded. PCSX2 may be inoperable.") );
|
||||
}
|
||||
}
|
||||
|
||||
void PluginInitErrorEvent::InvokeEvent()
|
||||
{
|
||||
if( !m_except ) return;
|
||||
|
||||
ScopedExcept deleteMe( m_except );
|
||||
m_except = NULL;
|
||||
|
||||
if( !HandlePluginError( *deleteMe ) )
|
||||
{
|
||||
Console.Error( L"User-canceled plugin configuration after plugin initialization failure. Plugins unloaded." );
|
||||
Msgbox::Alert( _("Warning! System plugins have not been loaded. PCSX2 may be inoperable.") );
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a string message telling the user to consult guides for obtaining a legal BIOS.
|
||||
// This message is in a function because it's used as part of several dialogs in PCSX2 (there
|
||||
// are multiple variations on the BIOS and BIOS folder checks).
|
||||
|
@ -675,43 +595,6 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
|||
CoreThread.Resume();
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
catch( Exception::PluginOpenError& ex )
|
||||
{
|
||||
// It might be possible for there to be no GS Frame, but I don't really know. This does
|
||||
// prevent PCSX2 from locking up on a Windows wxWidgets 3.0 build. My conjecture is this:
|
||||
// 1. Messagebox appears
|
||||
// 2. Either a close or hide signal for gsframe gets sent to messagebox.
|
||||
// 3. Message box hides itself without exiting the modal event loop, therefore locking up
|
||||
// PCSX2. This probably happened in the BIOS error case above as well.
|
||||
// So the idea is to explicitly close the gsFrame before the modal MessageBox appears and
|
||||
// intercepts the close message. Only for wx3.0 though - it sometimes breaks linux wx2.8.
|
||||
|
||||
if (GSFrame* gsframe = wxGetApp().GetGsFramePtr())
|
||||
gsframe->Close();
|
||||
|
||||
Console.Error(ex.FormatDiagnosticMessage());
|
||||
|
||||
// Make sure it terminates properly for nogui users.
|
||||
if (wxGetApp().HasGUI())
|
||||
AddIdleEvent(PluginInitErrorEvent(ex));
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
catch( Exception::PluginInitError& ex )
|
||||
{
|
||||
ShutdownPlugins();
|
||||
|
||||
Console.Error( ex.FormatDiagnosticMessage() );
|
||||
AddIdleEvent( PluginInitErrorEvent(ex) );
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
catch( Exception::PluginError& ex )
|
||||
{
|
||||
UnloadPlugins();
|
||||
|
||||
Console.Error( ex.FormatDiagnosticMessage() );
|
||||
AddIdleEvent( PluginErrorEvent(ex) );
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
#if 0
|
||||
catch( Exception::ThreadDeadlock& ex )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue