Skip to content

Commit

Permalink
Merge pull request #13579 from ANR2ME/adhoc_fix
Browse files Browse the repository at this point in the history
Adhoc fix - Updating Adhocctl behavior after doing some small test
  • Loading branch information
hrydgard committed Oct 29, 2020
2 parents 36a6140 + 4eca124 commit a4a0b4b
Show file tree
Hide file tree
Showing 5 changed files with 616 additions and 329 deletions.
61 changes: 39 additions & 22 deletions Core/HLE/proAdhoc.cpp
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -315,15 +320,15 @@ void changeBlockingMode(int fd, int nonblocking) {
#endif
}

int countAvailableNetworks() {
int countAvailableNetworks(const bool excludeSelf) {
// Network Count
int count = 0;

// Group Reference
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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
18 changes: 13 additions & 5 deletions Core/HLE/proAdhoc.h
Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions Core/HLE/sceNet.cpp
Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down

0 comments on commit a4a0b4b

Please sign in to comment.