An attempt to differentiate adhoc connect, create, and join.

This commit is contained in:
ANR2ME 2020-08-18 00:39:46 +07:00
parent 4520a20a9f
commit 6a9cf0f575
7 changed files with 265 additions and 78 deletions

View File

@ -18,17 +18,20 @@
#if defined(_WIN32)
#include "Common/CommonWindows.h"
#endif
#include <TimeUtil.h>
#include "i18n/i18n.h"
#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Core/Config.h"
#include "Core/MemMapHelpers.h"
#include "Core/Util/PPGeDraw.h"
#include "Core/HLE/sceKernelMemory.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceUtility.h"
#include <Core/HLE/sceNet.h>
#include "Core/HLE/sceNet.h"
#include "Core/HLE/sceNetAdhoc.h"
#include "Core/Dialog/PSPNetconfDialog.h"
#include <ext/native/util/text/utf8.h>
#include "ext/native/util/text/utf8.h"
#define NETCONF_CONNECT_APNET 0
@ -44,6 +47,13 @@ static const float FONT_SCALE = 0.65f;
const static int NET_INIT_DELAY_US = 300000;
const static int NET_SHUTDOWN_DELAY_US = 26000;
const static int NET_RUNNING_DELAY_US = 1000000; // KHBBS is showing adhoc dialog for about 3-4 seconds, but feels too long, so we're faking it to 1 sec instead to let players read the text
const static int NET_CONNECT_TIMEOUT = 5000000;
struct ScanInfos {
s32_le sz;
SceNetAdhocctlScanInfoEmu si;
} PACK;
PSPNetconfDialog::PSPNetconfDialog() {
}
@ -78,6 +88,11 @@ int PSPNetconfDialog::Init(u32 paramAddr) {
cancelButtonFlag = CTRL_CIRCLE;
}
connResult = -1;
scanInfosAddr = 0;
scanStep = 0;
startTime = (u64)(real_time_now() * 1000000.0);
StartFade(true);
return 0;
}
@ -114,7 +129,7 @@ void PSPNetconfDialog::DisplayMessage(std::string text1, std::string text2a, std
// Without the scrollbar, we have 350 total pixels.
float WRAP_WIDTH = 300.0f;
if (UTF8StringNonASCIICount(text1.c_str()) >= text1.size() / 4) {
if (UTF8StringNonASCIICount(text1.c_str()) >= (int)text1.size() / 4) {
WRAP_WIDTH = 336.0f;
if (text1.size() > 12) {
messageStyle.scale = 0.6f;
@ -182,12 +197,20 @@ void PSPNetconfDialog::DisplayMessage(std::string text1, std::string text2a, std
PPGeScissor(0, (int)(centerY - h2 - 2), 480, (int)(centerY + h2 + 2));
PPGeDrawTextWrapped(text1.c_str(), 240.0f, centerY - h2 - scrollPos_, WRAP_WIDTH, 0, messageStyle);
if (text2a != "")
if (text2a != "") {
if (text2b != "")
PPGeDrawTextWrapped(text2a.c_str(), 240.0f - 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyleRight);
else
PPGeDrawTextWrapped(text2a.c_str(), 240.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyle);
}
if (text2b != "")
PPGeDrawTextWrapped(text2b.c_str(), 240.0f + 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyleLeft);
if (text3a != "")
if (text3a != "") {
if (text3b != "")
PPGeDrawTextWrapped(text3a.c_str(), 240.0f - 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyleRight);
else
PPGeDrawTextWrapped(text3a.c_str(), 240.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyle);
}
if (text3b != "")
PPGeDrawTextWrapped(text3b.c_str(), 240.0f + 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyleLeft);
PPGeScissorReset();
@ -229,6 +252,7 @@ int PSPNetconfDialog::Update(int animSpeed) {
UpdateButtons();
auto di = GetI18NCategory("Dialog");
auto err = GetI18NCategory("Error");
u64 now = (u64)(real_time_now() * 1000000.0);
// It seems JPCSP doesn't check for NETCONF_STATUS_APNET
if (request.netAction == NETCONF_CONNECT_APNET || request.netAction == NETCONF_STATUS_APNET || request.netAction == NETCONF_CONNECT_APNET_LAST) {
@ -310,6 +334,7 @@ int PSPNetconfDialog::Update(int animSpeed) {
}
else if (request.netAction == NETCONF_CONNECT_ADHOC || request.netAction == NETCONF_CREATE_ADHOC || request.netAction == NETCONF_JOIN_ADHOC) {
int state = NetAdhocctl_GetState();
bool timedout = (state == ADHOCCTL_STATE_DISCONNECTED && now - startTime > NET_CONNECT_TIMEOUT);
UpdateFade(animSpeed);
StartDraw();
@ -317,19 +342,105 @@ int PSPNetconfDialog::Update(int animSpeed) {
DrawBanner();
DrawIndicator();
if (timedout) {
// FIXME: Do we need to show error message?
DisplayMessage(di->T("InternalError", "An internal error has occurred.") + StringFromFormat("\n(%08X)", connResult));
DisplayButtons(DS_BUTTON_CANCEL, di->T("Back"));
}
else {
std::string channel = std::to_string(g_Config.iWlanAdhocChannel);
if (g_Config.iWlanAdhocChannel == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC)
channel = "Automatic";
DisplayMessage(di->T("ConnectingChannel", "Connecting.\nPlease wait...\n\nChannel")+std::string(" ")+di->T(channel));
DisplayMessage(di->T("ConnectingPleaseWait", "Connecting.\nPlease wait..."), di->T("Channel") + std::string(" ") + di->T(channel));
// Only Join mode is showing Cancel button on KHBBS and the button will fade out before the dialog is fading out, probably because it's already connected thus can't be canceled anymore
if (request.netAction == NETCONF_JOIN_ADHOC)
DisplayButtons(DS_BUTTON_CANCEL, di->T("Cancel"));
if (state == ADHOCCTL_STATE_DISCONNECTED && request.NetconfData.IsValid()) {
// KHBBS will first enter the arena using NETCONF_CONNECT_ADHOC (auto-create group when not exist yet?), but when the event started the event's creator use NETCONF_CREATE_ADHOC while the joining players use NETCONF_JOIN_ADHOC
if (request.NetconfData.IsValid()) {
if (state == ADHOCCTL_STATE_DISCONNECTED) {
switch (request.netAction)
{
case NETCONF_CREATE_ADHOC:
if (connResult < 0) {
connResult = sceNetAdhocctlCreate(request.NetconfData->groupName);
}
break;
case NETCONF_JOIN_ADHOC:
// FIXME: Should we Scan for a matching group first before Joining a Group (like adhoc games normally do)? Or Is it really allowed to join non-existing group?
if (scanStep == 0) {
if (sceNetAdhocctlScan() >= 0) {
u32 structsz = sizeof(ScanInfos);
if (Memory::IsValidAddress(scanInfosAddr))
userMemory.Free(scanInfosAddr);
scanInfosAddr = userMemory.Alloc(structsz, false, "NetconfScanInfo");
Memory::Write_U32(sizeof(SceNetAdhocctlScanInfoEmu), scanInfosAddr);
scanStep = 1;
}
}
else if (scanStep == 1) {
s32 sz = Memory::Read_U32(scanInfosAddr);
// Get required buffer size
if (sceNetAdhocctlGetScanInfo(scanInfosAddr, 0) >= 0) {
s32 reqsz = Memory::Read_U32(scanInfosAddr);
if (reqsz > sz) {
sz = reqsz;
if (Memory::IsValidAddress(scanInfosAddr))
userMemory.Free(scanInfosAddr);
u32 structsz = sz + sizeof(s32);
scanInfosAddr = userMemory.Alloc(structsz, false, "NetconfScanInfo");
Memory::Write_U32(sz, scanInfosAddr);
}
if (reqsz > 0) {
if (sceNetAdhocctlGetScanInfo(scanInfosAddr, scanInfosAddr + sizeof(s32)) >= 0) {
ScanInfos* scanInfos = (ScanInfos*)Memory::GetPointer(scanInfosAddr);
int n = scanInfos->sz / sizeof(SceNetAdhocctlScanInfoEmu);
// Assuming returned SceNetAdhocctlScanInfoEmu(s) are contagious where next is pointing to current addr + sizeof(SceNetAdhocctlScanInfoEmu)
while (n > 0) {
SceNetAdhocctlScanInfoEmu* si = (SceNetAdhocctlScanInfoEmu*)Memory::GetPointer(scanInfosAddr + sizeof(s32) + sizeof(SceNetAdhocctlScanInfoEmu) * (n - 1LL));
if (memcmp(si->group_name.data, request.NetconfData->groupName, ADHOCCTL_GROUPNAME_LEN) == 0) {
// Moving found group info to the front so we can use it on sceNetAdhocctlJoin easily
memcpy((char*)scanInfos + sizeof(s32), si, sizeof(SceNetAdhocctlScanInfoEmu));
scanStep = 2;
break;
}
n--;
}
// Target group not found, try to scan again later
if (n <= 0) {
scanStep = 0;
}
}
}
// No group found, try to scan again later
else {
scanStep = 0;
}
}
}
else if (scanStep == 2) {
if (connResult < 0) {
connResult = sceNetAdhocctlJoin(scanInfosAddr + sizeof(s32));
if (connResult >= 0) {
// We are done!
if (Memory::IsValidAddress(scanInfosAddr))
userMemory.Free(scanInfosAddr);
scanInfosAddr = 0;
}
}
}
break;
default:
if (connResult < 0) {
connResult = sceNetAdhocctlConnect(request.NetconfData->groupName);
}
break;
}
}
}
}
// The Netconf dialog stays visible until the network reaches
// the state ADHOCCTL_STATE_CONNECTED.
@ -342,12 +453,20 @@ int PSPNetconfDialog::Update(int animSpeed) {
else if (GetStatus() == SCE_UTILITY_STATUS_FINISHED) {
StartFade(false);
}
// Let's not leaks any memory
if (Memory::IsValidAddress(scanInfosAddr))
userMemory.Free(scanInfosAddr);
scanInfosAddr = 0;
}
if (request.netAction == NETCONF_JOIN_ADHOC && IsButtonPressed(cancelButtonFlag)) {
if ((request.netAction == NETCONF_JOIN_ADHOC || timedout) && IsButtonPressed(cancelButtonFlag)) {
StartFade(false);
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NET_SHUTDOWN_DELAY_US);
request.common.result = SCE_UTILITY_DIALOG_RESULT_ABORT;
// Let's not leaks any memory
if (Memory::IsValidAddress(scanInfosAddr))
userMemory.Free(scanInfosAddr);
scanInfosAddr = 0;
}
EndDraw();
@ -374,11 +493,25 @@ int PSPNetconfDialog::Shutdown(bool force) {
void PSPNetconfDialog::DoState(PointerWrap &p) {
PSPDialog::DoState(p);
auto s = p.Section("PSPNetconfigDialog", 0, 1);
auto s = p.Section("PSPNetconfigDialog", 0, 2);
if (!s)
return;
Do(p, request);
if (s >= 2) {
Do(p, scanInfosAddr);
Do(p, scanStep);
Do(p, connResult);
}
else {
scanInfosAddr = 0;
scanStep = 0;
connResult = -1;
}
if (p.mode == p.MODE_READ) {
startTime = 0;
}
}
pspUtilityDialogCommon* PSPNetconfDialog::GetCommonParam()

View File

@ -34,6 +34,7 @@ struct SceUtilityNetconfParam {
int netWifiSpot; // Flag to allow WIFI connections
};
class PSPNetconfDialog: public PSPDialog {
public:
PSPNetconfDialog();
@ -57,11 +58,15 @@ private:
SceUtilityNetconfParam request = {};
u32 requestAddr = 0;
int connResult = 0;
int connResult = -1;
bool hideNotice = false;
int yesnoChoice = 0;
float scrollPos_ = 0.0f;
int framesUpHeld_ = 0;
int framesDownHeld_ = 0;
u32 scanInfosAddr = 0;
int scanStep = 0;
u64 startTime = 0;
};

View File

@ -55,7 +55,8 @@ bool friendFinderRunning = false;
SceNetAdhocctlPeerInfo * friends = NULL;
SceNetAdhocctlScanInfo * networks = NULL;
SceNetAdhocctlScanInfo * newnetworks = NULL;
int threadStatus = ADHOCCTL_STATE_DISCONNECTED;
int adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
int adhocConnectionType = ADHOC_CONNECT;
int actionAfterAdhocMipsCall;
int actionAfterMatchingMipsCall;
@ -1293,9 +1294,9 @@ int friendFinder(){
// Update User BSSID
parameter.bssid.mac_addr = packet->mac; // This packet seems to contains Adhoc Group Creator's BSSID (similar to AP's BSSID) so it shouldn't get mixed up with local MAC address
// Notify Event Handlers
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
// Change State
threadStatus = ADHOCCTL_STATE_CONNECTED;
//threadStatus = ADHOCCTL_STATE_CONNECTED;
// Give time a little time
//sceKernelDelayThread(adhocEventDelayMS * 1000);
//sleep_ms(adhocEventDelayMS);
@ -1492,14 +1493,14 @@ int friendFinder(){
peerlock.unlock();
// Notify Event Handlers
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN, 0);
notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN, 0);
//int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++)
//{
// // Active Handler
// if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]);
//}
// Change State
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
//threadStatus = ADHOCCTL_STATE_DISCONNECTED;
// Give time a little time
//sceKernelDelayThread(adhocEventDelayMS * 1000);
//sleep_ms(adhocEventDelayMS);
@ -1522,7 +1523,7 @@ int friendFinder(){
// Groups/Networks should be deallocated isn't?
// Prevent the games from having trouble to reInitiate Adhoc (the next NetInit -> PdpCreate after NetTerm)
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
// Log Shutdown
INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread");

View File

@ -847,9 +847,17 @@ extern int one;
extern bool friendFinderRunning;
extern SceNetAdhocctlPeerInfo * friends;
extern SceNetAdhocctlScanInfo * networks;
extern int threadStatus;
extern int adhocctlState;
extern int adhocConnectionType;
// End of Aux vars
enum AdhocConnectionType : int
{
ADHOC_CONNECT = 0,
ADHOC_CREATE = 1,
ADHOC_JOIN = 2,
};
// Check if Matching callback is running
bool IsMatchingInCallback(SceNetAdhocMatchingContext * context);
bool SetMatchingInCallback(SceNetAdhocMatchingContext* context, bool IsInCB);

View File

@ -469,7 +469,7 @@ void __NetApctlCallbacks()
// Must be delayed long enough whenever there is a pending callback.
sceKernelDelayThread(delayus);
hleSkipDeadbeef();;
hleSkipDeadbeef();
}
static inline u32 AllocUser(u32 size, bool fromTop, const char *name) {

View File

@ -113,7 +113,7 @@ void __NetAdhocShutdown() {
}
void __NetAdhocDoState(PointerWrap &p) {
auto s = p.Section("sceNetAdhoc", 1, 4);
auto s = p.Section("sceNetAdhoc", 1, 5);
if (!s)
return;
@ -156,6 +156,14 @@ void __NetAdhocDoState(PointerWrap &p) {
it = 0;
}
}
if (s >= 5) {
Do(p, adhocConnectionType);
Do(p, adhocctlState);
}
else {
adhocConnectionType = ADHOC_CONNECT;
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
}
if (p.mode == p.MODE_READ) {
// Previously, this wasn't being saved. It needs its own space.
@ -276,10 +284,10 @@ static u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
}
int NetAdhocctl_GetState() {
return threadStatus;
return adhocctlState;
}
static int sceNetAdhocctlGetState(u32 ptrToStatus) {
int sceNetAdhocctlGetState(u32 ptrToStatus) {
// Library uninitialized
if (!netAdhocctlInited)
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED;
@ -1044,7 +1052,7 @@ static int sceNetAdhocctlGetAdhocId(u32 productStructAddr) {
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED;
}
static int sceNetAdhocctlScan() {
int sceNetAdhocctlScan() {
INFO_LOG(SCENET, "sceNetAdhocctlScan() at %08x", currentMIPS->pc);
// Library initialized
@ -1052,14 +1060,14 @@ static int sceNetAdhocctlScan() {
// Wait until Not connected
if (friendFinderRunning) {
int cnt = 0;
while ((threadStatus != ADHOCCTL_STATE_DISCONNECTED) && (cnt < adhocDefaultTimeout)) {
while ((adhocctlState != ADHOCCTL_STATE_DISCONNECTED) && (cnt < adhocDefaultTimeout)) {
sleep_ms(1);
cnt++;
}
}
if (threadStatus == ADHOCCTL_STATE_DISCONNECTED) {
threadStatus = ADHOCCTL_STATE_SCANNING;
if (adhocctlState == ADHOCCTL_STATE_DISCONNECTED) {
adhocctlState = ADHOCCTL_STATE_SCANNING;
// Reset Networks/Group list to prevent other threads from using these soon to be replaced networks
peerlock.lock();
@ -1075,24 +1083,24 @@ static int sceNetAdhocctlScan() {
if (iResult == SOCKET_ERROR) {
int error = errno;
ERROR_LOG(SCENET, "Socket error (%i) when sending", error);
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
//if (error == ECONNABORTED || error == ECONNRESET || error == ENOTCONN) return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; // A case where it need to reconnect to AdhocServer
return ERROR_NET_ADHOCCTL_DISCONNECTED; // ERROR_NET_ADHOCCTL_BUSY
}
// Does Connected Event's mipscall need be executed after returning from sceNetAdhocctlScan ?
notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN, 0);
hleCheckCurrentCallbacks();
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN, 0);
//hleCheckCurrentCallbacks();
// Wait for Status to be connected to prevent Ford Street Racing from Failed to find game session
// TODO: Do this async while Delaying HLE Result
if (friendFinderRunning) {
/*if (friendFinderRunning) {
int cnt = 0;
while ((threadStatus == ADHOCCTL_STATE_SCANNING) && (cnt < adhocDefaultTimeout)) {
while ((adhocctlState == ADHOCCTL_STATE_SCANNING) && (cnt < adhocDefaultTimeout)) {
sleep_ms(1);
cnt++;
}
}
}*/
//sceKernelDelayThread(adhocEventPollDelayMS * 1000);
//hleDelayResult(0, "give time to init/cleanup", adhocEventPollDelayMS * 1000);
@ -1109,7 +1117,7 @@ static int sceNetAdhocctlScan() {
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED;
}
static int sceNetAdhocctlGetScanInfo(u32 sizeAddr, u32 bufAddr) {
int sceNetAdhocctlGetScanInfo(u32 sizeAddr, u32 bufAddr) {
s32_le *buflen = NULL;
if (Memory::IsValidAddress(sizeAddr)) buflen = (s32_le *)Memory::GetPointer(sizeAddr);
SceNetAdhocctlScanInfoEmu *buf = NULL;
@ -1245,7 +1253,7 @@ u32 NetAdhocctl_Disconnect() {
// Library initialized
if (netAdhocctlInited) {
// Connected State (Adhoc Mode)
if (threadStatus != ADHOCCTL_STATE_DISCONNECTED) { // (threadStatus == ADHOCCTL_STATE_CONNECTED)
if (adhocctlState != ADHOCCTL_STATE_DISCONNECTED) { // (threadStatus == ADHOCCTL_STATE_CONNECTED)
// Clear Network Name
memset(&parameter.group_name, 0, sizeof(parameter.group_name));
@ -1265,7 +1273,7 @@ u32 NetAdhocctl_Disconnect() {
}
// Set Disconnected State
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
// Free Network Lock
//_freeNetworkLock();
@ -1324,7 +1332,7 @@ static u32 sceNetAdhocctlDelHandler(u32 handlerID) {
int NetAdhocctl_Term() {
if (netAdhocctlInited) {
if (threadStatus != ADHOCCTL_STATE_DISCONNECTED)
if (adhocctlState != ADHOCCTL_STATE_DISCONNECTED)
NetAdhocctl_Disconnect();
// Terminate Adhoc Threads
@ -1512,14 +1520,14 @@ int NetAdhocctl_Create(const char* groupName) {
// Wait until Not connected
if (friendFinderRunning) {
int cnt = 0;
while ((threadStatus != ADHOCCTL_STATE_DISCONNECTED && threadStatus != ADHOCCTL_STATE_SCANNING) && (cnt < adhocDefaultTimeout)) {
while ((adhocctlState != ADHOCCTL_STATE_DISCONNECTED && adhocctlState != ADHOCCTL_STATE_SCANNING) && (cnt < adhocDefaultTimeout)) {
sleep_ms(1);
cnt++;
}
}
// Disconnected State, may also need to check for Scanning state to prevent some games from failing to host a game session
if ((threadStatus == ADHOCCTL_STATE_DISCONNECTED) || (threadStatus == ADHOCCTL_STATE_SCANNING)) {
if ((adhocctlState == ADHOCCTL_STATE_DISCONNECTED) || (adhocctlState == ADHOCCTL_STATE_SCANNING)) {
// Set Network Name
if (groupNameStruct != NULL) parameter.group_name = *groupNameStruct;
@ -1546,7 +1554,7 @@ int NetAdhocctl_Create(const char* groupName) {
ERROR_LOG(SCENET, "Socket error (%i) when sending", errno);
//return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; // ERROR_NET_ADHOCCTL_DISCONNECTED; // ERROR_NET_ADHOCCTL_BUSY;
//Faking success, to prevent Full Auto 2 from freezing while Initializing Network
threadStatus = ADHOCCTL_STATE_CONNECTED;
adhocctlState = ADHOCCTL_STATE_CONNECTED;
// Notify Event Handlers, Needed for the Nickname to be shown on the screen when success is faked
// Might be better not to notify the game when faking success (failed to connect to adhoc server), at least the player will know that it failed to connect
//__UpdateAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0); //CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventAdhocctlHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0));
@ -1558,17 +1566,17 @@ int NetAdhocctl_Create(const char* groupName) {
//setConnectionStatus(1);
// Connected Event's mipscall need be executed before returning from sceNetAdhocctlCreate (or before the next sceNet function?)
notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
// Wait for Status to be connected to prevent Ford Street Racing from Failed to create game session
// TODO: Do this async while Delaying HLE Result
if (friendFinderRunning) { // This is thread-unsafe
/*if (friendFinderRunning) { // This is thread-unsafe
int cnt = 0;
while ((threadStatus != ADHOCCTL_STATE_CONNECTED) && (cnt < adhocDefaultTimeout)) { // This is thread-unsafe
while ((adhocctlState != ADHOCCTL_STATE_CONNECTED) && (cnt < adhocDefaultTimeout)) { // This is thread-unsafe
sleep_ms(1);
cnt++;
}
}
}*/
//sceKernelDelayThreadCB(adhocEventDelayMS * 1000);
//hleCheckCurrentCallbacks();
@ -1602,24 +1610,24 @@ int sceNetAdhocctlCreate(const char *groupName) {
return -1;
}
adhocConnectionType = ADHOC_CREATE;
return NetAdhocctl_Create(groupName);
}
static int sceNetAdhocctlConnect(u32 ptrToGroupName) {
if (Memory::IsValidAddress(ptrToGroupName)) {
const char* groupName = Memory::GetCharPointer(ptrToGroupName);
int sceNetAdhocctlConnect(const char* groupName) {
char grpName[9] = { 0 };
memcpy(grpName, groupName, ADHOCCTL_GROUPNAME_LEN); // Copied to null-terminated var to prevent unexpected behaviour on Logs
INFO_LOG(SCENET, "sceNetAdhocctlConnect(groupName=%s) at %08x", grpName, currentMIPS->pc);
return NetAdhocctl_Create(groupName);
INFO_LOG(SCENET, "sceNetAdhocctlConnect(%s) at %08x", grpName, currentMIPS->pc);
if (!g_Config.bEnableWlan) {
return -1;
}
return ERROR_NET_ADHOC_INVALID_ARG; // ERROR_NET_ADHOC_INVALID_ADDR;
adhocConnectionType = ADHOC_CONNECT;
return NetAdhocctl_Create(groupName);
}
static int sceNetAdhocctlJoin(u32 scanInfoAddr) {
WARN_LOG(SCENET, "UNTESTED sceNetAdhocctlJoin(%08x) at %08x", scanInfoAddr, currentMIPS->pc);
int sceNetAdhocctlJoin(u32 scanInfoAddr) {
INFO_LOG(SCENET, "sceNetAdhocctlJoin(%08x) at %08x", scanInfoAddr, currentMIPS->pc);
if (!g_Config.bEnableWlan) {
return -1;
}
@ -1631,11 +1639,14 @@ static int sceNetAdhocctlJoin(u32 scanInfoAddr) {
if (Memory::IsValidAddress(scanInfoAddr))
{
SceNetAdhocctlScanInfoEmu* sinfo = (SceNetAdhocctlScanInfoEmu*)Memory::GetPointer(scanInfoAddr);
//while (true) sleep_ms(1);
char grpName[9] = { 0 };
memcpy(grpName, sinfo->group_name.data, ADHOCCTL_GROUPNAME_LEN); // Copied to null-terminated var to prevent unexpected behaviour on Logs
DEBUG_LOG(SCENET, "sceNetAdhocctlJoin - Group: %s", grpName);
// We can ignore minor connection process differences here
// TODO: Adhoc Server may need to be changed to differentiate between Host/Create and Join, otherwise it can't support multiple Host using the same Group name, thus causing one of the Host to be confused being treated as Join.
return NetAdhocctl_Create((const char*)&sinfo->group_name);
adhocConnectionType = ADHOC_JOIN;
return NetAdhocctl_Create(grpName);
}
// Invalid Argument
@ -4055,26 +4066,48 @@ void __NetTriggerCallbacks()
args[0] = flags;
args[1] = error;
//if (/*__KernelGetCurThread() == threadAdhocID &&*/ (!__IsInInterrupt() && __KernelIsDispatchEnabled() && !__KernelInCallback()) && IsAdhocctlInCallback() == 0)
// FIXME: When Joining a group, Do we need to wait for group creator's peer data before triggering the callback to make sure the game not to thinks we're the group creator?
if (flags != ADHOCCTL_EVENT_CONNECT || adhocConnectionType != ADHOC_JOIN || getActivePeerCount() > 0)
{
// Since 0 is a valid index to types_ we use -1 to detects if it was loaded from an old save state
if (actionAfterAdhocMipsCall < 0) {
actionAfterAdhocMipsCall = __KernelRegisterActionType(AfterAdhocMipsCall::Create);
}
delayus = (adhocEventPollDelayMS + 2 * adhocExtraPollDelayMS) * 1000; // Added an extra delay to prevent I/O Timing method from causing disconnection
switch (flags) {
case ADHOCCTL_EVENT_CONNECT:
adhocctlState = ADHOCCTL_STATE_CONNECTED;
delayus = (adhocEventDelayMS + 2 * adhocExtraPollDelayMS) * 1000; // May affects Dissidia 012 and GTA VCS
break;
case ADHOCCTL_EVENT_SCAN: // notified only when scan completed?
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
break;
case ADHOCCTL_EVENT_DISCONNECT:
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
break;
case ADHOCCTL_EVENT_GAME:
adhocctlState = ADHOCCTL_STATE_GAMEMODE;
break;
case ADHOCCTL_EVENT_DISCOVER:
adhocctlState = ADHOCCTL_STATE_DISCOVER;
break;
case ADHOCCTL_EVENT_WOL_INTERRUPT:
adhocctlState = ADHOCCTL_STATE_WOL;
break;
case ADHOCCTL_EVENT_ERROR:
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
break;
}
for (std::map<int, AdhocctlHandler>::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); ++it) {
DEBUG_LOG(SCENET, "AdhocctlCallback: [ID=%i][EVENT=%i]", it->first, flags);
args[2] = it->second.argument;
AfterAdhocMipsCall* after = (AfterAdhocMipsCall*)__KernelCreateAction(actionAfterAdhocMipsCall);
after->SetData(it->first, flags, args[2]);
//SetAdhocctlInCallback(true);
//__KernelDirectMipsCall(it->second.entryPoint, after, args, 3, true);
hleEnqueueCall(it->second.entryPoint, 3, args, after);
}
adhocctlEvents.pop_front();
if (flags == ADHOCCTL_EVENT_CONNECT)
delayus = (adhocEventDelayMS + 2*adhocExtraPollDelayMS) * 1000; // May affects Dissidia 012 and GTA VCS
else
delayus = (adhocEventPollDelayMS + 2*adhocExtraPollDelayMS) * 1000; // Added an extra delay to prevent I/O Timing method from causing disconnection
}
}
@ -4118,7 +4151,7 @@ void __NetMatchingCallbacks() //(int matchingId)
const HLEFunction sceNetAdhoc[] = {
{0XE1D621D7, &WrapU_V<sceNetAdhocInit>, "sceNetAdhocInit", 'x', "" },
{0XA62C6F57, &WrapI_V<sceNetAdhocTerm>, "sceNetAdhocTerm", 'i', "" },
{0X0AD043ED, &WrapI_U<sceNetAdhocctlConnect>, "sceNetAdhocctlConnect", 'i', "x" },
{0X0AD043ED, &WrapI_C<sceNetAdhocctlConnect>, "sceNetAdhocctlConnect", 'i', "s" },
{0X6F92741B, &WrapI_CIIU<sceNetAdhocPdpCreate>, "sceNetAdhocPdpCreate", 'i', "siix" },
{0XABED3790, &WrapI_ICUVIII<sceNetAdhocPdpSend>, "sceNetAdhocPdpSend", 'i', "isxpiii" },
{0XDFE53E03, &WrapI_IVVVVUI<sceNetAdhocPdpRecv>, "sceNetAdhocPdpRecv", 'i', "ippppxi" },
@ -4386,7 +4419,7 @@ const HLEFunction sceNetAdhocctl[] = {
{0X20B317A0, &WrapU_UU<sceNetAdhocctlAddHandler>, "sceNetAdhocctlAddHandler", 'x', "xx" },
{0X6402490B, &WrapU_U<sceNetAdhocctlDelHandler>, "sceNetAdhocctlDelHandler", 'x', "x" },
{0X34401D65, &WrapU_V<sceNetAdhocctlDisconnect>, "sceNetAdhocctlDisconnect", 'x', "" },
{0X0AD043ED, &WrapI_U<sceNetAdhocctlConnect>, "sceNetAdhocctlConnect", 'i', "x" },
{0X0AD043ED, &WrapI_C<sceNetAdhocctlConnect>, "sceNetAdhocctlConnect", 'i', "s" },
{0X08FFF7A0, &WrapI_V<sceNetAdhocctlScan>, "sceNetAdhocctlScan", 'i', "" },
{0X75ECD386, &WrapI_U<sceNetAdhocctlGetState>, "sceNetAdhocctlGetState", 'i', "x" },
{0X8916C003, &WrapI_CU<sceNetAdhocctlGetNameByAddr>, "sceNetAdhocctlGetNameByAddr", 'i', "sx" },

View File

@ -41,7 +41,18 @@ void __UpdateAdhocctlHandlers(u32 flags, u32 error);
void __UpdateMatchingHandler(MatchingArgs params);
// I have to call this from netdialog
int sceNetAdhocctlGetState(u32 ptrToStatus);
int sceNetAdhocctlCreate(const char * groupName);
int sceNetAdhocctlConnect(const char* groupName);
int sceNetAdhocctlJoin(u32 scanInfoAddr);
int sceNetAdhocctlScan();
int sceNetAdhocctlGetScanInfo(u32 sizeAddr, u32 bufAddr);
int NetAdhocMatching_Term();
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;
@ -60,7 +71,3 @@ extern u32_le dummyThreadCode[3];
extern u32 matchingThreadHackAddr;
extern u32_le matchingThreadCode[3];
int NetAdhocMatching_Term();
int NetAdhocctl_Term();
int NetAdhocctl_GetState();
int NetAdhoc_Term();