Merge pull request #13579 from ANR2ME/adhoc_fix

Adhoc fix - Updating Adhocctl behavior after doing some small test
This commit is contained in:
Henrik Rydgård 2020-10-29 11:57:58 +01:00 committed by GitHub
commit a4a0b4ba00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 612 additions and 325 deletions

View file

@ -21,6 +21,10 @@
// This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
// All credit goes to him!
#if defined(_WIN32)
#include "Common/CommonWindows.h"
#endif
#if !defined(_WIN32)
#include <unistd.h>
#include <netinet/tcp.h>
@ -62,6 +66,7 @@ SceNetAdhocctlPeerInfo * friends = NULL;
SceNetAdhocctlScanInfo * networks = NULL;
SceNetAdhocctlScanInfo * newnetworks = NULL;
u64 adhocctlStartTime = 0;
bool isAdhocctlBusy = false;
int adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
int adhocctlCurrentMode = ADHOCCTL_MODE_NONE;
int adhocConnectionType = ADHOC_CONNECT;
@ -315,7 +320,7 @@ void changeBlockingMode(int fd, int nonblocking) {
#endif
}
int countAvailableNetworks() {
int countAvailableNetworks(const bool excludeSelf) {
// Network Count
int count = 0;
@ -323,7 +328,7 @@ int countAvailableNetworks() {
SceNetAdhocctlScanInfo * group = networks;
// Count Groups
for (; group != NULL; group = group->next) count++;
for (; group != NULL && (!excludeSelf || !isLocalMAC(&group->bssid.mac_addr)); group = group->next) count++;
// Return Network Count
return count;
@ -1165,6 +1170,7 @@ void AfterAdhocMipsCall::run(MipsCall& call) {
u32 v0 = currentMIPS->r[MIPS_REG_V0];
if (__IsInInterrupt()) ERROR_LOG(SCENET, "AfterAdhocMipsCall::run [ID=%i][Event=%d] is Returning Inside an Interrupt!", HandlerID, EventID);
SetAdhocctlInCallback(false);
isAdhocctlBusy = false;
DEBUG_LOG(SCENET, "AfterAdhocMipsCall::run [ID=%i][Event=%d] [cbId: %u][retV0: %08x]", HandlerID, EventID, call.cbId, v0);
//call.setReturnValue(v0);
}
@ -1334,6 +1340,10 @@ int friendFinder(){
if (initNetwork(&product_code) == 0) {
networkInited = true;
INFO_LOG(SCENET, "FriendFinder: Network [RE]Initialized");
// At this point we are most-likely not in a Group within the Adhoc Server, so we should probably reset AdhocctlState
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
netAdhocGameModeEntered = false;
isAdhocctlBusy = false;
}
else {
networkInited = false;
@ -1395,6 +1405,12 @@ int friendFinder(){
}
}
// Calculate EnterGameMode Timeout to prevent waiting forever for disconnected players
if (isAdhocctlBusy && adhocctlState == ADHOCCTL_STATE_DISCONNECTED && adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE && netAdhocGameModeEntered && static_cast<s64>(now - adhocctlStartTime) > netAdhocEnterGameModeTimeout) {
netAdhocGameModeEntered = false;
notifyAdhocctlHandlers(ADHOCCTL_EVENT_ERROR, ERROR_NET_ADHOC_TIMEOUT);
}
// Handle Packets
if (rxpos > 0) {
// BSSID Packet
@ -1419,14 +1435,14 @@ int friendFinder(){
}) == gameModeMacs.end()) {
// Arrange the order to be consistent on all players (Host on top), Starting from our self the rest of new players will be added to the back
gameModeMacs.push_back(localMac);
// FIXME: OPCODE_CONNECT_BSSID only triggered once, but the timing of ADHOCCTL_EVENT_GAME notification could be too soon, since there could be more players that need to join before the event should be notified
if (netAdhocGameModeEntered && gameModeMacs.size() >= requiredGameModeMacs.size()) {
notifyAdhocctlHandlers(ADHOCCTL_EVENT_GAME, 0);
}
}
else
WARN_LOG(SCENET, "GameMode SelfMember [%s] Already Existed!", mac2str(&localMac).c_str());
if (gameModeMacs.size() >= requiredGameModeMacs.size()) {
//adhocctlState = ADHOCCTL_STATE_GAMEMODE;
notifyAdhocctlHandlers(ADHOCCTL_EVENT_GAME, 0);
}
}
else {
//adhocctlState = ADHOCCTL_STATE_CONNECTED;
@ -1521,17 +1537,16 @@ int friendFinder(){
it = gameModeMacs.begin() + 1;
gameModeMacs.insert(it, packet->mac);
}
// From JPCSP: Join complete when all the required MACs have joined
if (netAdhocGameModeEntered && requiredGameModeMacs.size() > 0 && gameModeMacs.size() == requiredGameModeMacs.size()) {
// TODO: Should we replace gameModeMacs contents with requiredGameModeMacs contents to make sure they are in the same order with macs from sceNetAdhocctlCreateEnterGameMode? But may not be consistent with the list on client side!
//gameModeMacs = requiredGameModeMacs;
notifyAdhocctlHandlers(ADHOCCTL_EVENT_GAME, 0);
}
}
else
WARN_LOG(SCENET, "GameMode Member [%s] Already Existed!", mac2str(&packet->mac).c_str());
// From JPCSP: Join complete when all the required MACs have joined
if (requiredGameModeMacs.size() > 0 && gameModeMacs.size() >= requiredGameModeMacs.size()) {
// TODO: Should we replace gameModeMacs contents with requiredGameModeMacs contents to make sure they are in the same order with macs from sceNetAdhocctlCreateEnterGameMode? But may not be consistent with the list on client side!
//gameModeMacs = requiredGameModeMacs;
//adhocctlState = ADHOCCTL_STATE_GAMEMODE;
notifyAdhocctlHandlers(ADHOCCTL_EVENT_GAME, 0);
}
}
// Update HUD User Count
@ -1572,13 +1587,14 @@ int friendFinder(){
// Log Incoming Peer Delete Request
INFO_LOG(SCENET, "FriendFinder: Incoming Peer Data Delete Request...");
/*if (adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE) {
if (adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE) {
auto peer = findFriendByIP(packet->ip);
gameModeMacs.erase(std::remove_if(gameModeMacs.begin(), gameModeMacs.end(),
[peer](SceNetEtherAddr const& e) {
return isMacMatch(&e, &peer->mac_addr);
}), gameModeMacs.end());
}*/
for (auto& gma : replicaGameModeAreas)
if (isMacMatch(&gma.mac, &peer->mac_addr)) {
gma.updateTimestamp = 0;
break;
}
}
// Delete User by IP, should delete by MAC since IP can be shared (behind NAT) isn't?
deleteFriendByIP(packet->ip);
@ -1633,7 +1649,8 @@ int friendFinder(){
// Set group parameters
// Since 0 is not a valid active channel we fake the channel for Automatic Channel (JPCSP use 11 as default). Ridge Racer 2 will ignore any groups with channel 0 or that doesn't matched with channel value returned from sceUtilityGetSystemParamInt (which mean sceUtilityGetSystemParamInt must not return channel 0 when connected to a network?)
group->channel = parameter.channel; //(parameter.channel == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC) ? defaultWlanChannel : parameter.channel;
group->mode = adhocctlCurrentMode;
// This Mode should be a valid mode (>=0), probably should be sent by AdhocServer since there are 2 possibilities (Normal and GameMode). Air Conflicts - Aces Of World War 2 (which use GameMode) seems to relies on this Mode value.
group->mode = std::max(ADHOCCTL_MODE_NORMAL, adhocctlCurrentMode); // default to ADHOCCTL_MODE_NORMAL
// Link into Group List
newnetworks = group;

View file

@ -114,9 +114,15 @@ inline bool isDisconnected(int errcode) { return (errcode == EPIPE || errcode ==
#define ADHOC_GAMEMODE_PORT 31000
#define GAMEMODE_UPDATE_INTERVAL 500 // 12000 usec on JPCSP, but lower value works better on BattleZone (in order to get full speed 60 FPS)
#define GAMEMODE_INIT_DELAY 10000
#define GAMEMODE_SYNC_TIMEOUT 250000
// GameMode Type
#define ADHOCCTL_GAMETYPE_1A 1
#define ADHOCCTL_GAMETYPE_1B 2
#define ADHOCCTL_GAMETYPE_2A 3
// psp strutcs and definitions
#define ADHOCCTL_MODE_NONE -1
#define ADHOCCTL_MODE_NONE -1 // We only use this internally as initial value before attempting to create/connect/join/scan any group
#define ADHOCCTL_MODE_NORMAL 0 // ADHOCCTL_MODE_ADHOC
#define ADHOCCTL_MODE_GAMEMODE 1
@ -141,7 +147,7 @@ inline bool isDisconnected(int errcode) { return (errcode == EPIPE || errcode ==
// ProductType ( extracted from SSID along with ProductId & GroupName, Pattern = "PSP_([AXS])(.........)_([LG])_(.*)" )
#define PSP_ADHOCCTL_TYPE_COMMERCIAL 0
#define PSP_ADHOCCTL_TYPE_DEBUG 1
#define PSP_ADHOCCTL_TYPE_SYSTEM 2
#define PSP_ADHOCCTL_TYPE_SYSTEM 2 // Used for GameSharing?
// Kernel Utility Netconf Adhoc Types
#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2
@ -321,6 +327,7 @@ typedef struct GameModeArea {
//int socket; // PDP socket?
u64 updateTimestamp;
int dataUpdated;
int dataSent;
SceNetEtherAddr mac;
u8* data; // upto "size" bytes started from "addr" ?
} PACK GameModeArea;
@ -393,8 +400,8 @@ typedef struct SceNetAdhocGameModeBufferStat {
// Adhoc ID (Game Product Key)
#define ADHOCCTL_ADHOCID_LEN 9
typedef struct SceNetAdhocctlAdhocId {
s32_le type;
uint8_t data[ADHOCCTL_ADHOCID_LEN];
s32_le type; // Air Conflicts - Aces Of World War 2 is using 2 for GameSharing?
uint8_t data[ADHOCCTL_ADHOCID_LEN]; // Air Conflicts - Aces Of World War 2 is using "000000001" for GameSharing?
uint8_t padding[3];
} PACK SceNetAdhocctlAdhocId; // should this be packed?
#ifdef _MSC_VER
@ -913,6 +920,7 @@ extern bool friendFinderRunning;
extern SceNetAdhocctlPeerInfo * friends;
extern SceNetAdhocctlScanInfo * networks;
extern u64 adhocctlStartTime;
extern bool isAdhocctlBusy;
extern int adhocctlState;
extern int adhocctlCurrentMode;
extern int adhocConnectionType;
@ -1025,7 +1033,7 @@ void changeBlockingMode(int fd, int nonblocking);
* Count Virtual Networks by analyzing the Friend List
* @return Number of Virtual Networks
*/
int countAvailableNetworks();
int countAvailableNetworks(const bool excludeSelf = false);
/*
* Find an existing group in networks

View file

@ -676,8 +676,6 @@ static u32 sceWlanGetEtherAddr(u32 addrAddr) {
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "illegal address");
}
// FIXME: Return 0x80410180 (pspnet[_core] error code?) when Adhocctl not connected to a group (ie. ADHOCCTL_STATE_DISCONNECTED)?
u8 *addr = Memory::GetPointer(addrAddr);
if (PPSSPP_ID > 1) {
Memory::Memset(addrAddr, PPSSPP_ID, 6);
@ -697,6 +695,10 @@ static u32 sceWlanGetEtherAddr(u32 addrAddr) {
}
static u32 sceNetGetLocalEtherAddr(u32 addrAddr) {
// FIXME: Return 0x80410180 (pspnet[_core] error code?) before successful attempt to Create/Connect/Join a Group? (ie. adhocctlCurrentMode == ADHOCCTL_MODE_NONE)
if (adhocctlCurrentMode == ADHOCCTL_MODE_NONE)
return hleLogDebug(SCENET, 0x80410180, "address not available?");
return sceWlanGetEtherAddr(addrAddr);
}

File diff suppressed because it is too large Load diff

View file

@ -98,6 +98,8 @@ int NetAdhoc_Term();
extern bool netAdhocInited;
extern bool netAdhocctlInited;
extern bool networkInited;
extern bool netAdhocGameModeEntered;
extern int netAdhocEnterGameModeTimeout;
extern int adhocDefaultTimeout; //3000000 usec
extern int adhocDefaultDelay; //10000
extern int adhocExtraDelay; //20000