PINE: Update to the age of Qt

This commit is contained in:
isJuhn 2023-01-24 20:28:03 +01:00 committed by refractionpcsx2
parent 1964bbc03a
commit e3962aa794
10 changed files with 234 additions and 168 deletions

View File

@ -67,6 +67,9 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pineEnable, "EmuCore", "EnablePINE", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.pineSlot, "EmuCore", "PINESlot", 28011);
dialog->registerWidgetHelp(m_ui.eeRoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.eeClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr(""));

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>809</width>
<height>647</height>
<height>725</height>
</rect>
</property>
<property name="windowTitle">
@ -37,7 +37,7 @@
<x>0</x>
<y>0</y>
<width>807</width>
<height>645</height>
<height>723</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -417,6 +417,45 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>PINE Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="1" column="1">
<widget class="QLineEdit" name="pineSlot">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Slot:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="pineEnable">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">

View File

@ -31,6 +31,7 @@
#include "PerformanceMetrics.h"
#include "Sio.h"
#include "VMManager.h"
#include "PINE.h"
#include "common/Assertions.h"
#include "common/CrashHandler.h"
@ -77,6 +78,8 @@ static std::string s_session_serial;
static bool s_screensaver_inhibited = false;
static PINEServer s_pine_server;
#ifdef ENABLE_DISCORD_PRESENCE
static bool s_discord_presence_active = false;
#endif
@ -272,6 +275,8 @@ void CommonHost::CPUThreadInitialize()
if (EmuConfig.EnableDiscordPresence)
InitializeDiscordPresence();
#endif
ReloadPINE();
}
void CommonHost::CPUThreadShutdown()
@ -284,6 +289,8 @@ void CommonHost::CPUThreadShutdown()
Achievements::Shutdown();
#endif
s_pine_server.Deinitialize();
InputManager::CloseSources();
VMManager::WaitForSaveStateFlush();
VMManager::Internal::ReleaseMemory();
@ -379,6 +386,8 @@ void CommonHost::OnGameChanged(const std::string& disc_path, const std::string&
#ifdef ENABLE_DISCORD_PRESENCE
UpdateDiscordPresence(GetRichPresenceString());
#endif
ReloadPINE();
}
void CommonHost::CPUThreadVSync()
@ -539,4 +548,20 @@ std::string CommonHost::GetRichPresenceString()
return rich_presence_string;
}
#endif
#endif
void CommonHost::ReloadPINE()
{
if (EmuConfig.EnablePINE && (s_pine_server.m_slot != EmuConfig.PINESlot || s_pine_server.m_end))
{
if (!s_pine_server.m_end)
{
s_pine_server.Deinitialize();
}
s_pine_server.Initialize(EmuConfig.PINESlot);
}
else if ((!EmuConfig.EnablePINE && !s_pine_server.m_end))
{
s_pine_server.Deinitialize();
}
}

View File

@ -85,6 +85,9 @@ namespace CommonHost
void UpdateDiscordPresence(const std::string& rich_presence);
#endif
/// Reloads PINE IPC Server if needed. Does nothing if it's already running on the correct port.
void ReloadPINE();
namespace Internal
{
/// Resets any state for hotkey-related VMs, called on VM startup.

View File

@ -1293,6 +1293,8 @@ struct Pcsx2Config
McdOptions Mcd[8];
std::string GzipIsoIndexTemplate; // for quick-access index with gzipped ISO
int PINESlot;
// Set at runtime, not loaded from config.
std::string CurrentBlockdump;
std::string CurrentIRX;

View File

@ -27,6 +27,7 @@ u32 ElfEntry;
std::pair<u32,u32> ElfTextRange;
std::string LastELF;
bool isPSXElf;
std::string ElfVersion;
// All of ElfObjects functions.
ElfObject::ElfObject(std::string srcfile, IsoFile& isofile, bool isPSXElf)
@ -365,6 +366,7 @@ int GetPS2ElfName( std::string& name )
{
Console.WriteLn( Color_Blue, "(SYSTEM.CNF) Software version = %.*s",
static_cast<int>(value.size()), value.data());
ElfVersion = value;
}
}

