diff --git a/CMakeLists.txt b/CMakeLists.txt index 19a2ab8893..3d30e7e0b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2252,6 +2252,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/HLE/sceNet.h Core/HLE/sceNet_lib.cpp Core/HLE/sceNet_lib.h + Core/HLE/NetAdhocCommon.cpp + Core/HLE/NetAdhocCommon.h Core/HLE/sceNetAdhoc.cpp Core/HLE/sceNetAdhoc.h Core/HLE/sceNetAdhocMatching.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 95afc14886..4623e05f56 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -627,6 +627,7 @@ + @@ -1140,6 +1141,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index e9d8adab35..f37280cbaa 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -520,6 +520,9 @@ HLE\Libraries + + HLE\Libraries + HLE\Libraries @@ -1758,6 +1761,9 @@ HLE\Libraries + + HLE\Libraries + HLE\Libraries diff --git a/Core/HLE/NetAdhocCommon.cpp b/Core/HLE/NetAdhocCommon.cpp new file mode 100644 index 0000000000..242735a3c6 --- /dev/null +++ b/Core/HLE/NetAdhocCommon.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2025- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "Core/HLE/NetAdhocCommon.h" + +#include "sceKernelMemory.h" +#include "Core/MemMapHelpers.h" + +u32 dummyThreadHackAddr = 0; +u32_le dummyThreadCode[3]; + + +void netAdhocValidateLoopMemory() { + // Allocate Memory if it wasn't valid/allocated after loaded from old SaveState + if (!dummyThreadHackAddr || strcmp("dummythreadhack", kernelMemory.GetBlockTag(dummyThreadHackAddr)) != 0) { + u32 blockSize = sizeof(dummyThreadCode); + dummyThreadHackAddr = kernelMemory.Alloc(blockSize, false, "dummythreadhack"); + if (dummyThreadHackAddr) + Memory::Memcpy(dummyThreadHackAddr, dummyThreadCode, sizeof(dummyThreadCode)); + } +} + +int netAdhocEnterGameModeTimeout = 15000000; // 15 sec as default timeout, to wait for all players to join + +std::recursive_mutex adhocEvtMtx; + +int IsAdhocctlInCB = 0; + + +u32 matchingThreadHackAddr = 0; +u32_le matchingThreadCode[3]; + +bool g_adhocServerConnected = false; diff --git a/Core/HLE/NetAdhocCommon.h b/Core/HLE/NetAdhocCommon.h new file mode 100644 index 0000000000..1e0b532b06 --- /dev/null +++ b/Core/HLE/NetAdhocCommon.h @@ -0,0 +1,56 @@ +// Copyright (c) 2025- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "CommonTypes.h" +#include "Swap.h" + +#include + +extern u32 dummyThreadHackAddr; +extern u32_le dummyThreadCode[3]; + +void netAdhocValidateLoopMemory(); + +extern int netAdhocEnterGameModeTimeout; + +// Old comments regarding the value of adhocDefaultTimeout: +// 3000000 usec +//2000000 usec // For some unknown reason, sometimes it tooks more than 2 seconds for Adhocctl Init to connect to AdhocServer on localhost (normally only 10 ms), and sometimes it tooks more than 1 seconds for built-in AdhocServer to be ready (normally only 1 ms) +constexpr int adhocDefaultTimeout = 5000000; + +constexpr int adhocDefaultDelay = 10000; //10000 +constexpr int adhocExtraDelay = 20000; //20000 +constexpr int adhocEventPollDelay = 100000; //100000; // Seems to be the same with PSP_ADHOCCTL_RECV_TIMEOUT + +// Old comments regarding the value of adhocEventDelay: +//1000000 +constexpr int adhocEventDelay = 2000000; //2000000 on real PSP ? + +extern std::recursive_mutex adhocEvtMtx; + +// TODO: this one is broken, perhaps delete it entirely? +extern int IsAdhocctlInCB; + + +extern u32 matchingThreadHackAddr; +extern u32_le matchingThreadCode[3]; + +extern bool g_adhocServerConnected; + +constexpr u32 defaultLastRecvDelta = 10000; //10000 usec worked well for games published by Falcom (ie. Ys vs Sora Kiseki, Vantage Master Portable) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index a3d6d1730b..1afa6b0731 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -52,7 +52,9 @@ #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceNetAdhoc.h" #include "Core/Instance.h" -#include "proAdhoc.h" +#include "proAdhoc.h" + +#include "Core/HLE/NetAdhocCommon.h" #ifdef _WIN32 #undef errno diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 17617d8b17..5f1ea72722 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -54,6 +54,9 @@ #include "Core/HLE/sceNp2.h" #include "Core/HLE/sceNetInet.h" #include "Core/HLE/sceNetResolver.h" +#include "Core/HLE/NetAdhocCommon.h" + +#include "Core/MIPS/MIPSCodeUtils.h" // for macros to implement __CreateHLELoop // These are all public. Should probably add accessors around these. bool g_netInited; @@ -524,6 +527,19 @@ static void __ResetInitNetLib() { memset(¶meter, 0, sizeof(parameter)); } +u32_le __CreateHLELoop(u32_le *loopAddr, const char *sceFuncName, const char *hleFuncName, const char *tagName) { + if (loopAddr == NULL || sceFuncName == NULL || hleFuncName == NULL) + return 0; + + loopAddr[0] = MIPS_MAKE_SYSCALL(sceFuncName, hleFuncName); + loopAddr[1] = MIPS_MAKE_B(-2); + loopAddr[2] = MIPS_MAKE_NOP(); + u32 blockSize = sizeof(u32_le)*3; + u32_le threadHackAddress = kernelMemory.Alloc(blockSize, false, tagName); // blockSize will be rounded to 256 granularity + Memory::Memcpy(threadHackAddress, loopAddr, sizeof(u32_le) * 3); // This area will be cleared again after loading an old savestate :( + return threadHackAddress; +} + void __NetCallbackInit() { // Init Network Callbacks dummyThreadHackAddr = __CreateHLELoop(dummyThreadCode, "sceNetAdhoc", "__NetTriggerCallbacks", "dummythreadhack"); diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 53801fa2da..8457e0bca0 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -52,6 +52,7 @@ #include "Core/HLE/sceNet.h" #include "Core/HLE/proAdhocServer.h" #include "Core/HLE/KernelWaitHelpers.h" +#include "Core/HLE/NetAdhocCommon.h" #ifdef _WIN32 #undef errno @@ -62,7 +63,6 @@ // TODO: Make accessor functions instead, and throw all this state in a struct. bool netAdhocInited; bool netAdhocctlInited; -bool g_adhocServerConnected = false; #define DISCOVER_DURATION_US 2000000 // 2 seconds is probably the normal time it takes for PSP to connect to a group (ie. similar to NetconfigDialog time) u64 netAdhocDiscoverStartTime = 0; @@ -72,25 +72,11 @@ SceNetAdhocDiscoverParam* netAdhocDiscoverParam = nullptr; u32 netAdhocDiscoverBufAddr = 0; bool netAdhocGameModeEntered = false; -int netAdhocEnterGameModeTimeout = 15000000; // 15 sec as default timeout, to wait for all players to join - -int adhocDefaultTimeout = 5000000; //2000000 usec // For some unknown reason, sometimes it tooks more than 2 seconds for Adhocctl Init to connect to AdhocServer on localhost (normally only 10 ms), and sometimes it tooks more than 1 seconds for built-in AdhocServer to be ready (normally only 1 ms) -int adhocDefaultDelay = 10000; //10000 -int adhocExtraDelay = 20000; //20000 -int adhocEventPollDelay = 100000; //100000; // Same timings with PSP_ADHOCCTL_RECV_TIMEOUT ? -int adhocMatchingEventDelay = 30000; //30000 -int adhocEventDelay = 2000000; //2000000 on real PSP ? - -constexpr u32 defaultLastRecvDelta = 10000; //10000 usec worked well for games published by Falcom (ie. Ys vs Sora Kiseki, Vantage Master Portable) SceUID threadAdhocID; -std::recursive_mutex adhocEvtMtx; std::deque> adhocctlEvents; std::map adhocctlHandlers; - -int IsAdhocctlInCB = 0; - int adhocctlNotifyEvent = -1; int adhocctlStateEvent = -1; int adhocSocketNotifyEvent = -1; @@ -100,11 +86,6 @@ std::map sendTargetPeers; int gameModeNotifyEvent = -1; -u32 dummyThreadHackAddr = 0; -u32_le dummyThreadCode[3]; -u32 matchingThreadHackAddr = 0; -u32_le matchingThreadCode[3]; - int AcceptPtpSocket(int ptpId, int newsocket, sockaddr_in& peeraddr, SceNetEtherAddr* addr, u16_le* port); int PollAdhocSocket(SceNetAdhocPollSd* sds, int count, int timeout, int nonblock); int FlushPtpSocket(int socketId); @@ -1092,16 +1073,6 @@ int WaitBlockingAdhocSocket(u64 threadSocketId, int type, int pspSocketId, void* return ERROR_NET_ADHOC_TIMEOUT; } -void netAdhocValidateLoopMemory() { - // Allocate Memory if it wasn't valid/allocated after loaded from old SaveState - if (!dummyThreadHackAddr || strcmp("dummythreadhack", kernelMemory.GetBlockTag(dummyThreadHackAddr)) != 0) { - u32 blockSize = sizeof(dummyThreadCode); - dummyThreadHackAddr = kernelMemory.Alloc(blockSize, false, "dummythreadhack"); - if (dummyThreadHackAddr) - Memory::Memcpy(dummyThreadHackAddr, dummyThreadCode, sizeof(dummyThreadCode)); - } -} - void __NetAdhocDoState(PointerWrap &p) { auto s = p.Section("sceNetAdhoc", 1, 8); if (!s) @@ -1208,19 +1179,6 @@ void __UpdateAdhocctlHandlers(u32 flag, u32 error) { adhocctlEvents.push_back({ flag, error }); } -u32_le __CreateHLELoop(u32_le *loopAddr, const char *sceFuncName, const char *hleFuncName, const char *tagName) { - if (loopAddr == NULL || sceFuncName == NULL || hleFuncName == NULL) - return 0; - - loopAddr[0] = MIPS_MAKE_SYSCALL(sceFuncName, hleFuncName); - loopAddr[1] = MIPS_MAKE_B(-2); - loopAddr[2] = MIPS_MAKE_NOP(); - u32 blockSize = sizeof(u32_le)*3; - u32_le dummyThreadHackAddr = kernelMemory.Alloc(blockSize, false, tagName); // blockSize will be rounded to 256 granularity - Memory::Memcpy(dummyThreadHackAddr, loopAddr, sizeof(u32_le) * 3); // This area will be cleared again after loading an old savestate :( - return dummyThreadHackAddr; -} - void __AdhocNotifInit() { adhocctlNotifyEvent = CoreTiming::RegisterEvent("__AdhocctlNotify", __AdhocctlNotify); adhocSocketNotifyEvent = CoreTiming::RegisterEvent("__AdhocSocketNotify", __AdhocSocketNotify); diff --git a/Core/HLE/sceNetAdhoc.h b/Core/HLE/sceNetAdhoc.h index a3fa481d34..76793fe61c 100644 --- a/Core/HLE/sceNetAdhoc.h +++ b/Core/HLE/sceNetAdhoc.h @@ -23,12 +23,6 @@ #ifdef _MSC_VER #pragma pack(push,1) #endif -typedef struct SceNetAdhocDiscoverParam { - u32_le unknown1; // SleepMode? (ie. 0 on on Legend Of The Dragon, 1 on Dissidia 012) - char groupName[ADHOCCTL_GROUPNAME_LEN]; - u32_le unknown2; // size of something? (ie. 0x3c on Legend Of The Dragon, 0x14 on Dissidia 012) // Note: the param size is 0x14 may be it can contains extra data too? - u32_le result; // inited to 0? -} PACK SceNetAdhocDiscoverParam; typedef struct ProductStruct { // Similar to SceNetAdhocctlAdhocId ? s32_le unknown; // Unknown, set to 0 // Product Type ? @@ -79,6 +73,14 @@ enum AdhocSocketRequestType : int ADHOC_POLL_SOCKET = 7, }; +// TODO: maybe move these to sceNetAdhocDiscover? +typedef struct SceNetAdhocDiscoverParam { + u32_le unknown1; // SleepMode? (ie. 0 on on Legend Of The Dragon, 1 on Dissidia 012) + char groupName[ADHOCCTL_GROUPNAME_LEN]; + u32_le unknown2; // size of something? (ie. 0x3c on Legend Of The Dragon, 0x14 on Dissidia 012) // Note: the param size is 0x14 may be it can contains extra data too? + u32_le result; // inited to 0? +} PACK SceNetAdhocDiscoverParam; + enum AdhocDiscoverStatus : int { NET_ADHOC_DISCOVER_STATUS_NONE = 0, @@ -99,17 +101,21 @@ class PointerWrap; void Register_sceNetAdhoc(); void Register_sceNetAdhocDiscover(); + +// TODO: expose it via "sceNetAdhocctl.h" void Register_sceNetAdhocctl(); -u32_le __CreateHLELoop(u32_le* loopAddr, const char* sceFuncName, const char* hleFuncName, const char* tagName = NULL); void __NetAdhocInit(); void __NetAdhocShutdown(); void __NetAdhocDoState(PointerWrap &p); + +// TODO: expose it via "sceNetAdhocctl.h" void __UpdateAdhocctlHandlers(u32 flags, u32 error); bool __NetAdhocConnected(); +// TODO: expose these via "sceNetAdhocctl.h" // Called from netdialog (and from sceNetApctl) // NOTE: use hleCall for sceNet* ones! int sceNetAdhocctlGetState(u32 ptrToStatus); @@ -125,29 +131,15 @@ int sceNetAdhocctlTerm(); int NetAdhocctl_Term(); int NetAdhocctl_GetState(); int NetAdhocctl_Create(const char* groupName); + int NetAdhoc_Term(); // May need to use these from sceNet.cpp -extern bool netAdhocInited; -extern bool netAdhocctlInited; -extern bool g_adhocServerConnected; +extern bool netAdhocInited; // TODO: keep here +extern bool netAdhocctlInited; // TODO: move to sceNetAdhocctl + extern bool netAdhocGameModeEntered; -extern s32 netAdhocDiscoverStatus; - -extern int netAdhocEnterGameModeTimeout; -extern int adhocDefaultTimeout; //3000000 usec -extern int adhocDefaultDelay; //10000 -extern int adhocExtraDelay; //20000 -extern int adhocEventPollDelay; //100000; // Seems to be the same with PSP_ADHOCCTL_RECV_TIMEOUT -extern int adhocMatchingEventDelay; //30000 -extern int adhocEventDelay; //1000000 -extern std::recursive_mutex adhocEvtMtx; -extern int IsAdhocctlInCB; - -extern u32 dummyThreadHackAddr; -extern u32_le dummyThreadCode[3]; -extern u32 matchingThreadHackAddr; -extern u32_le matchingThreadCode[3]; +extern s32 netAdhocDiscoverStatus; // TODO: maybe move to sceNetAdhocDiscover? // Exposing those for the matching routines // NOTE: use hleCall for sceNet* ones! diff --git a/Core/HLE/sceNetAdhocMatching.cpp b/Core/HLE/sceNetAdhocMatching.cpp index 9351b8d761..f4a577937e 100644 --- a/Core/HLE/sceNetAdhocMatching.cpp +++ b/Core/HLE/sceNetAdhocMatching.cpp @@ -18,6 +18,7 @@ #include "Core/HLE/sceNetAdhocMatching.h" #include "Core/HLE/sceNetAdhoc.h" +#include "Core/HLE/NetAdhocCommon.h" #include #include @@ -43,6 +44,8 @@ std::vector matchingThreads; std::deque matchingEvents; bool netAdhocMatchingInited; +int adhocMatchingEventDelay = 30000; //30000 + static bool savedNetAdhocMatchingInited; // the storage to use during the savestating routine in sceNetAdhoc.cpp void DoNetAdhocMatchingInited(PointerWrap &p) { @@ -69,8 +72,6 @@ void RestoreNetAdhocMatchingInited() { int netAdhocMatchingStarted = 0; -constexpr u32 defaultLastRecvDelta = 10000; //10000 usec worked well for games published by Falcom (ie. Ys vs Sora Kiseki, Vantage Master Portable) - void __UpdateMatchingHandler(const MatchingArgs &ArgsPtr) { std::lock_guard adhocGuard(adhocEvtMtx); diff --git a/Core/HLE/sceNetAdhocMatching.h b/Core/HLE/sceNetAdhocMatching.h index 0aeae59dfc..a262a66995 100644 --- a/Core/HLE/sceNetAdhocMatching.h +++ b/Core/HLE/sceNetAdhocMatching.h @@ -44,3 +44,4 @@ void __NetAdhocMatchingInit(); void __NetAdhocMatchingShutdown(); extern bool netAdhocMatchingInited; +extern int adhocMatchingEventDelay; //30000 diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index a5459bbad9..62afba4405 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -36,6 +36,7 @@ #include "Core/HLE/sceNetAdhoc.h" #include "Core/HLE/proAdhoc.h" #include "Core/HLE/sceNetAdhocMatching.h" +#include "Core/HLE/NetAdhocCommon.h" #include "Common/System/Request.h" #include "Core/Util/AtracTrack.h" diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 7336981174..8068addbfb 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -47,6 +47,7 @@ #include "Core/HLE/sceNet.h" #include "Core/HLE/sceNetInet.h" #include "Core/HLE/sceNetAdhoc.h" +#include "Core/HLE/NetAdhocCommon.h" #include "GPU/GPUCommon.h" #include "GPU/GPUState.h" diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 672b819f73..fa433fa784 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -214,6 +214,7 @@ + @@ -478,6 +479,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index dada5b41fc..b459ebb663 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -126,6 +126,7 @@ + @@ -538,6 +539,7 @@ + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 5987d02894..bd579004fb 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -708,6 +708,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/HLE/sceNet_lib.cpp \ $(SRC)/Core/HLE/proAdhoc.cpp \ $(SRC)/Core/HLE/proAdhocServer.cpp \ + $(SRC)/Core/HLE/NetAdhocCommon.cpp \ $(SRC)/Core/HLE/sceNetAdhoc.cpp \ $(SRC)/Core/HLE/sceNetAdhocMatching.cpp \ $(SRC)/Core/HLE/sceNetApctl.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index dc7a0ddf64..604727db4c 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -739,6 +739,7 @@ SOURCES_CXX += \ $(COREDIR)/HLE/sceMpeg.cpp \ $(COREDIR)/HLE/sceNet.cpp \ $(COREDIR)/HLE/sceNet_lib.cpp \ + $(COREDIR)/HLE/NetAdhocCommon.cpp \ $(COREDIR)/HLE/sceNetAdhoc.cpp \ $(COREDIR)/HLE/sceNetAdhocMatching.cpp \ $(COREDIR)/HLE/sceNetApctl.cpp \