Skip to content

Commit

Permalink
Merge pull request #13172 from hrydgard/generalized-multi-instance
Browse files Browse the repository at this point in the history
Generalized multi-instance
  • Loading branch information
hrydgard authored Jul 20, 2020
2 parents 253d82c + fb0b3b3 commit af2ed00
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 130 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/CwCheat.h
Core/HDRemaster.cpp
Core/HDRemaster.h
Core/Instance.cpp
Core/Instance.h
Core/ThreadEventQueue.h
Core/WebServer.cpp
Core/WebServer.h
Expand Down
24 changes: 22 additions & 2 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "Core/ConfigValues.h"
#include "Core/Loaders.h"
#include "Core/HLE/sceUtility.h"
#include "Core/Instance.h"
#include "GPU/Common/FramebufferCommon.h"

// TODO: Find a better place for this.
Expand Down Expand Up @@ -1107,8 +1108,13 @@ static void IterateSettings(IniFile &iniFile, std::function<void(IniFile::Sectio
}
}

Config::Config() : bGameSpecific(false) { }
Config::~Config() { }
Config::Config() : bGameSpecific(false) {
InitInstanceCounter();
}

Config::~Config() {
ShutdownInstanceCounter();
}

std::map<std::string, std::pair<std::string, int>> GetLangValuesMapping() {
std::map<std::string, std::pair<std::string, int>> langValuesMapping;
Expand Down Expand Up @@ -1290,9 +1296,23 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
jitForcedOff = true;
g_Config.iCpuCore = (int)CPUCore::INTERPRETER;
}

// Automatically silence secondary instances. Could be an option I guess, but meh.
if (PPSSPP_ID > 1) {
g_Config.iGlobalVolume = 0;
}

INFO_LOG(LOADER, "Config loaded: '%s'", iniFilename_.c_str());
}