View File

@ -163,3 +163,4 @@ extern u32 ElfEntry;
extern std::pair<u32,u32> ElfTextRange;
extern std::string LastELF;
extern bool isPSXElf;
extern std::string ElfVersion;

View File

@ -15,15 +15,12 @@
#include "PrecompiledHeader.h"
#ifdef PCSX2_LEFTOVER_FROM_WX
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include <sys/types.h>
#if _WIN32
#define read_portable(a, b, c) (recv(a, b, c, 0))
#define write_portable(a, b, c) (send(a, b, c, 0))
#define read_portable(a, b, c) (recv(a, (char*)b, c, 0))
#define write_portable(a, b, c) (send(a, (const char*)b, c, 0))
#define close_portable(a) (closesocket(a))
#define bzero(b, len) (memset((b), '\0', (len)), (void)0)
#include <WinSock2.h>
@ -34,35 +31,44 @@
#define close_portable(a) (close(a))
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#endif
#include "Common.h"
#include "Memory.h"
#include "gui/AppSaveStates.h"
#include "gui/AppCoreThread.h"
#include "gui/SysThreads.h"
#include "Elfheader.h"
#include "pcsx2/VMManager.h"
#include "svnrev.h"
#include "PINE.h"
PINEServer::PINEServer(SysCoreThread* vm, unsigned int slot)
: pxThread("PINE_Server")
PINEServer::PINEServer() {}
PINEServer::~PINEServer()
{
Deinitialize();
}
bool PINEServer::Initialize(int slot)
{
m_end.store(false, std::memory_order_release);
m_slot = slot;
#ifdef _WIN32
WSADATA wsa;
struct sockaddr_in server;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
Console.WriteLn(Color_Red, "PINE: Cannot initialize winsock! Shutting down...");
return;
Deinitialize();
return false;
}
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if ((m_sock == INVALID_SOCKET) || slot > 65536)
{
Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down...");
return;
Deinitialize();
return false;
}
// yes very good windows s/sun/sin/g sure is fine
@ -74,7 +80,8 @@ PINEServer::PINEServer(SysCoreThread* vm, unsigned int slot)
if (bind(m_sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down...");
return;
Deinitialize();
return false;
}
#else
@ -103,7 +110,8 @@ PINEServer::PINEServer(SysCoreThread* vm, unsigned int slot)
if (m_sock < 0)
{
Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down...");
return;
Deinitialize();
return false;
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path, m_socket_name.c_str());
@ -114,32 +122,42 @@ PINEServer::PINEServer(SysCoreThread* vm, unsigned int slot)
if (bind(m_sock, (struct sockaddr*)&server, sizeof(struct sockaddr_un)))
{
Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down...");
return;
Deinitialize();
return false;
}
#endif
// maximum queue of 4096 commands before refusing, approximated to the
// nearest legal value. We do not use SOMAXCONN as windows have this idea
// that a "reasonable" value is 5, which is not.
listen(m_sock, 4096);
if (listen(m_sock, 4096))
{
Console.WriteLn(Color_Red, "PINE: Cannot listen for connections! Shutting down...");
Deinitialize();
return false;
}
// we save a handle of the main vm object
m_vm = vm;
// we allocate once buffers to not have to do mallocs for each IPC
// request, as malloc is expansive when we optimize for µs.
m_ret_buffer.resize(MAX_IPC_RETURN_SIZE);
m_ipc_buffer.resize(MAX_IPC_SIZE);
// we start the thread
Start();
m_thread = std::thread(&PINEServer::MainLoop, this);
return true;
}
char* PINEServer::MakeOkIPC(char* ret_buffer, uint32_t size = 5)
std::vector<u8>& PINEServer::MakeOkIPC(std::vector<u8>& ret_buffer, uint32_t size = 5)
{
ToArray<uint32_t>(ret_buffer, size, 0);
ToResultVector<uint32_t>(ret_buffer, size, 0);
ret_buffer[4] = IPC_OK;
return ret_buffer;
}
char* PINEServer::MakeFailIPC(char* ret_buffer, uint32_t size = 5)
std::vector<u8>& PINEServer::MakeFailIPC(std::vector<u8>& ret_buffer, uint32_t size = 5)
{
ToArray<uint32_t>(ret_buffer, size, 0);
ToResultVector<uint32_t>(ret_buffer, size, 0);
ret_buffer[4] = IPC_FAIL;
return ret_buffer;
}
@ -170,30 +188,24 @@ int PINEServer::StartSocket()
return 0;
}
void PINEServer::ExecuteTaskInThread()
void PINEServer::MainLoop()
{
m_end = false;
// we allocate once buffers to not have to do mallocs for each IPC
// request, as malloc is expansive when we optimize for µs.
m_ret_buffer = new char[MAX_IPC_RETURN_SIZE];
m_ipc_buffer = new char[MAX_IPC_SIZE];
if (StartSocket() < 0)
return;
while (true)
while (!m_end.load(std::memory_order_acquire))
{
// either int or ssize_t depending on the platform, so we have to
// use a bunch of auto
auto receive_length = 0;
auto end_length = 4;
const gsl::span<u8> ipc_buffer_span = gsl::make_span(m_ipc_buffer);
// while we haven't received the entire packet, maybe due to
// socket datagram splittage, we continue to read
while (receive_length < end_length)
{
auto tmp_length = read_portable(m_msgsock, &m_ipc_buffer[receive_length], MAX_IPC_SIZE - receive_length);
const auto tmp_length = read_portable(m_msgsock, &ipc_buffer_span[receive_length], MAX_IPC_SIZE - receive_length);
// we recreate the socket if an error happens
if (tmp_length <= 0)
@ -209,7 +221,7 @@ void PINEServer::ExecuteTaskInThread()
// if we got at least the final size then update
if (end_length == 4 && receive_length >= 4)
{
end_length = FromArray<u32>(m_ipc_buffer, 0);
end_length = FromSpan<u32>(ipc_buffer_span, 0);
// we'd like to avoid a client trying to do OOB
if (end_length > MAX_IPC_SIZE || end_length < 4)
{
@ -227,10 +239,10 @@ void PINEServer::ExecuteTaskInThread()
// disconnects
if (receive_length != 0)
{
res = ParseCommand(&m_ipc_buffer[4], m_ret_buffer, (u32)end_length - 4);
res = ParseCommand(ipc_buffer_span.subspan(4), m_ret_buffer, (u32)end_length - 4);
// if we cannot send back our answer restart the socket
if (write_portable(m_msgsock, res.buffer, res.size) < 0)
if (write_portable(m_msgsock, res.buffer.data(), res.size) < 0)
{
if (StartSocket() < 0)
return;
@ -240,9 +252,10 @@ void PINEServer::ExecuteTaskInThread()
return;
}
PINEServer::~PINEServer()
void PINEServer::Deinitialize()
{
m_end = true;
m_end.store(true, std::memory_order_release);
#ifdef _WIN32
WSACleanup();
#else
@ -250,17 +263,14 @@ PINEServer::~PINEServer()
#endif
close_portable(m_sock);
close_portable(m_msgsock);
delete[] m_ret_buffer;
delete[] m_ipc_buffer;
// destroy the thread
try
if (m_thread.joinable())
{
pxThread::Cancel();
m_thread.join();
}
DESTRUCTOR_CATCHALL
}
PINEServer::IPCBuffer PINEServer::ParseCommand(char* buf, char* ret_buffer, u32 buf_size)
PINEServer::IPCBuffer PINEServer::ParseCommand(gsl::span<u8> buf, std::vector<u8>& ret_buffer, u32 buf_size)
{
u32 ret_cnt = 5;
u32 buf_cnt = 0;
@ -285,211 +295,197 @@ PINEServer::IPCBuffer PINEServer::ParseCommand(char* buf, char* ret_buffer, u32
{
case MsgRead8:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 4, ret_cnt, 1, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
const u32 a = FromSpan<u32>(buf, buf_cnt);
const u8 res = memRead8(a);
ToArray(ret_buffer, res, ret_cnt);
ToResultVector(ret_buffer, res, ret_cnt);
ret_cnt += 1;
buf_cnt += 4;
break;
}
case MsgRead16:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 4, ret_cnt, 2, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
const u32 a = FromSpan<u32>(buf, buf_cnt);
const u16 res = memRead16(a);
ToArray(ret_buffer, res, ret_cnt);
ToResultVector(ret_buffer, res, ret_cnt);
ret_cnt += 2;
buf_cnt += 4;
break;
}
case MsgRead32:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 4, ret_cnt, 4, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
const u32 a = FromSpan<u32>(buf, buf_cnt);
const u32 res = memRead32(a);
ToArray(ret_buffer, res, ret_cnt);
ToResultVector(ret_buffer, res, ret_cnt);
ret_cnt += 4;
buf_cnt += 4;
break;
}
case MsgRead64:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 4, ret_cnt, 8, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
const u32 a = FromSpan<u32>(buf, buf_cnt);
const u64 res = memRead64(a);
ToArray(ret_buffer, res, ret_cnt);
ToResultVector(ret_buffer, res, ret_cnt);
ret_cnt += 8;
buf_cnt += 4;
break;
}
case MsgWrite8:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 1 + 4, ret_cnt, 0, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
memWrite8(a, FromArray<u8>(&buf[buf_cnt], 4));
const u32 a = FromSpan<u32>(buf, buf_cnt);
memWrite8(a, FromSpan<u8>(buf, buf_cnt + 4));
buf_cnt += 5;
break;
}
case MsgWrite16:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 2 + 4, ret_cnt, 0, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
memWrite16(a, FromArray<u16>(&buf[buf_cnt], 4));
const u32 a = FromSpan<u32>(buf, buf_cnt);
memWrite16(a, FromSpan<u16>(buf, buf_cnt + 4));
buf_cnt += 6;
break;
}
case MsgWrite32:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 4 + 4, ret_cnt, 0, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
memWrite32(a, FromArray<u32>(&buf[buf_cnt], 4));
const u32 a = FromSpan<u32>(buf, buf_cnt);
memWrite32(a, FromSpan<u32>(buf, buf_cnt + 4));
buf_cnt += 8;
break;
}
case MsgWrite64:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 8 + 4, ret_cnt, 0, buf_size))
goto error;
const u32 a = FromArray<u32>(&buf[buf_cnt], 0);
memWrite64(a, FromArray<u64>(&buf[buf_cnt], 4));
const u32 a = FromSpan<u32>(buf, buf_cnt);
memWrite64(a, FromSpan<u64>(buf, buf_cnt + 4));
buf_cnt += 12;
break;
}
case MsgVersion:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
char version[256] = {};
std::string version;
if (GIT_TAGGED_COMMIT) // Nightly builds
{
// tagged commit - more modern implementation of dev build versioning
// - there is no need to include the commit - that is associated with the tag, git is implied
sprintf(version, "PCSX2 Nightly - %s", GIT_TAG);
version = fmt::format("PCSX2 Nightly - {}", GIT_TAG);
}
else
{
sprintf(version, "PCSX2 %u.%u.%u-%lld", PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo, SVN_REV);
version = fmt::format("PCSX2 {}.{}.{}-{}", PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo, SVN_REV);
}
const u32 size = strlen(version) + 1;
version[size] = 0x00;
const u32 size = version.size() + 1;
if (!SafetyChecks(buf_cnt, 0, ret_cnt, size + 4, buf_size))
goto error;
ToArray(ret_buffer, size, ret_cnt);
ToResultVector(ret_buffer, size, ret_cnt);
ret_cnt += 4;
memcpy(&ret_buffer[ret_cnt], version, size);
memcpy(&ret_buffer[ret_cnt], version.c_str(), size);
ret_cnt += size;
break;
}
case MsgSaveState:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 1, ret_cnt, 0, buf_size))
goto error;
StateCopy_SaveToSlot(FromArray<u8>(&buf[buf_cnt], 0));
VMManager::SaveStateToSlot(FromSpan<u8>(buf, buf_cnt));
buf_cnt += 1;
break;
}
case MsgLoadState:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
if (!SafetyChecks(buf_cnt, 1, ret_cnt, 0, buf_size))
goto error;
StateCopy_LoadFromSlot(FromArray<u8>(&buf[buf_cnt], 0), false);
VMManager::LoadStateFromSlot(FromSpan<u8>(buf, buf_cnt));
buf_cnt += 1;
break;
}
case MsgTitle:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
char* title = new char[GameInfo::gameName.size() + 1];
sprintf(title, "%s", GameInfo::gameName.ToUTF8().data());
const u32 size = strlen(title) + 1;
title[size] = 0x00;
const std::string gameName = VMManager::GetGameName();
const u32 size = gameName.size() + 1;
if (!SafetyChecks(buf_cnt, 0, ret_cnt, size + 4, buf_size))
goto error;
ToArray(ret_buffer, size, ret_cnt);
ToResultVector(ret_buffer, size, ret_cnt);
ret_cnt += 4;
memcpy(&ret_buffer[ret_cnt], title, size);
memcpy(&ret_buffer[ret_cnt], gameName.c_str(), size);
ret_cnt += size;
delete[] title;
break;
}
case MsgID:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
char* title = new char[GameInfo::gameSerial.size() + 1];
sprintf(title, "%s", GameInfo::gameSerial.ToUTF8().data());
const u32 size = strlen(title) + 1;
title[size] = 0x00;
const std::string gameSerial = VMManager::GetGameSerial();
const u32 size = gameSerial.size() + 1;
if (!SafetyChecks(buf_cnt, 0, ret_cnt, size + 4, buf_size))
goto error;
ToArray(ret_buffer, size, ret_cnt);
ToResultVector(ret_buffer, size, ret_cnt);
ret_cnt += 4;
memcpy(&ret_buffer[ret_cnt], title, size);
memcpy(&ret_buffer[ret_cnt], gameSerial.c_str(), size);
ret_cnt += size;
delete[] title;
break;
}
case MsgUUID:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
char* title = new char[GameInfo::gameCRC.size() + 1];
sprintf(title, "%s", GameInfo::gameCRC.ToUTF8().data());
const u32 size = strlen(title) + 1;
title[size] = 0x00;
const std::string crc(fmt::format("{:08x}", VMManager::GetGameCRC()));
const u32 size = crc.size() + 1;
if (!SafetyChecks(buf_cnt, 0, ret_cnt, size + 4, buf_size))
goto error;
ToArray(ret_buffer, size, ret_cnt);
ToResultVector(ret_buffer, size, ret_cnt);
ret_cnt += 4;
memcpy(&ret_buffer[ret_cnt], title, size);
memcpy(&ret_buffer[ret_cnt], crc.c_str(), size);
ret_cnt += size;
delete[] title;
break;
}
case MsgGameVersion:
{
if (!m_vm->HasActiveMachine())
if (!VMManager::HasValidVM())
goto error;
char* title = new char[GameInfo::gameVersion.size() + 1];
sprintf(title, "%s", GameInfo::gameVersion.ToUTF8().data());
const u32 size = strlen(title) + 1;
title[size] = 0x00;
const u32 size = ElfVersion.size() + 1;
if (!SafetyChecks(buf_cnt, 0, ret_cnt, size + 4, buf_size))
goto error;
ToArray(ret_buffer, size, ret_cnt);
ToResultVector(ret_buffer, size, ret_cnt);
ret_cnt += 4;
memcpy(&ret_buffer[ret_cnt], title, size);
memcpy(&ret_buffer[ret_cnt], ElfVersion.c_str(), size);
ret_cnt += size;
delete[] title;
break;
}
case MsgStatus:
@ -497,18 +493,20 @@ PINEServer::IPCBuffer PINEServer::ParseCommand(char* buf, char* ret_buffer, u32
if (!SafetyChecks(buf_cnt, 0, ret_cnt, 4, buf_size))
goto error;
EmuStatus status;
if (m_vm->HasActiveMachine())
{
if (GetCoreThread().IsClosing())
status = Paused;
else
status = Running;
switch (VMManager::GetState()) {
case VMState::Running:
status = EmuStatus::Running;
break;
case VMState::Paused:
status = EmuStatus::Paused;
break;
default:
status = EmuStatus::Shutdown;
break;
}
else
{
status = Shutdown;
}
ToArray(ret_buffer, status, ret_cnt);
ToResultVector(ret_buffer, status, ret_cnt);
ret_cnt += 4;
break;
}
@ -521,5 +519,3 @@ PINEServer::IPCBuffer PINEServer::ParseCommand(char* buf, char* ret_buffer, u32
}
return IPCBuffer{(int)ret_cnt, MakeOkIPC(ret_buffer, ret_cnt)};
}
#endif

