mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #13302 from unknownbrackets/net-local
Net: Simplify local IP lookup and cleanup instance counter a bit
This commit is contained in:
commit
0752e7d158
15 changed files with 184 additions and 135 deletions
|
@ -1117,12 +1117,13 @@ static void IterateSettings(IniFile &iniFile, std::function<void(Section *sectio
|
|||
}
|
||||
}
|
||||
|
||||
Config::Config() : bGameSpecific(false) {
|
||||
InitInstanceCounter();
|
||||
Config::Config() {
|
||||
}
|
||||
|
||||
Config::~Config() {
|
||||
ShutdownInstanceCounter();
|
||||
if (bUpdatedInstanceCounter) {
|
||||
ShutdownInstanceCounter();
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::pair<std::string, int>> GetLangValuesMapping() {
|
||||
|
@ -1173,6 +1174,11 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0;
|
||||
iniFilename_ = FindConfigFile(useIniFilename ? iniFileName : "ppsspp.ini");
|
||||
|
||||
if (!bUpdatedInstanceCounter) {
|
||||
InitInstanceCounter();
|
||||
bUpdatedInstanceCounter = true;
|
||||
}
|
||||
|
||||
const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0;
|
||||
controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : "controls.ini");
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ public:
|
|||
// Whether to save the config on close.
|
||||
bool bSaveSettings;
|
||||
bool bFirstRun;
|
||||
bool bGameSpecific;
|
||||
bool bGameSpecific = false;
|
||||
bool bUpdatedInstanceCounter = false;
|
||||
|
||||
int iRunCount; // To be used to for example check for updates every 10 runs and things like that.
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ bool updateChatScreen = false;
|
|||
int newChat = 0;
|
||||
bool isOriPort = false;
|
||||
bool isLocalServer = false;
|
||||
sockaddr LocalhostIP;
|
||||
SockAddrIN4 g_localhostIP;
|
||||
sockaddr LocalIP;
|
||||
int defaultWlanChannel = PSP_SYSTEMPARAM_ADHOC_CHANNEL_1; // Don't put 0(Auto) here, it needed to be a valid/actual channel number
|
||||
|
||||
|
@ -1538,7 +1538,7 @@ int getLocalIp(sockaddr_in* SocketAddress) {
|
|||
socklen_t addrLen = sizeof(localAddr);
|
||||
if (SOCKET_ERROR != getsockname(metasocket, (struct sockaddr*) & localAddr, &addrLen)) {
|
||||
if (isLocalServer) {
|
||||
localAddr.sin_addr = ((sockaddr_in*)&LocalhostIP)->sin_addr;
|
||||
localAddr.sin_addr = g_localhostIP.in.sin_addr;
|
||||
}
|
||||
SocketAddress->sin_addr = localAddr.sin_addr;
|
||||
return 0;
|
||||
|
@ -1559,7 +1559,7 @@ int getLocalIp(sockaddr_in* SocketAddress) {
|
|||
if (pHost) {
|
||||
memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length);
|
||||
if (isLocalServer) {
|
||||
SocketAddress->sin_addr = ((sockaddr_in*)&LocalhostIP)->sin_addr;
|
||||
SocketAddress->sin_addr = g_localhostIP.in.sin_addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1583,7 +1583,7 @@ int getLocalIp(sockaddr_in* SocketAddress) {
|
|||
}
|
||||
freeifaddrs(ifAddrStruct);
|
||||
if (isLocalServer) {
|
||||
SocketAddress->sin_addr = ((sockaddr_in*)&LocalhostIP)->sin_addr;
|
||||
SocketAddress->sin_addr = g_localhostIP.in.sin_addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1609,7 +1609,7 @@ int getLocalIp(sockaddr_in* SocketAddress) {
|
|||
SocketAddress->sin_addr = name.sin_addr; // May be we should cache this so it doesn't need to use connect all the time, or even better cache it when connecting to adhoc server to get an accurate IP
|
||||
closesocket(sock);
|
||||
if (isLocalServer) {
|
||||
SocketAddress->sin_addr = ((sockaddr_in*)&LocalhostIP)->sin_addr;
|
||||
SocketAddress->sin_addr = g_localhostIP.in.sin_addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1626,7 +1626,7 @@ uint32_t getLocalIp(int sock) {
|
|||
socklen_t addrLen = sizeof(localAddr);
|
||||
getsockname(sock, (struct sockaddr*)&localAddr, &addrLen);
|
||||
if (isLocalServer) {
|
||||
localAddr.sin_addr = ((sockaddr_in*)&LocalhostIP)->sin_addr;
|
||||
localAddr.sin_addr = g_localhostIP.in.sin_addr;
|
||||
}
|
||||
return localAddr.sin_addr.s_addr;
|
||||
}
|
||||
|
@ -1846,12 +1846,12 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
|||
setsockopt(metasocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
|
||||
setsockopt(metasocket, SOL_SOCKET, SO_DONTROUTE, (const char*)&on, sizeof(on));
|
||||
|
||||
((struct sockaddr_in*) & LocalhostIP)->sin_port = 0;
|
||||
g_localhostIP.in.sin_port = 0;
|
||||
// Bind Local Address to Socket
|
||||
iResult = bind(metasocket, (struct sockaddr*) & LocalhostIP, sizeof(sockaddr));
|
||||
iResult = bind(metasocket, &g_localhostIP.addr, sizeof(sockaddr));
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", inet_ntoa(((struct sockaddr_in*) & LocalhostIP)->sin_addr), iResult);
|
||||
host->NotifyUserMessage(std::string(n->T("Failed to Bind Localhost IP")) + " " + inet_ntoa(((struct sockaddr_in*) & LocalhostIP)->sin_addr), 2.0, 0x0000ff);
|
||||
ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", inet_ntoa(g_localhostIP.in.sin_addr), iResult);
|
||||
host->NotifyUserMessage(std::string(n->T("Failed to Bind Localhost IP")) + " " + inet_ntoa(g_localhostIP.in.sin_addr), 2.0, 0x0000ff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1920,7 +1920,7 @@ bool resolveIP(uint32_t ip, SceNetEtherAddr * mac) {
|
|||
getLocalIp(&addr);
|
||||
uint32_t localIp = addr.sin_addr.s_addr;
|
||||
|
||||
if (ip == localIp || ip == ((sockaddr_in*)&LocalhostIP)->sin_addr.s_addr){
|
||||
if (ip == localIp || ip == g_localhostIP.in.sin_addr.s_addr) {
|
||||
getLocalMac(mac);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -828,11 +828,16 @@ extern std::recursive_mutex peerlock;
|
|||
extern SceNetAdhocPdpStat * pdp[255];
|
||||
extern SceNetAdhocPtpStat * ptp[255];
|
||||
|
||||
union SockAddrIN4 {
|
||||
sockaddr addr;
|
||||
sockaddr_in in;
|
||||
};
|
||||
|
||||
extern uint16_t portOffset;
|
||||
extern uint32_t minSocketTimeoutUS;
|
||||
extern bool isOriPort;
|
||||
extern bool isLocalServer;
|
||||
extern sockaddr LocalhostIP; // Used to differentiate localhost IP on multiple-instance
|
||||
extern SockAddrIN4 g_localhostIP; // Used to differentiate localhost IP on multiple-instance
|
||||
extern sockaddr LocalIP; // IP of Network Adapter used to connect to Adhoc Server (LAN/WAN)
|
||||
extern int defaultWlanChannel; // Default WLAN Channel for Auto, JPCSP uses 11
|
||||
|
||||
|
|
|
@ -1828,7 +1828,7 @@ int create_listen_socket(uint16_t port)
|
|||
//Should only bind to specific IP for the 2nd or more instance of PPSSPP to prevent communication interference issue when sharing the same port. Doesn't work well when PPSSPP_ID reseted everytime emulation restarted.
|
||||
/*
|
||||
if (PPSSPP_ID > 1) {
|
||||
local.sin_addr = ((sockaddr_in *)&LocalhostIP)->sin_addr;
|
||||
local.sin_addr = g_localhostIP.in.sin_addr;
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
|
@ -114,49 +114,27 @@ void AfterApctlMipsCall::SetData(int HandlerID, int OldState, int NewState, int
|
|||
}
|
||||
|
||||
static int InitLocalhostIP() {
|
||||
// find local IP
|
||||
addrinfo* localAddr;
|
||||
addrinfo* ptr;
|
||||
char ipstr[256];
|
||||
sprintf(ipstr, "127.0.0.%u", PPSSPP_ID);
|
||||
int iResult = getaddrinfo(ipstr, 0, NULL, &localAddr);
|
||||
if (iResult != 0) {
|
||||
ERROR_LOG(SCENET, "DNS Error (%s) result: %d\n", ipstr, iResult);
|
||||
//osm.Show("DNS Error, can't resolve client bind " + ipstr, 8.0f);
|
||||
((sockaddr_in*)&LocalhostIP)->sin_family = AF_INET;
|
||||
((sockaddr_in*)&LocalhostIP)->sin_addr.s_addr = inet_addr(ipstr); //"127.0.0.1"
|
||||
((sockaddr_in*)&LocalhostIP)->sin_port = 0;
|
||||
return iResult;
|
||||
}
|
||||
for (ptr = localAddr; ptr != NULL; ptr = ptr->ai_next) {
|
||||
switch (ptr->ai_family) {
|
||||
case AF_INET:
|
||||
memcpy(&LocalhostIP, ptr->ai_addr, sizeof(sockaddr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
((sockaddr_in*)&LocalhostIP)->sin_port = 0;
|
||||
freeaddrinfo(localAddr);
|
||||
// The entire 127.*.*.* is reserved for loopback.
|
||||
uint32_t localIP = 0x7F000001 + PPSSPP_ID - 1;
|
||||
|
||||
// Resolve server dns
|
||||
addrinfo* resultAddr;
|
||||
in_addr serverIp;
|
||||
serverIp.s_addr = INADDR_NONE;
|
||||
g_localhostIP.in.sin_family = AF_INET;
|
||||
g_localhostIP.in.sin_addr.s_addr = htonl(localIP);
|
||||
g_localhostIP.in.sin_port = 0;
|
||||
|
||||
iResult = getaddrinfo(g_Config.proAdhocServer.c_str(), 0, NULL, &resultAddr);
|
||||
if (iResult != 0) {
|
||||
ERROR_LOG(SCENET, "DNS Error (%s)\n", g_Config.proAdhocServer.c_str());
|
||||
return iResult;
|
||||
}
|
||||
for (ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next) {
|
||||
switch (ptr->ai_family) {
|
||||
case AF_INET:
|
||||
serverIp = ((sockaddr_in*)ptr->ai_addr)->sin_addr;
|
||||
break;
|
||||
// If lookup fails, we'll assume it's not local.
|
||||
isLocalServer = false;
|
||||
|
||||
addrinfo *resultAddr = nullptr;
|
||||
std::string error;
|
||||
if (net::DNSResolve(g_Config.proAdhocServer, "", &resultAddr, error, net::DNSType::IPV4)) {
|
||||
for (addrinfo *ptr = resultAddr; ptr != nullptr; ptr = ptr->ai_next) {
|
||||
auto addr4 = ((sockaddr_in *)ptr->ai_addr)->sin_addr.s_addr;
|
||||
isLocalServer = (ntohl(addr4) & 0x7F000000) == 0x7F000000;
|
||||
}
|
||||
|
||||
net::DNSResolveFree(resultAddr);
|
||||
resultAddr = nullptr;
|
||||
}
|
||||
freeaddrinfo(resultAddr);
|
||||
isLocalServer = (((uint8_t*)&serverIp.s_addr)[0] == 0x7f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -198,7 +176,7 @@ void __NetInit() {
|
|||
|
||||
SceNetEtherAddr mac;
|
||||
getLocalMac(&mac);
|
||||
INFO_LOG(SCENET, "LocalHost IP will be %s [%s]", inet_ntoa(((sockaddr_in*)&LocalhostIP)->sin_addr), mac2str(&mac).c_str());
|
||||
INFO_LOG(SCENET, "LocalHost IP will be %s [%s]", inet_ntoa(g_localhostIP.in.sin_addr), mac2str(&mac).c_str());
|
||||
|
||||
// TODO: May be we should initialize & cleanup somewhere else than here for PortManager to be used as general purpose for whatever port forwarding PPSSPP needed
|
||||
__UPnPInit();
|
||||
|
|
|
@ -37,14 +37,82 @@
|
|||
uint8_t PPSSPP_ID = 0;
|
||||
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
static HANDLE hIDMapFile = NULL;
|
||||
static HANDLE hIDMapFile = nullptr;
|
||||
static HANDLE mapLock = nullptr;
|
||||
#else
|
||||
static int hIDMapFile = 0;
|
||||
static int hIDMapFile = -1;
|
||||
static long BUF_SIZE = 4096;
|
||||
#endif
|
||||
|
||||
static int32_t* pIDBuf = NULL;
|
||||
struct InstanceInfo {
|
||||
uint8_t pad[2];
|
||||
uint8_t next;
|
||||
uint8_t total;
|
||||
};
|
||||
|
||||
#define ID_SHM_NAME "/PPSSPP_ID"
|
||||
|
||||
static bool UpdateInstanceCounter(void (*callback)(volatile InstanceInfo *)) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
if (!hIDMapFile) {
|
||||
return false;
|
||||
}
|
||||
InstanceInfo *buf = (InstanceInfo *)MapViewOfFile(hIDMapFile, // handle to map object
|
||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||
0,
|
||||
0,
|
||||
sizeof(InstanceInfo));
|
||||
|
||||
if (!buf) {
|
||||
ERROR_LOG(SCENET, "Could not map view of file %s (%d).", ID_SHM_NAME, GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (!mapLock || WaitForSingleObject(mapLock, INFINITE) == 0) {
|
||||
callback(buf);
|
||||
if (mapLock) {
|
||||
ReleaseMutex(mapLock);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
UnmapViewOfFile(buf);
|
||||
|
||||
return result;
|
||||
#elif PPSSPP_PLATFORM(ANDROID) || defined(__LIBRETRO__)
|
||||
// TODO: replace shm_open & shm_unlink with ashmem or android-shmem
|
||||
return false;
|
||||
#else
|
||||
if (hIDMapFile < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InstanceInfo *buf = (InstanceInfo *)mmap(0, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, hIDMapFile, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
ERROR_LOG(SCENET, "mmap(%s) failure.", ID_SHM_NAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (mlock(buf, BUF_SIZE) == 0) {
|
||||
callback(buf);
|
||||
munlock(buf, BUF_SIZE);
|
||||
result = true;
|
||||
}
|
||||
|
||||
munmap(buf, BUF_SIZE);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
int GetInstancePeerCount() {
|
||||
static int c = 0;
|
||||
UpdateInstanceCounter([](volatile InstanceInfo *buf) {
|
||||
c = buf->total;
|
||||
});
|
||||
return c;
|
||||
}
|
||||
|
||||
// Get current number of instance of PPSSPP running.
|
||||
// Must be called only once during init.
|
||||
void InitInstanceCounter() {
|
||||
|
@ -56,6 +124,8 @@ void InitInstanceCounter() {
|
|||
int gran = sysInfo.dwAllocationGranularity ? sysInfo.dwAllocationGranularity : 0x10000;
|
||||
BUF_SIZE = (BUF_SIZE + gran - 1) & ~(gran - 1);
|
||||
|
||||
mapLock = CreateMutex(nullptr, FALSE, L"PPSSPP_ID_mutex");
|
||||
|
||||
hIDMapFile = CreateFileMapping(
|
||||
INVALID_HANDLE_VALUE, // use paging file
|
||||
NULL, // default security
|
||||
|
@ -65,89 +135,55 @@ void InitInstanceCounter() {
|
|||
TEXT(ID_SHM_NAME)); // name of mapping object
|
||||
|
||||
DWORD lasterr = GetLastError();
|
||||
if (hIDMapFile == NULL)
|
||||
{
|
||||
if (!hIDMapFile) {
|
||||
ERROR_LOG(SCENET, "Could not create %s file mapping object (%d).", ID_SHM_NAME, lasterr);
|
||||
PPSSPP_ID = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
PPSSPP_ID = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
(*pIDBuf)++;
|
||||
int id = *pIDBuf;
|
||||
UnmapViewOfFile(pIDBuf);
|
||||
//CloseHandle(hIDMapFile); //Should be called when program exits
|
||||
//hIDMapFile = NULL;
|
||||
|
||||
PPSSPP_ID = id;
|
||||
#elif PPSSPP_PLATFORM(ANDROID) || defined(__LIBRETRO__)
|
||||
// TODO : replace shm_open & shm_unlink with ashmem or android-shmem
|
||||
PPSSPP_ID = 1;
|
||||
#else
|
||||
long BUF_SIZE = 4096;
|
||||
//caddr_t pIDBuf;
|
||||
int status;
|
||||
|
||||
// Create shared memory object
|
||||
|
||||
// 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
|
||||
if (hIDMapFile < 0 || (ftruncate(hIDMapFile, BUF_SIZE)) == -1) { // Set the size
|
||||
ERROR_LOG(SCENET, "ftruncate(%s) failure.", ID_SHM_NAME);
|
||||
PPSSPP_ID = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
PPSSPP_ID = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
PPSSPP_ID = id;
|
||||
#endif
|
||||
|
||||
bool success = UpdateInstanceCounter([](volatile InstanceInfo *buf) {
|
||||
PPSSPP_ID = ++buf->next;
|
||||
buf->total++;
|
||||
});
|
||||
if (!success) {
|
||||
PPSSPP_ID = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownInstanceCounter() {
|
||||
UpdateInstanceCounter([](volatile InstanceInfo *buf) {
|
||||
buf->total--;
|
||||
});
|
||||
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
if (hIDMapFile) {
|
||||
CloseHandle(hIDMapFile); // If program exited(or crashed?) or the last handle reference closed the shared memory object will be deleted.
|
||||
hIDMapFile = nullptr;
|
||||
}
|
||||
if (mapLock) {
|
||||
CloseHandle(mapLock);
|
||||
mapLock = nullptr;
|
||||
}
|
||||
#elif PPSSPP_PLATFORM(ANDROID) || defined(__LIBRETRO__)
|
||||
// Do nothing
|
||||
#else
|
||||
// TODO : This unlink should be called when program exits instead of everytime the game reset.
|
||||
if (hIDMapFile != 0) {
|
||||
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;
|
||||
hIDMapFile = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ extern uint8_t PPSSPP_ID;
|
|||
|
||||
void InitInstanceCounter();
|
||||
void ShutdownInstanceCounter();
|
||||
int GetInstancePeerCount();
|
||||
|
||||
inline bool IsFirstInstance() {
|
||||
return PPSSPP_ID == 1;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Debugger/SymbolMap.h"
|
||||
#include "Core/Instance.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "Core/MIPS/JitCommon/JitBlockCache.h"
|
||||
#include "Windows/InputBox.h"
|
||||
|
@ -466,7 +467,11 @@ namespace MainWindow
|
|||
|
||||
void UpdateWindowTitle() {
|
||||
// Seems to be fine to call now since we use a UNICODE build...
|
||||
SetWindowText(hwndMain, windowTitle.c_str());
|
||||
std::wstring title = windowTitle;
|
||||
if (PPSSPP_ID >= 1 && GetInstancePeerCount() > 1) {
|
||||
title.append(ConvertUTF8ToWString(StringFromFormat(" (instance: %d)", (int)PPSSPP_ID)));
|
||||
}
|
||||
SetWindowText(hwndMain, title.c_str());
|
||||
}
|
||||
|
||||
void SetWindowTitle(const wchar_t *title) {
|
||||
|
@ -708,6 +713,7 @@ namespace MainWindow
|
|||
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
UpdateWindowTitle();
|
||||
bool pause = true;
|
||||
if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
|
||||
WindowsRawInput::GainFocus();
|
||||
|
@ -741,6 +747,10 @@ namespace MainWindow
|
|||
}
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
UpdateWindowTitle();
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
// This window is always covered by DisplayWindow. No reason to erase.
|
||||
return 1;
|
||||
|
|
|
@ -170,9 +170,7 @@ void WindowsHost::SetWindowTitle(const char *message) {
|
|||
#ifdef _DEBUG
|
||||
winTitle.append(L" (debug)");
|
||||
#endif
|
||||
if (PPSSPP_ID >= 1) {
|
||||
winTitle.append(ConvertUTF8ToWString(StringFromFormat(" (instance: %d)", (int)PPSSPP_ID)));
|
||||
}
|
||||
lastTitle_ = winTitle;
|
||||
|
||||
MainWindow::SetWindowTitle(winTitle.c_str());
|
||||
PostMessage(mainWindow_, MainWindow::WM_USER_WINDOW_TITLE_CHANGED, 0, 0);
|
||||
|
@ -194,6 +192,12 @@ void WindowsHost::ShutdownSound() {
|
|||
|
||||
void WindowsHost::UpdateUI() {
|
||||
PostMessage(mainWindow_, MainWindow::WM_USER_UPDATE_UI, 0, 0);
|
||||
|
||||
int peers = GetInstancePeerCount();
|
||||
if (PPSSPP_ID >= 1 && peers != lastNumInstances_) {
|
||||
lastNumInstances_ = peers;
|
||||
PostMessage(mainWindow_, MainWindow::WM_USER_WINDOW_TITLE_CHANGED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHost::UpdateMemView() {
|
||||
|
|
|
@ -73,6 +73,8 @@ private:
|
|||
HWND mainWindow_;
|
||||
GraphicsContext *gfx_ = nullptr;
|
||||
size_t numDinputDevices_ = 0;
|
||||
std::wstring lastTitle_;
|
||||
int lastNumInstances_ = 0;
|
||||
|
||||
std::list<std::unique_ptr<InputDevice>> input;
|
||||
};
|
||||
|
|
|
@ -516,6 +516,22 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
|||
g_Config.internalDataDirectory = W32Util::UserDocumentsPath();
|
||||
InitSysDirectories();
|
||||
|
||||
// Check for the Vulkan workaround before any serious init.
|
||||
for (size_t i = 1; i < wideArgs.size(); ++i) {
|
||||
if (wideArgs[i][0] == L'-') {
|
||||
// This should only be called by DetectVulkanInExternalProcess().
|
||||
if (wideArgs[i] == L"--vulkan-available-check") {
|
||||
// Just call it, this way it will crash here if it doesn't work.
|
||||
// (this is an external process.)
|
||||
bool result = VulkanMayBeAvailable();
|
||||
|
||||
LogManager::Shutdown();
|
||||
WinMainCleanup();
|
||||
return result ? EXIT_CODE_VULKAN_WORKS : EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load config up here, because those changes below would be overwritten
|
||||
// if it's not loaded here first.
|
||||
g_Config.AddSearchPath("");
|
||||
|
@ -574,17 +590,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
|||
g_Config.bSoftwareRendering = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This should only be called by DetectVulkanInExternalProcess().
|
||||
if (wideArgs[i] == L"--vulkan-available-check") {
|
||||
// Just call it, this way it will crash here if it doesn't work.
|
||||
// (this is an external process.)
|
||||
bool result = VulkanMayBeAvailable();
|
||||
|
||||
LogManager::Shutdown();
|
||||
WinMainCleanup();
|
||||
return result ? EXIT_CODE_VULKAN_WORKS : EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
|
|
|
@ -11,10 +11,6 @@ namespace net {
|
|||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// use free() to free the returned string.
|
||||
char *DNSResolveTry(const char *host, const char **err);
|
||||
char *DNSResolve(const char *host);
|
||||
|
||||
enum class DNSType {
|
||||
ANY = 0,
|
||||
IPV4 = 1,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "gfx_es2/draw_text.h"
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
UIContext::UIContext() {
|
||||
fontStyle_ = new UI::FontStyle();
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "math/geom2d.h"
|
||||
#include "math/lin/vec3.h"
|
||||
#include "gfx/texture_atlas.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
// Everything you need to draw a UI collected into a single unit that can be passed around.
|
||||
// Everything forward declared so this header is safe everywhere.
|
||||
|
@ -22,13 +22,17 @@ namespace Draw {
|
|||
}
|
||||
|
||||
class Texture;
|
||||
class ManagedTexture;
|
||||
class DrawBuffer;
|
||||
class TextDrawer;
|
||||
|
||||
namespace UI {
|
||||
struct Drawable;
|
||||
struct EventParams;
|
||||
struct Theme;
|
||||
struct FontStyle;
|
||||
class Event;
|
||||
class View;
|
||||
}
|
||||
|
||||
class DrawBuffer;
|
||||
|
|
Loading…
Add table
Reference in a new issue