void Config::Save(const char *saveReason) {
if (!IsFirstInstance()) {
// TODO: Should we allow saving config if started from a different directory?
// How do we tell?
WARN_LOG(LOADER, "Not saving config - secondary instances don't.");
return;
}

if (jitForcedOff) {
// if JIT has been forced off, we don't want to screw up the user's ppsspp.ini
g_Config.iCpuCore = (int)CPUCore::JIT;
Expand Down
2 changes: 2 additions & 0 deletions Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@
<ClCompile Include="HLE\sceUsbCam.cpp" />
<ClCompile Include="HLE\sceUsbMic.cpp" />
<ClCompile Include="HW\Camera.cpp" />
<ClCompile Include="Instance.cpp" />
<ClCompile Include="MemFault.cpp" />
<ClCompile Include="MIPS\IR\IRAsm.cpp" />
<ClCompile Include="MIPS\IR\IRCompALU.cpp" />
Expand Down Expand Up @@ -918,6 +919,7 @@
<ClInclude Include="HLE\sceUsbCam.h" />
<ClInclude Include="HLE\sceUsbMic.h" />
<ClInclude Include="HW\Camera.h" />
<ClInclude Include="Instance.h" />
<ClInclude Include="MemFault.h" />
<ClInclude Include="MIPS\IR\IRFrontend.h" />
<ClInclude Include="MIPS\IR\IRInst.h" />
Expand Down
6 changes: 6 additions & 0 deletions Core/Core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,9 @@
<ClCompile Include="MemFault.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="Instance.cpp">
<Filter>Core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELF\ElfReader.h">
Expand Down Expand Up @@ -1385,6 +1388,9 @@
<ClInclude Include="MemFault.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="Instance.h">
<Filter>Core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/proAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/Instance.h"
#include "proAdhoc.h"
#include "i18n/i18n.h"

Expand Down Expand Up @@ -68,7 +69,6 @@ bool updateChatScreen = false;
int newChat = 0;

bool isLocalServer = false;
uint8_t PPSSPP_ID = 0;
sockaddr localIP; // This might serves the same purpose with existing "localip" above, but since this is copied from my old code so here it is (too lazy to rewrite the code)

int isLocalMAC(const SceNetEtherAddr * addr) {
Expand Down
1 change: 0 additions & 1 deletion Core/HLE/proAdhoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,6 @@ extern std::map<int, AdhocctlHandler> adhocctlHandlers;

extern uint16_t portOffset;
extern bool isLocalServer;
extern uint8_t PPSSPP_ID;
extern sockaddr localIP;
extern uint32_t fakePoolSize;
extern SceNetAdhocMatchingContext * contexts;
Expand Down
123 changes: 1 addition & 122 deletions Core/HLE/sceNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "Core/HLE/sceNetAdhoc.h"
#include "Core/HLE/sceNet.h"
#include "Core/Reporting.h"
#include "Core/Instance.h"

static bool netInited;
static bool netInetInited;
Expand All @@ -56,124 +57,6 @@ static struct SceNetMallocStat netMallocStat;

static std::map<int, ApctlHandler> apctlHandlers;

#ifdef _WIN32
static HANDLE hIDMapFile = NULL;
#elif __linux__ || __APPLE__
static int hIDMapFile = 0;
#endif
static int32_t* pIDBuf = NULL;
#define ID_SHM_NAME "/PPSSPP_ID"

// Get current number of instance of PPSSPP running.
// Must be called only once during init.
static uint8_t getPPSSPPInstanceNumber() {
#ifdef _WIN32
uint32_t BUF_SIZE = 4096;
SYSTEM_INFO sysInfo;

GetSystemInfo(&sysInfo);
int gran = sysInfo.dwAllocationGranularity ? sysInfo.dwAllocationGranularity : 0x10000;
BUF_SIZE = (BUF_SIZE + gran - 1) & ~(gran - 1);

hIDMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
TEXT(ID_SHM_NAME)); // name of mapping object

DWORD lasterr = GetLastError();
if (hIDMapFile == NULL)
{
ERROR_LOG(SCENET, "Could not create %s file mapping object (%d).", ID_SHM_NAME, lasterr);
return 1;
}
pIDBuf = (int32_t*)MapViewOfFile(hIDMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
sizeof(int32_t)); //BUF_SIZE

if (pIDBuf == NULL)
{
ERROR_LOG(SCENET, "Could not map view of file %s (%d).", ID_SHM_NAME, GetLastError());
//CloseHandle(hIDMapFile);
return 1;
}

(*pIDBuf)++;
int id = *pIDBuf;
UnmapViewOfFile(pIDBuf);
//CloseHandle(hIDMapFile); //Should be called when program exits
//hIDMapFile = NULL;

return id;
#elif __ANDROID__
// TODO : replace shm_open & shm_unlink with ashmem or android-shmem
return 1;
#elif __linux__ || __APPLE__
long BUF_SIZE = 4096;
//caddr_t pIDBuf;
int status;

// Create shared memory object

hIDMapFile = shm_open(ID_SHM_NAME, O_CREAT | O_RDWR, 0);
BUF_SIZE = (BUF_SIZE < sysconf(_SC_PAGE_SIZE)) ? sysconf(_SC_PAGE_SIZE) : BUF_SIZE;

if ((ftruncate(hIDMapFile, BUF_SIZE)) == -1) { // Set the size
ERROR_LOG(SCENET, "ftruncate(%s) failure.", ID_SHM_NAME);
return 1;
}

pIDBuf = (int32_t*)mmap(0, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, hIDMapFile, 0);
if (pIDBuf == MAP_FAILED) { // Set the size
ERROR_LOG(SCENET, "mmap(%s) failure.", ID_SHM_NAME);
pIDBuf = NULL;
return 1;
}

int id = 1;
if (mlock(pIDBuf, BUF_SIZE) == 0) {
(*pIDBuf)++;
id = *pIDBuf;
munlock(pIDBuf, BUF_SIZE);
}

status = munmap(pIDBuf, BUF_SIZE); // Unmap the page
//status = close(hIDMapFile); // Close file, should be called when program exits?
//status = shm_unlink(ID_SHM_NAME); // Unlink [& delete] shared-memory object, should be called when program exits

return id;
#else
return 1;
#endif
}

static void PPSSPPIDCleanup() {
#ifdef _WIN32
if (hIDMapFile != NULL) {
CloseHandle(hIDMapFile); // If program exited(or crashed?) or the last handle reference closed the shared memory object will be deleted.
hIDMapFile = NULL;
}
#elif __ANDROID__
if (hIDMapFile != 0) {
close(hIDMapFile);
// TODO : replace shm_unlink with ashmem or android-shmem
//shm_unlink(ID_SHM_NAME); // If program exited or crashed before unlinked the shared memory object and it's contents will persist.
hIDMapFile = 0;
}
#elif __linux__ || __APPLE__
// TODO : This unlink should be called when program exits instead of everytime the game reset.
if (hIDMapFile != 0) {
close(hIDMapFile);
shm_unlink(ID_SHM_NAME); // If program exited or crashed before unlinked the shared memory object and it's contents will persist.
hIDMapFile = 0;
}
#endif
}

static int InitLocalIP() {
// find local IP
addrinfo* localAddr;
Expand Down Expand Up @@ -232,10 +115,6 @@ static void __ResetInitNetLib() {

void __NetInit() {
portOffset = g_Config.iPortOffset;
if (PPSSPP_ID == 0) // For persistent ID/IP, New instances may have a possibility to have the same ID/IP if PPSSPPIDCleanup() being called on every reset
{
PPSSPP_ID = getPPSSPPInstanceNumber(); // This should be called when program started instead of when the game started/reseted
}

net::Init();
InitLocalIP();
Expand Down
Loading

0 comments on commit af2ed00

Please sign in to comment.