View File

@ -18,8 +18,6 @@
#pragma once
#ifdef PCSX2_LEFTOVER_FROM_WX
// PINE uses a concept of "slot" to be able to communicate with multiple
// emulators at the same time, each slot should be unique to each emulator to
// allow PnP and configurable by the end user so that several runs don't
@ -27,22 +25,20 @@
#define PINE_DEFAULT_SLOT 28011
#define PINE_EMULATOR_NAME "pcsx2"
#include "gui/PersistentThread.h"
#include "gui/SysThreads.h"
#include <thread>
#include <string>
#include <vector>
#include <atomic>
#include <gsl/span>
#ifdef _WIN32
#include <WinSock2.h>
#include <windows.h>
#endif
using namespace Threading;
class SysCoreThread;
class PINEServer : public pxThread
class PINEServer
{
// parent thread
typedef pxThread _parent;
std::thread m_thread;
protected:
#ifdef _WIN32
@ -77,13 +73,13 @@ protected:
* A preallocated buffer used to store all IPC replies.
* to the size of 50.000 MsgWrite64 IPC calls.
*/
char* m_ret_buffer;
std::vector<u8> m_ret_buffer{};
/**
* IPC messages buffer.
* A preallocated buffer used to store all IPC messages.
*/
char* m_ipc_buffer;
std::vector<u8> m_ipc_buffer{};
/**
* IPC Command messages opcodes.
@ -130,7 +126,7 @@ protected:
struct IPCBuffer
{
int size; /**< Size of the buffer. */
char* buffer; /**< Buffer. */
std::vector<u8> buffer; /**< Buffer. */
};
/**
@ -145,11 +141,8 @@ protected:
IPC_FAIL = 0xFF /**< IPC command failed to complete. */
};
// handle to the main vm thread
SysCoreThread* m_vm;
// Thread used to relay IPC commands.
void ExecuteTaskInThread();
void MainLoop();
/**
* Internal function, Parses an IPC command.
@ -159,7 +152,7 @@ protected:
* return value: IPCBuffer containing a buffer with the result
* of the command and its size.
*/
IPCBuffer ParseCommand(char* buf, char* ret_buffer, u32 buf_size);
IPCBuffer ParseCommand(gsl::span<u8> buf, std::vector<u8>& ret_buffer, u32 buf_size);
/**
* Formats an IPC buffer
@ -167,8 +160,8 @@ protected:
* size: size of the IPC buffer.
* return value: buffer containing the status code allocated of size
*/
static inline char* MakeOkIPC(char* ret_buffer, uint32_t size);
static inline char* MakeFailIPC(char* ret_buffer, uint32_t size);
static inline std::vector<u8>& MakeOkIPC(std::vector<u8>& ret_buffer, uint32_t size);
static inline std::vector<u8>& MakeFailIPC(std::vector<u8>& ret_buffer, uint32_t size);
/**
* Initializes an open socket for IPC communication.
@ -177,31 +170,29 @@ protected:
int StartSocket();
/**
* Converts an uint to an char* in little endian
* res_array: the array to modify
* Converts a primitive value to bytes in little endian
* res_vector: the vector to modify
* res: the value to convert
* i: when to insert it into the array
* return value: res_array
* i: where to insert it into the vector
* NB: implicitely inlined
*/
template <typename T>
static char* ToArray(char* res_array, T res, int i)
static void ToResultVector(std::vector<u8>& res_vector, T res, int i)
{
memcpy((res_array + i), (char*)&res, sizeof(T));
return res_array;
memcpy(&res_vector[i], (char*)&res, sizeof(T));
}
/**
* Converts a char* to an uint in little endian
* arr: the array to convert
* i: when to load it from the array
* Converts bytes in little endian to a primitive value
* span: the span to convert
* i: where to load it from the span
* return value: the converted value
* NB: implicitely inlined
*/
template <typename T>
static T FromArray(char* arr, int i)
static T FromSpan(gsl::span<u8> span, int i)
{
return *(T*)(arr + i);
return *(T*)(&span[i]);
}
/**
@ -210,7 +201,7 @@ protected:
*/
static inline bool SafetyChecks(u32 command_len, int command_size, u32 reply_len, int reply_size = 0, u32 buf_size = MAX_IPC_SIZE - 1)
{
bool res = ((command_len + command_size) > buf_size ||
const bool res = ((command_len + command_size) > buf_size ||
(reply_len + reply_size) >= MAX_IPC_RETURN_SIZE);
if (unlikely(res))
return false;
@ -219,12 +210,13 @@ protected:
public:
// Whether the socket processing thread should stop executing/is stopped.
bool m_end = true;
std::atomic_bool m_end{ false };
int m_slot;
/* Initializers */
PINEServer(SysCoreThread* vm, unsigned int slot = PINE_DEFAULT_SLOT);
PINEServer();
virtual ~PINEServer();
bool Initialize(int slot = PINE_DEFAULT_SLOT);
void Deinitialize();
}; // class SocketIPC
#endif

View File

@ -1318,6 +1318,7 @@ Pcsx2Config::Pcsx2Config()
}
GzipIsoIndexTemplate = "$(f).pindex.tmp";
PINESlot = 28011;
}
void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
@ -1371,6 +1372,7 @@ void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
#endif
SettingsWrapEntry(GzipIsoIndexTemplate);
SettingsWrapEntry(PINESlot);
// For now, this in the derived config for backwards ini compatibility.
SettingsWrapEntryEx(CurrentBlockdump, "BlockDumpSaveDirectory");
@ -1446,7 +1448,8 @@ bool Pcsx2Config::operator==(const Pcsx2Config& right) const
OpEqu(Framerate) &&
OpEqu(Trace) &&
OpEqu(BaseFilenames) &&
OpEqu(GzipIsoIndexTemplate);
OpEqu(GzipIsoIndexTemplate) &&
OpEqu(PINESlot);
for (u32 i = 0; i < sizeof(Mcd) / sizeof(Mcd[0]); i++)
{
equal &= OpEqu(Mcd[i].Enabled);