mtgs: switching to a plugin-less architecture

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2021-05-11 16:57:37 +02:00 committed by Kojin
parent f04f941dbb
commit 160117ffbb
4 changed files with 26 additions and 159 deletions

View File

@ -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();

View File

@ -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."));
}
}

View File

@ -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>

View File

@ -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 )
{