1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00
This commit is contained in:
RipleyTom 2020-03-04 14:55:35 +01:00 committed by GitHub
parent bb1b4bac9b
commit f1f5c91386
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 2198 additions and 788 deletions

View File

@ -351,6 +351,10 @@ target_sources(rpcs3_emu PRIVATE
Io/GHLtar.cpp
)
# Np
target_sources(rpcs3_emu PRIVATE
NP/np_handler.cpp
)
# Memory
target_sources(rpcs3_emu PRIVATE

View File

@ -2,12 +2,18 @@
#include "Emu/system_config.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/lv2/sys_sync.h"
#include "cellGame.h"
#include "cellSysutil.h"
#include "cellNetCtl.h"
#include "Utilities/StrUtil.h"
#include "Emu/IdManager.h"
#include "Emu/NP/np_handler.h"
#include <thread>
LOG_CHANNEL(cellNetCtl);
@ -90,14 +96,14 @@ error_code cellNetCtlInit()
{
cellNetCtl.warning("cellNetCtlInit()");
auto net_ctl_manager = g_fxo->get<cell_net_ctl_manager>();
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (net_ctl_manager->is_initialized)
if (nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_TERMINATED;
}
net_ctl_manager->is_initialized = true;
nph->is_netctl_init = true;
return CELL_OK;
}
@ -106,15 +112,17 @@ void cellNetCtlTerm()
{
cellNetCtl.warning("cellNetCtlTerm()");
auto net_ctl_manager = g_fxo->get<cell_net_ctl_manager>();
net_ctl_manager->is_initialized = false;
const auto nph = g_fxo->get<named_thread<np_handler>>();
nph->is_netctl_init = false;
}
error_code cellNetCtlGetState(vm::ptr<s32> state)
{
cellNetCtl.trace("cellNetCtlGetState(state=*0x%x)", state);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -124,7 +132,8 @@ error_code cellNetCtlGetState(vm::ptr<s32> state)
return CELL_NET_CTL_ERROR_INVALID_ADDR;
}
*state = g_cfg.net.net_status;
*state = nph->get_net_status();
return CELL_OK;
}
@ -132,7 +141,9 @@ error_code cellNetCtlAddHandler(vm::ptr<cellNetCtlHandler> handler, vm::ptr<void
{
cellNetCtl.todo("cellNetCtlAddHandler(handler=*0x%x, arg=*0x%x, hid=*0x%x)", handler, arg, hid);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -149,7 +160,9 @@ error_code cellNetCtlDelHandler(s32 hid)
{
cellNetCtl.todo("cellNetCtlDelHandler(hid=0x%x)", hid);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -166,7 +179,9 @@ error_code cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info)
{
cellNetCtl.todo("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -183,7 +198,7 @@ error_code cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info)
return CELL_OK;
}
if (g_cfg.net.net_status == CELL_NET_CTL_STATE_Disconnected)
if (nph->get_net_status() == CELL_NET_CTL_STATE_Disconnected)
{
return CELL_NET_CTL_ERROR_NOT_CONNECTED;
}
@ -198,15 +213,7 @@ error_code cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info)
}
else if (code == CELL_NET_CTL_INFO_IP_ADDRESS)
{
if (g_cfg.net.net_status != CELL_NET_CTL_STATE_IPObtained)
{
// 0.0.0.0 seems to be the default address when no ethernet cables are connected to the PS3
strcpy_trunc(info->ip_address, "0.0.0.0");
}
else
{
strcpy_trunc(info->ip_address, g_cfg.net.ip_address);
}
strcpy_trunc(info->ip_address, nph->get_ip());
}
else if (code == CELL_NET_CTL_INFO_NETMASK)
{
@ -224,7 +231,9 @@ error_code cellNetCtlNetStartDialogLoadAsync(vm::cptr<CellNetCtlNetStartDialogPa
{
cellNetCtl.error("cellNetCtlNetStartDialogLoadAsync(param=*0x%x)", param);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -244,10 +253,17 @@ error_code cellNetCtlNetStartDialogLoadAsync(vm::cptr<CellNetCtlNetStartDialogPa
return CELL_NET_CTL_ERROR_INVALID_SIZE;
}
// TODO: Actually sign into PSN or an emulated network similar to PSN (ESN)
// TODO: Properly open the dialog prompt for sign in
sysutil_send_system_cmd(CELL_SYSUTIL_NET_CTL_NETSTART_LOADED, 0);
sysutil_send_system_cmd(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0);
// This is a hack for Diva F 2nd that registers the sysutil callback after calling this function.
g_fxo->init<named_thread>("Delayed cellNetCtlNetStartDialogLoadAsync messages", []()
{
lv2_obj::wait_timeout(500000, nullptr);
if (thread_ctrl::state() != thread_state::aborting)
{
sysutil_send_system_cmd(CELL_SYSUTIL_NET_CTL_NETSTART_LOADED, 0);
sysutil_send_system_cmd(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0);
}
});
return CELL_OK;
}
@ -256,7 +272,9 @@ error_code cellNetCtlNetStartDialogAbortAsync()
{
cellNetCtl.error("cellNetCtlNetStartDialogAbortAsync()");
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -268,7 +286,9 @@ error_code cellNetCtlNetStartDialogUnloadAsync(vm::ptr<CellNetCtlNetStartDialogR
{
cellNetCtl.warning("cellNetCtlNetStartDialogUnloadAsync(result=*0x%x)", result);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}
@ -283,15 +303,7 @@ error_code cellNetCtlNetStartDialogUnloadAsync(vm::ptr<CellNetCtlNetStartDialogR
return CELL_NET_CTL_ERROR_INVALID_SIZE;
}
if (g_cfg.net.net_status == CELL_NET_CTL_STATE_Disconnected)
{
result->result = CELL_NET_CTL_ERROR_NET_NOT_CONNECTED;
}
else
{
// Hack
result->result = CELL_NET_CTL_ERROR_DIALOG_CANCELED;
}
result->result = nph->get_net_status() == CELL_NET_CTL_STATE_IPObtained ? 0 : CELL_NET_CTL_ERROR_DIALOG_CANCELED;
sysutil_send_system_cmd(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0);
@ -302,7 +314,9 @@ error_code cellNetCtlGetNatInfo(vm::ptr<CellNetCtlNatInfo> natInfo)
{
cellNetCtl.warning("cellNetCtlGetNatInfo(natInfo=*0x%x)", natInfo);
if (!g_fxo->get<cell_net_ctl_manager>()->is_initialized)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (!nph->is_netctl_init)
{
return CELL_NET_CTL_ERROR_NOT_INITIALIZED;
}

View File

@ -352,8 +352,3 @@ struct CellGameUpdateParam
using CellGameUpdateCallback = void(s32 status, s32 error_code, vm::ptr<void> userdata);
using CellGameUpdateCallbackEx = void(vm::ptr<CellGameUpdateResult> result, vm::ptr<void> userdata);
struct cell_net_ctl_manager
{
atomic_t<bool> is_initialized = false;
};

File diff suppressed because it is too large Load Diff

View File

@ -9,14 +9,14 @@
error_code sceNpInit(u32 poolsize, vm::ptr<void> poolptr);
error_code sceNpTerm();
using in_addr_t = u32;
using in_port_t = u16;
using sa_family_t = u8;
using socklen_t = u32;
using np_in_addr_t = u32;
using np_in_port_t = u16;
using np_sa_family_t = u8;
using np_socklen_t = u32;
struct in_addr
struct np_in_addr
{
in_addr_t s_addr; // TODO: alignment?
np_in_addr_t np_s_addr; // TODO: alignment?
};
using sys_memory_container_t = u32;
@ -1121,8 +1121,8 @@ union SceNpSignalingConnectionInfo
SceNpId npId;
struct
{
be_t<u32> addr; // in_addr
be_t<u16> port; // in_port_t
np_in_addr addr; // in_addr
np_in_port_t port; // in_port_t
} address;
be_t<u32> packet_loss;
};
@ -1298,22 +1298,3 @@ using SceNpMatchingGUIHandler = void(u32 ctx_id, s32 event, s32 error_code, vm::
using SceNpProfileResultHandler = s32(s32 result, vm::ptr<void> arg);
using SceNpManagerSubSigninCallback = void(s32 result, vm::ptr<SceNpId> npId, vm::ptr<void> cb_arg);
// fxm objects
struct sce_np_manager
{
std::atomic<bool> is_initialized = false;
};
struct sce_np_lookup_manager
{
std::atomic<bool> is_initialized = false;
};
struct sce_np_score_manager
{
std::atomic<bool> is_initialized = false;
};
extern s32 g_psn_connection_status;

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,8 @@
#include <atomic>
extern logs::channel sceNp2;
// Error codes
enum SceNpMatching2Error : u32
{
@ -485,6 +487,7 @@ typedef u8 SceNpMatching2Operator;
typedef u8 SceNpMatching2CastType;
typedef u8 SceNpMatching2SessionType;
typedef u8 SceNpMatching2SignalingType;
typedef u8 SceNpMatching2SignalingFlag;
typedef u8 SceNpMatching2EventCause;
typedef u8 SceNpMatching2ServerStatus;
typedef u8 SceNpMatching2Role;
@ -537,7 +540,7 @@ struct SceNpMatching2BinAttr
{
be_t<SceNpMatching2AttributeId> id;
u8 padding[2];
be_t<u32> ptr;
vm::bptr<u8> ptr;
be_t<u32> size;
};
@ -587,9 +590,9 @@ struct SceNpMatching2JoinedSessionInfo
// User information
struct SceNpMatching2UserInfo
{
vm::ptr<SceNpMatching2UserInfo> next;
vm::bptr<SceNpMatching2UserInfo> next;
SceNpUserInfo2 userInfo;
vm::ptr<SceNpMatching2BinAttr> userBinAttr;
vm::bptr<SceNpMatching2BinAttr> userBinAttr;
be_t<u32> userBinAttrNum;
SceNpMatching2JoinedSessionInfo joinedSessionInfo;
be_t<u32> joinedSessionInfoNum;
@ -628,15 +631,15 @@ struct SceNpMatching2LobbyMemberBinAttrInternal
// Lobby-internal lobby member information
struct SceNpMatching2LobbyMemberDataInternal
{
vm::ptr<SceNpMatching2LobbyMemberDataInternal> next;
vm::bptr<SceNpMatching2LobbyMemberDataInternal> next;
SceNpUserInfo2 userInfo;
CellRtcTick joinDate;
be_t<SceNpMatching2LobbyMemberId> memberId;
u8 padding[2];
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2JoinedSessionInfo> joinedSessionInfo;
vm::bptr<SceNpMatching2JoinedSessionInfo> joinedSessionInfo;
be_t<u32> joinedSessionInfoNum;
vm::ptr<SceNpMatching2LobbyMemberBinAttrInternal> lobbyMemberBinAttrInternal;
vm::bptr<SceNpMatching2LobbyMemberBinAttrInternal> lobbyMemberBinAttrInternal;
be_t<u32> lobbyMemberBinAttrInternalNum; // Unsigned ints are be_t<u32> not uint, right?
};
@ -661,7 +664,7 @@ struct SceNpMatching2LobbyBinAttrInternal
// Lobby-external lobby information
struct SceNpMatching2LobbyDataExternal
{
vm::ptr<SceNpMatching2LobbyDataExternal> next;
vm::bptr<SceNpMatching2LobbyDataExternal> next;
be_t<SceNpMatching2ServerId> serverId;
u8 padding1[2];
be_t<SceNpMatching2WorldId> worldId;
@ -670,11 +673,11 @@ struct SceNpMatching2LobbyDataExternal
be_t<u32> maxSlot;
be_t<u32> curMemberNum;
be_t<u32> flagAttr;
vm::ptr<SceNpMatching2IntAttr> lobbySearchableIntAttrExternal;
vm::bptr<SceNpMatching2IntAttr> lobbySearchableIntAttrExternal;
be_t<u32> lobbySearchableIntAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> lobbySearchableBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> lobbySearchableBinAttrExternal;
be_t<u32> lobbySearchableBinAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> lobbyBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> lobbyBinAttrExternal;
be_t<u32> lobbyBinAttrExternalNum;
u8 padding3[4];
};
@ -689,7 +692,7 @@ struct SceNpMatching2LobbyDataInternal
be_t<u32> maxSlot;
SceNpMatching2LobbyMemberIdList memberIdList;
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2LobbyBinAttrInternal> lobbyBinAttrInternal;
vm::bptr<SceNpMatching2LobbyBinAttrInternal> lobbyBinAttrInternal;
be_t<u32> lobbyBinAttrInternalNum;
};
@ -752,7 +755,7 @@ struct SceNpMatching2RoomMemberBinAttrInternal
// External room member data
struct SceNpMatching2RoomMemberDataExternal
{
vm::ptr<SceNpMatching2RoomMemberDataExternal> next;
vm::bptr<SceNpMatching2RoomMemberDataExternal> next;
SceNpUserInfo2 userInfo;
CellRtcTick joinDate;
SceNpMatching2Role role;
@ -762,27 +765,27 @@ struct SceNpMatching2RoomMemberDataExternal
// Internal room member data
struct SceNpMatching2RoomMemberDataInternal
{
vm::ptr<SceNpMatching2RoomMemberDataInternal> next;
vm::bptr<SceNpMatching2RoomMemberDataInternal> next;
SceNpUserInfo2 userInfo;
CellRtcTick joinDate;
be_t<SceNpMatching2RoomMemberId> memberId;
SceNpMatching2TeamId teamId;
u8 padding1[1];
vm::ptr<SceNpMatching2RoomGroup> roomGroup;
vm::bptr<SceNpMatching2RoomGroup> roomGroup;
SceNpMatching2NatType natType;
u8 padding2[3];
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2RoomMemberBinAttrInternal> roomMemberBinAttrInternal;
vm::bptr<SceNpMatching2RoomMemberBinAttrInternal> roomMemberBinAttrInternal;
be_t<u32> roomMemberBinAttrInternalNum;
};
// Internal room member data list
struct SceNpMatching2RoomMemberDataInternalList
{
vm::ptr<SceNpMatching2RoomMemberDataInternal> members;
vm::bptr<SceNpMatching2RoomMemberDataInternal> members;
be_t<u32> membersNum;
vm::ptr<SceNpMatching2RoomMemberDataInternal> me;
vm::ptr<SceNpMatching2RoomMemberDataInternal> owner;
vm::bptr<SceNpMatching2RoomMemberDataInternal> me;
vm::bptr<SceNpMatching2RoomMemberDataInternal> owner;
};
// Internal room binary attribute
@ -797,7 +800,7 @@ struct SceNpMatching2RoomBinAttrInternal
// External room data
struct SceNpMatching2RoomDataExternal
{
vm::ptr<SceNpMatching2RoomDataExternal> next;
vm::bptr<SceNpMatching2RoomDataExternal> next;
be_t<SceNpMatching2ServerId> serverId;
u8 padding1[2];
be_t<SceNpMatching2WorldId> worldId;
@ -810,15 +813,15 @@ struct SceNpMatching2RoomDataExternal
be_t<u16> openPrivateSlotNum;
be_t<u16> curMemberNum;
be_t<SceNpMatching2RoomPasswordSlotMask> passwordSlotMask;
vm::ptr<SceNpUserInfo2> owner;
vm::ptr<SceNpMatching2RoomGroup> roomGroup;
vm::bptr<SceNpUserInfo2> owner;
vm::bptr<SceNpMatching2RoomGroup> roomGroup;
be_t<u32> roomGroupNum;
be_t<u32> flagAttr;
vm::ptr<SceNpMatching2IntAttr> roomSearchableIntAttrExternal;
vm::bptr<SceNpMatching2IntAttr> roomSearchableIntAttrExternal;
be_t<u32> roomSearchableIntAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> roomSearchableBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> roomSearchableBinAttrExternal;
be_t<u32> roomSearchableBinAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> roomBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> roomBinAttrExternal;
be_t<u32> roomBinAttrExternalNum;
};
@ -833,10 +836,10 @@ struct SceNpMatching2RoomDataInternal
be_t<SceNpMatching2RoomPasswordSlotMask> passwordSlotMask;
be_t<u32> maxSlot;
SceNpMatching2RoomMemberDataInternalList memberList;
vm::ptr<SceNpMatching2RoomGroup> roomGroup;
vm::bptr<SceNpMatching2RoomGroup> roomGroup;
be_t<u32> roomGroupNum;
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2RoomBinAttrInternal> roomBinAttrInternal;
vm::bptr<SceNpMatching2RoomBinAttrInternal> roomBinAttrInternal;
be_t<u32> roomBinAttrInternalNum;
};
@ -857,9 +860,9 @@ union SceNpMatching2RoomMessageDestination
// Invitation data
struct SceNpMatching2InvitationData
{
vm::ptr<SceNpMatching2JoinedSessionInfo> targetSession;
vm::bptr<SceNpMatching2JoinedSessionInfo> targetSession;
be_t<u32> targetSessionNum;
vm::ptr<void> optData;
vm::bptr<void> optData;
be_t<u32> optDataLen;
};
@ -867,7 +870,7 @@ struct SceNpMatching2InvitationData
struct SceNpMatching2SignalingOptParam
{
SceNpMatching2SignalingType type;
u8 reserved1[1];
SceNpMatching2SignalingFlag flag;
be_t<SceNpMatching2RoomMemberId> hubMemberId;
u8 reserved2[4];
};
@ -875,8 +878,8 @@ struct SceNpMatching2SignalingOptParam
// Option parameters for requests
struct SceNpMatching2RequestOptParam
{
SceNpMatching2RequestCallback cbFunc;
vm::ptr<void> cbFuncArg;
vm::bptr<SceNpMatching2RequestCallback> cbFunc;
vm::bptr<void> cbFuncArg;
be_t<u32> timeout;
be_t<u16> appReqId;
u8 padding[2];
@ -927,7 +930,7 @@ struct SceNpMatching2GetWorldInfoListRequest
// World data list request response data
struct SceNpMatching2GetWorldInfoListResponse
{
vm::ptr<SceNpMatching2World> world;
vm::bptr<SceNpMatching2World> world;
be_t<u32> worldNum;
};
@ -936,7 +939,7 @@ struct SceNpMatching2SetUserInfoRequest
{
be_t<SceNpMatching2ServerId> serverId;
u8 padding[2];
vm::ptr<SceNpMatching2BinAttr> userBinAttr;
vm::bptr<SceNpMatching2BinAttr> userBinAttr;
be_t<u32> userBinAttrNum;
};
@ -945,7 +948,7 @@ struct SceNpMatching2GetUserInfoListRequest
{
be_t<SceNpMatching2ServerId> serverId;
u8 padding[2];
vm::ptr<SceNpId> npId;
vm::bptr<SceNpId> npId;
be_t<u32> npIdNum;
vm::bptr<SceNpMatching2AttributeId> attrId;
be_t<u32> attrIdNum;
@ -955,7 +958,7 @@ struct SceNpMatching2GetUserInfoListRequest
// User information list acquisition response data
struct SceNpMatching2GetUserInfoListResponse
{
vm::ptr<SceNpMatching2UserInfo> userInfo;
vm::bptr<SceNpMatching2UserInfo> userInfo;
be_t<u32> userInfoNum;
};
@ -968,7 +971,7 @@ struct SceNpMatching2GetRoomMemberDataExternalListRequest
// External room member data list request response data
struct SceNpMatching2GetRoomMemberDataExternalListResponse
{
vm::ptr<SceNpMatching2RoomMemberDataExternal> roomMemberDataExternal;
vm::bptr<SceNpMatching2RoomMemberDataExternal> roomMemberDataExternal;
be_t<u32> roomMemberDataExternalNum;
};
@ -976,11 +979,11 @@ struct SceNpMatching2GetRoomMemberDataExternalListResponse
struct SceNpMatching2SetRoomDataExternalRequest
{
be_t<SceNpMatching2RoomId> roomId;
vm::ptr<SceNpMatching2IntAttr> roomSearchableIntAttrExternal;
vm::bptr<SceNpMatching2IntAttr> roomSearchableIntAttrExternal;
be_t<u32> roomSearchableIntAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> roomSearchableBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> roomSearchableBinAttrExternal;
be_t<u32> roomSearchableBinAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> roomBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> roomBinAttrExternal;
be_t<u32> roomBinAttrExternalNum;
};
@ -996,7 +999,7 @@ struct SceNpMatching2GetRoomDataExternalListRequest
// External room data list request response data
struct SceNpMatching2GetRoomDataExternalListResponse
{
vm::ptr<SceNpMatching2RoomDataExternal> roomDataExternal;
vm::bptr<SceNpMatching2RoomDataExternal> roomDataExternal;
be_t<u32> roomDataExternalNum;
};
@ -1008,44 +1011,44 @@ struct SceNpMatching2CreateJoinRoomRequest
be_t<SceNpMatching2LobbyId> lobbyId;
be_t<u32> maxSlot;
be_t<u32> flagAttr;
vm::ptr<SceNpMatching2BinAttr> roomBinAttrInternal;
vm::bptr<SceNpMatching2BinAttr> roomBinAttrInternal;
be_t<u32> roomBinAttrInternalNum;
vm::ptr<SceNpMatching2IntAttr> roomSearchableIntAttrExternal;
vm::bptr<SceNpMatching2IntAttr> roomSearchableIntAttrExternal;
be_t<u32> roomSearchableIntAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> roomSearchableBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> roomSearchableBinAttrExternal;
be_t<u32> roomSearchableBinAttrExternalNum;
vm::ptr<SceNpMatching2BinAttr> roomBinAttrExternal;
vm::bptr<SceNpMatching2BinAttr> roomBinAttrExternal;
be_t<u32> roomBinAttrExternalNum;
vm::ptr<SceNpMatching2SessionPassword> roomPassword;
vm::ptr<SceNpMatching2RoomGroupConfig> groupConfig;
vm::bptr<SceNpMatching2SessionPassword> roomPassword;
vm::bptr<SceNpMatching2RoomGroupConfig> groupConfig;
be_t<u32> groupConfigNum;
vm::bptr<SceNpMatching2RoomPasswordSlotMask> passwordSlotMask;
vm::ptr<SceNpId> allowedUser;
vm::bptr<SceNpId> allowedUser;
be_t<u32> allowedUserNum;
vm::ptr<SceNpId> blockedUser;
vm::bptr<SceNpId> blockedUser;
be_t<u32> blockedUserNum;
vm::ptr<SceNpMatching2GroupLabel> joinRoomGroupLabel;
vm::ptr<SceNpMatching2BinAttr> roomMemberBinAttrInternal;
vm::bptr<SceNpMatching2GroupLabel> joinRoomGroupLabel;
vm::bptr<SceNpMatching2BinAttr> roomMemberBinAttrInternal;
be_t<u32> roomMemberBinAttrInternalNum;
SceNpMatching2TeamId teamId;
u8 padding2[3];
SceNpMatching2SignalingOptParam sigOptParam;
vm::bptr<SceNpMatching2SignalingOptParam> sigOptParam;
u8 padding3[4];
};
// Create-and-join room request response data
struct SceNpMatching2CreateJoinRoomResponse
{
vm::ptr<SceNpMatching2RoomDataInternal> roomDataInternal;
vm::bptr<SceNpMatching2RoomDataInternal> roomDataInternal;
};
// Join room request parameters
struct SceNpMatching2JoinRoomRequest
{
be_t<SceNpMatching2RoomId> roomId;
vm::ptr<SceNpMatching2SessionPassword> roomPassword;
vm::ptr<SceNpMatching2GroupLabel> joinRoomGroupLabel;
vm::ptr<SceNpMatching2BinAttr> roomMemberBinAttrInternal;
vm::bptr<SceNpMatching2SessionPassword> roomPassword;
vm::bptr<SceNpMatching2GroupLabel> joinRoomGroupLabel;
vm::bptr<SceNpMatching2BinAttr> roomMemberBinAttrInternal;
be_t<u32> roomMemberBinAttrInternalNum;
SceNpMatching2PresenceOptionData optData;
SceNpMatching2TeamId teamId;
@ -1055,7 +1058,7 @@ struct SceNpMatching2JoinRoomRequest
// Join room request response data
struct SceNpMatching2JoinRoomResponse
{
vm::ptr<SceNpMatching2RoomDataInternal> roomDataInternal;
vm::bptr<SceNpMatching2RoomDataInternal> roomDataInternal;
};
// Leave room request parameters
@ -1094,9 +1097,9 @@ struct SceNpMatching2SearchRoomRequest
SceNpMatching2RangeFilter rangeFilter;
be_t<SceNpMatching2FlagAttr> flagFilter;
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2IntSearchFilter> intFilter;
vm::bptr<SceNpMatching2IntSearchFilter> intFilter;
be_t<u32> intFilterNum;
vm::ptr<SceNpMatching2BinSearchFilter> binFilter;
vm::bptr<SceNpMatching2BinSearchFilter> binFilter;
be_t<u32> binFilterNum;
vm::bptr<SceNpMatching2AttributeId> attrId;
be_t<u32> attrIdNum;
@ -1106,7 +1109,7 @@ struct SceNpMatching2SearchRoomRequest
struct SceNpMatching2SearchRoomResponse
{
SceNpMatching2Range range;
vm::ptr<SceNpMatching2RoomDataExternal> roomDataExternal;
vm::bptr<SceNpMatching2RoomDataExternal> roomDataExternal;
};
// Room message send request parameters
@ -1145,9 +1148,9 @@ struct SceNpMatching2SetRoomDataInternalRequest
be_t<SceNpMatching2RoomId> roomId;
be_t<SceNpMatching2FlagAttr> flagFilter;
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2BinAttr> roomBinAttrInternal;
vm::bptr<SceNpMatching2BinAttr> roomBinAttrInternal;
be_t<u32> roomBinAttrInternalNum;
vm::ptr<SceNpMatching2RoomGroupPasswordConfig> passwordConfig;
vm::bptr<SceNpMatching2RoomGroupPasswordConfig> passwordConfig;
be_t<u32> passwordConfigNum;
vm::bptr<SceNpMatching2RoomPasswordSlotMask> passwordSlotMask;
vm::bptr<SceNpMatching2RoomMemberId> ownerPrivilegeRank;
@ -1166,7 +1169,7 @@ struct SceNpMatching2GetRoomDataInternalRequest
// Internal room data request response data
struct SceNpMatching2GetRoomDataInternalResponse
{
vm::ptr<SceNpMatching2RoomDataInternal> roomDataInternal;
vm::bptr<SceNpMatching2RoomDataInternal> roomDataInternal;
};
// Internal room member data configuration request parameters
@ -1178,7 +1181,7 @@ struct SceNpMatching2SetRoomMemberDataInternalRequest
u8 padding[5];
be_t<SceNpMatching2FlagAttr> flagFilter;
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2BinAttr> roomMemberBinAttrInternal;
vm::bptr<SceNpMatching2BinAttr> roomMemberBinAttrInternal;
be_t<u32> roomMemberBinAttrInternalNum;
};
@ -1195,7 +1198,7 @@ struct SceNpMatching2GetRoomMemberDataInternalRequest
// Internal room member data request response data
struct SceNpMatching2GetRoomMemberDataInternalResponse
{
vm::ptr<SceNpMatching2RoomMemberDataInternal> roomMemberDataInternal;
vm::bptr<SceNpMatching2RoomMemberDataInternal> roomMemberDataInternal;
};
// Signaling option parameter setting request parameter
@ -1218,16 +1221,16 @@ struct SceNpMatching2GetLobbyInfoListRequest
struct SceNpMatching2GetLobbyInfoListResponse
{
SceNpMatching2Range range;
vm::ptr<SceNpMatching2LobbyDataExternal> lobbyDataExternal;
vm::bptr<SceNpMatching2LobbyDataExternal> lobbyDataExternal;
};
// Lobby joining request parameter
struct SceNpMatching2JoinLobbyRequest
{
be_t<SceNpMatching2LobbyId> lobbyId;
vm::ptr<SceNpMatching2JoinedSessionInfo> joinedSessionInfo;
vm::bptr<SceNpMatching2JoinedSessionInfo> joinedSessionInfo;
be_t<u32> joinedSessionInfoNum;
vm::ptr<SceNpMatching2BinAttr> lobbyMemberBinAttrInternal;
vm::bptr<SceNpMatching2BinAttr> lobbyMemberBinAttrInternal;
be_t<u32> lobbyMemberBinAttrInternalNum;
SceNpMatching2PresenceOptionData optData;
u8 padding[4];
@ -1236,7 +1239,7 @@ struct SceNpMatching2JoinLobbyRequest
// Lobby joining response data
struct SceNpMatching2JoinLobbyResponse
{
vm::ptr<SceNpMatching2LobbyDataInternal> lobbyDataInternal;
vm::bptr<SceNpMatching2LobbyDataInternal> lobbyDataInternal;
};
// Lobby leaving request parameter
@ -1284,9 +1287,9 @@ struct SceNpMatching2SetLobbyMemberDataInternalRequest
u8 padding1[2];
be_t<SceNpMatching2FlagAttr> flagFilter;
be_t<SceNpMatching2FlagAttr> flagAttr;
vm::ptr<SceNpMatching2JoinedSessionInfo> joinedSessionInfo;
vm::bptr<SceNpMatching2JoinedSessionInfo> joinedSessionInfo;
be_t<u32> joinedSessionInfoNum;
vm::ptr<SceNpMatching2BinAttr> lobbyMemberBinAttrInternal;
vm::bptr<SceNpMatching2BinAttr> lobbyMemberBinAttrInternal;
be_t<u32> lobbyMemberBinAttrInternalNum;
u8 padding2[4];
};
@ -1304,7 +1307,7 @@ struct SceNpMatching2GetLobbyMemberDataInternalRequest
// Lobby-internal lobby member information acquisition response data
struct SceNpMatching2GetLobbyMemberDataInternalResponse
{
vm::ptr<SceNpMatching2LobbyMemberDataInternal> lobbyMemberDataInternal;
vm::bptr<SceNpMatching2LobbyMemberDataInternal> lobbyMemberDataInternal;
};
// Request parameters for obtaining a list of lobby-internal lobby member information
@ -1322,7 +1325,7 @@ struct SceNpMatching2GetLobbyMemberDataInternalListRequest
// Reponse data for obtaining a list of lobby-internal lobby member information
struct SceNpMatching2GetLobbyMemberDataInternalListResponse
{
vm::ptr<SceNpMatching2LobbyMemberDataInternal> lobbyMemberDataInternal;
vm::bptr<SceNpMatching2LobbyMemberDataInternal> lobbyMemberDataInternal;
be_t<u32> lobbyMemberDataInternalNum;
};
@ -1348,14 +1351,14 @@ struct SceNpMatching2SignalingGetPingInfoResponse
struct SceNpMatching2JoinProhibitiveRoomRequest
{
SceNpMatching2JoinRoomRequest joinParam;
vm::ptr<SceNpId> blockedUser;
vm::bptr<SceNpId> blockedUser;
be_t<u32> blockedUserNum;
};
// Room member update information
struct SceNpMatching2RoomMemberUpdateInfo
{
vm::ptr<SceNpMatching2RoomMemberDataInternal> roomMemberDataInternal;
vm::bptr<SceNpMatching2RoomMemberDataInternal> roomMemberDataInternal;
SceNpMatching2EventCause eventCause;
u8 padding[3];
SceNpMatching2PresenceOptionData optData;
@ -1368,7 +1371,7 @@ struct SceNpMatching2RoomOwnerUpdateInfo
be_t<SceNpMatching2RoomMemberId> newOwner;
SceNpMatching2EventCause eventCause;
u8 padding[3];
vm::ptr<SceNpMatching2SessionPassword> roomPassword;
vm::bptr<SceNpMatching2SessionPassword> roomPassword;
SceNpMatching2PresenceOptionData optData;
};
@ -1384,7 +1387,7 @@ struct SceNpMatching2RoomUpdateInfo
// Internal room data update information
struct SceNpMatching2RoomDataInternalUpdateInfo
{
vm::ptr<SceNpMatching2RoomDataInternal> newRoomDataInternal;
vm::bptr<SceNpMatching2RoomDataInternal> newRoomDataInternal;
vm::bptr<SceNpMatching2FlagAttr> newFlagAttr;
vm::bptr<SceNpMatching2FlagAttr> prevFlagAttr;
vm::bptr<SceNpMatching2RoomPasswordSlotMask> newRoomPasswordSlotMask;
@ -1398,7 +1401,7 @@ struct SceNpMatching2RoomDataInternalUpdateInfo
// Internal room member data update information
struct SceNpMatching2RoomMemberDataInternalUpdateInfo
{
vm::ptr<SceNpMatching2RoomMemberDataInternal> newRoomMemberDataInternal;
vm::bptr<SceNpMatching2RoomMemberDataInternal> newRoomMemberDataInternal;
vm::bptr<SceNpMatching2FlagAttr> newFlagAttr;
vm::bptr<SceNpMatching2FlagAttr> prevFlagAttr;
vm::bptr<SceNpMatching2TeamId> newTeamId;
@ -1412,8 +1415,8 @@ struct SceNpMatching2RoomMessageInfo
b8 filtered;
SceNpMatching2CastType castType;
u8 padding[2];
vm::ptr<SceNpMatching2RoomMessageDestination> dst;
vm::ptr<SceNpUserInfo2> srcMember;
vm::bptr<SceNpMatching2RoomMessageDestination> dst;
vm::bptr<SceNpUserInfo2> srcMember;
vm::cptr<void> msg;
be_t<u32> msgLen;
};
@ -1421,7 +1424,7 @@ struct SceNpMatching2RoomMessageInfo
// Lobby member update information
struct SceNpMatching2LobbyMemberUpdateInfo
{
vm::ptr<SceNpMatching2LobbyMemberDataInternal> lobbyMemberDataInternal;
vm::bptr<SceNpMatching2LobbyMemberDataInternal> lobbyMemberDataInternal;
SceNpMatching2EventCause eventCause;
u8 padding[3];
SceNpMatching2PresenceOptionData optData;
@ -1445,7 +1448,7 @@ struct SceNpMatching2LobbyMemberDataInternalUpdateInfo
be_t<SceNpMatching2FlagAttr> newFlagAttr;
SceNpMatching2JoinedSessionInfo newJoinedSessionInfo;
be_t<u32> newJoinedSessionInfoNum;
vm::ptr<SceNpMatching2LobbyMemberBinAttrInternal> newLobbyMemberBinAttrInternal;
vm::bptr<SceNpMatching2LobbyMemberBinAttrInternal> newLobbyMemberBinAttrInternal;
be_t<u32> newLobbyMemberBinAttrInternalNum;
};
@ -1455,8 +1458,8 @@ struct SceNpMatching2LobbyMessageInfo
b8 filtered;
SceNpMatching2CastType castType;
u8 padding[2];
vm::ptr<SceNpMatching2LobbyMessageDestination> dst;
vm::ptr<SceNpUserInfo2> srcMember;
vm::bptr<SceNpMatching2LobbyMessageDestination> dst;
vm::bptr<SceNpUserInfo2> srcMember;
vm::cptr<void> msg;
be_t<u32> msgLen;
};
@ -1466,8 +1469,8 @@ struct SceNpMatching2LobbyInvitationInfo
{
SceNpMatching2CastType castType;
u8 padding[3];
vm::ptr<SceNpMatching2LobbyMessageDestination> dst;
vm::ptr<SceNpUserInfo2> srcMember;
vm::bptr<SceNpMatching2LobbyMessageDestination> dst;
vm::bptr<SceNpUserInfo2> srcMember;
SceNpMatching2InvitationData invitationData;
};
@ -1579,20 +1582,3 @@ struct SceNpAuthGetAuthorizationCodeParameter
vm::bcptr<SceNpClientId> pClientId;
vm::bcptr<char> pScope;
};
// fxm objects
struct sce_np_2_manager
{
std::atomic<bool> is_initialized = false;
};
struct sce_np_2_matching_manager
{
std::atomic<bool> is_initialized = false;
};
struct sce_np_oauth_2_manager
{
std::atomic<bool> is_initialized = false;
};

View File

@ -4,6 +4,7 @@
#include "sceNpSns.h"
#include "sceNp.h"
#include "Emu/NP/np_handler.h"
LOG_CHANNEL(sceNpSns);
@ -182,7 +183,9 @@ error_code sceNpSnsFbGetAccessToken(u32 handle, vm::cptr<SceNpSnsFbAccessTokenPa
return SCE_NP_SNS_FB_ERROR_UNKNOWN_HANDLE;
}
if (g_psn_connection_status == SCE_NP_MANAGER_STATUS_OFFLINE)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (nph->get_psn_status() == SCE_NP_MANAGER_STATUS_OFFLINE)
{
return not_an_error(SCE_NP_SNS_ERROR_NOT_SIGN_IN);
}
@ -307,7 +310,9 @@ error_code sceNpSnsFbGetLongAccessToken(u32 handle, vm::cptr<SceNpSnsFbAccessTok
return SCE_NP_SNS_FB_ERROR_UNKNOWN_HANDLE;
}
if (g_psn_connection_status == SCE_NP_MANAGER_STATUS_OFFLINE)
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (nph->get_psn_status() == SCE_NP_MANAGER_STATUS_OFFLINE)
{
return not_an_error(SCE_NP_SNS_ERROR_NOT_SIGN_IN);
}

View File

@ -23,6 +23,8 @@
#include <poll.h>
#endif
#include "Emu/NP/np_handler.h"
LOG_CHANNEL(sys_net);
template<>
@ -155,6 +157,7 @@ static sys_net_error get_last_error(bool is_blocking, int native_error = 0)
ERROR_CASE(EALREADY);
ERROR_CASE(ENOTCONN);
ERROR_CASE(ECONNRESET);
ERROR_CASE(EADDRINUSE);
default: sys_net.error("Unknown/illegal socket error: %d", native_error);
}
@ -335,8 +338,8 @@ struct network_thread
using network_context = named_thread<network_thread>;
lv2_socket::lv2_socket(lv2_socket::socket_type s)
: socket(s)
lv2_socket::lv2_socket(lv2_socket::socket_type s, s32 s_type)
: socket(s), type(s_type)
{
// Set non-blocking
#ifdef _WIN32
@ -454,7 +457,7 @@ error_code sys_net_bnet_accept(ppu_thread& ppu, s32 s, vm::ptr<sys_net_sockaddr>
return 0;
}
auto newsock = std::make_shared<lv2_socket>(native_socket);
auto newsock = std::make_shared<lv2_socket>(native_socket, 0);
result = idm::import_existing<lv2_socket>(newsock);
@ -491,7 +494,8 @@ error_code sys_net_bnet_bind(ppu_thread& ppu, s32 s, vm::cptr<sys_net_sockaddr>
sys_net.warning("sys_net_bnet_bind(s=%d, addr=*0x%x, addrlen=%u)", s, addr, addrlen);
if (addr->sa_family != SYS_NET_AF_INET)
// 0 presumably defaults to AF_INET(to check?)
if (addr->sa_family != SYS_NET_AF_INET && addr->sa_family != 0)
{
sys_net.error("sys_net_bnet_bind(s=%d): unsupported sa_family (%d)", s, addr->sa_family);
return -SYS_NET_EAFNOSUPPORT;
@ -507,6 +511,18 @@ error_code sys_net_bnet_bind(ppu_thread& ppu, s32 s, vm::cptr<sys_net_sockaddr>
const auto sock = idm::check<lv2_socket>(s, [&](lv2_socket& sock) -> sys_net_error
{
if (sock.type == SYS_NET_SOCK_DGRAM_P2P)
{
const u16 daport = reinterpret_cast<const sys_net_sockaddr_in*>(addr.get_ptr())->sin_port;
const u16 davport = reinterpret_cast<const sys_net_sockaddr_in_p2p*>(addr.get_ptr())->sin_vport;
sys_net.warning("Trying to bind %s:%d:%d", inet_ntoa(name.sin_addr), daport, davport);
name.sin_port = std::bit_cast<u16, be_t<u16>>(daport + davport); // htons(daport + davport)
}
else
{
sys_net.warning("Trying to bind %s:%d", inet_ntoa(name.sin_addr), std::bit_cast<be_t<u16>, u16>(name.sin_port)); // ntohs(name.sin_port)
}
std::lock_guard lock(sock.mutex);
if (::bind(sock.socket, reinterpret_cast<struct sockaddr*>(&name), namelen) == 0)
@ -545,21 +561,27 @@ error_code sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptr<sys_net_sockaddr
name.sin_addr.s_addr = std::bit_cast<u32>(psa_in->sin_addr);
::socklen_t namelen = sizeof(name);
sys_net.warning("Attempting to connect on %s:%d", inet_ntoa(name.sin_addr), std::bit_cast<be_t<u16>, u16>(name.sin_port)); // ntohs(name.sin_port)
const auto sock = idm::check<lv2_socket>(s, [&](lv2_socket& sock)
{
std::lock_guard lock(sock.mutex);
if (addr->sa_family == 0 && !psa_in->sin_port && !psa_in->sin_addr)
{
const auto nph = g_fxo->get<named_thread<np_handler>>();
// Hack for DNS (8.8.8.8:53)
name.sin_port = std::bit_cast<u16, be_t<u16>>(53);
name.sin_addr.s_addr = 0x08080808;
name.sin_addr.s_addr = nph->get_dns();
// Overwrite arg (probably used to validate recvfrom addr)
psa_in->sin_family = SYS_NET_AF_INET;
psa_in->sin_port = 53;
psa_in->sin_addr = 0x08080808;
sys_net.warning("sys_net_bnet_connect(s=%d): using DNS 8.8.8.8:53...");
psa_in->sin_addr = nph->get_dns();
sys_net.warning("sys_net_bnet_connect: using DNS...");
nph->add_dns_spy(s);
}
else if (addr->sa_family != SYS_NET_AF_INET)
{
@ -717,6 +739,17 @@ error_code sys_net_bnet_getpeername(ppu_thread& ppu, s32 s, vm::ptr<sys_net_sock
paddr->sin_port = std::bit_cast<be_t<u16>, u16>(reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_port);
paddr->sin_addr = std::bit_cast<be_t<u32>, u32>(reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_addr.s_addr);
paddr->sin_zero = 0;
if (sock.type == SYS_NET_SOCK_DGRAM_P2P)
{
vm::ptr<sys_net_sockaddr_in_p2p> paddr_p2p = vm::cast(addr.addr());
paddr_p2p->sin_vport = paddr_p2p->sin_port - 3658;
paddr_p2p->sin_port = 3658;
in_addr rep;
rep.s_addr = htonl(paddr->sin_addr);
sys_net.error("Reporting P2P socket address as %s:%d:%d", inet_ntoa(rep), paddr_p2p->sin_port, paddr_p2p->sin_vport);
}
return {};
}
@ -1037,16 +1070,54 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
native_flags |= MSG_WAITALL;
}
s32 type = 0;
const auto sock = idm::check<lv2_socket>(s, [&](lv2_socket& sock)
{
type = sock.type;
std::lock_guard lock(sock.mutex);
//if (!(sock.events & lv2_socket::poll::read))
{
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (nph->is_dns(s) && nph->is_dns_queue(s))
{
const auto packet = nph->get_dns_packet(s);
ASSERT(packet.size() < len);
memcpy(buf.get_ptr(), packet.data(), packet.size());
native_result = packet.size();
native_addr.ss_family = AF_INET;
(reinterpret_cast<::sockaddr_in*>(&native_addr))->sin_port = std::bit_cast<u16, be_t<u16>>(53); // htons(53)
(reinterpret_cast<::sockaddr_in*>(&native_addr))->sin_addr.s_addr = nph->get_dns();
return true;
}
native_result = ::recvfrom(sock.socket, reinterpret_cast<char*>(buf.get_ptr()), len, native_flags, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen);
if (native_result >= 0)
{
if (sys_net.enabled == logs::level::trace)
{
std::string datrace;
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
u8* dabuf = static_cast<u8 *>(buf.get_ptr());
for (s32 index = 0; index < native_result; index++)
{
if ((index % 16) == 0)
datrace += '\n';
datrace += hex[(dabuf[index] >> 4) & 15];
datrace += hex[(dabuf[index]) & 15];
datrace += ' ';
}
sys_net.trace("DNS RESULT: %s", datrace);
}
return true;
}
@ -1083,6 +1154,8 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
if (!sock)
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error recvfrom(bad socket)");
return -SYS_NET_EBADF;
}
@ -1093,6 +1166,9 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
return not_an_error(-result);
}
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error recvfrom(result early): %d", result);
return -result;
}
@ -1110,11 +1186,15 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
if (result)
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error recvfrom(result): %d", result);
return -result;
}
if (ppu.gpr[3] == static_cast<u64>(-SYS_NET_EINTR))
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error recvfrom(interrupted)");
return -SYS_NET_EINTR;
}
}
@ -1141,9 +1221,23 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
paddr->sin_port = std::bit_cast<be_t<u16>, u16>(reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_port);
paddr->sin_addr = std::bit_cast<be_t<u32>, u32>(reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_addr.s_addr);
paddr->sin_zero = 0;
if (type == SYS_NET_SOCK_DGRAM_P2P)
{
vm::ptr<sys_net_sockaddr_in_p2p> paddr_p2p = vm::cast(addr.addr());
paddr_p2p->sin_vport = paddr_p2p->sin_port - 3658;
paddr_p2p->sin_port = 3658;
const u16 daport = reinterpret_cast<sys_net_sockaddr_in*>(addr.get_ptr())->sin_port;
const u16 davport = reinterpret_cast<sys_net_sockaddr_in_p2p*>(addr.get_ptr())->sin_vport;
sys_net.error("Received a P2P packet from %s:%d:%d", inet_ntoa(reinterpret_cast<::sockaddr_in*>(&native_addr)->sin_addr), daport, davport);
}
}
// Length
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Ok recvfrom: %d", native_result);
return not_an_error(native_result);
}
@ -1207,12 +1301,34 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 l
native_flags |= MSG_WAITALL;
}
s32 type = 0;
const auto sock = idm::check<lv2_socket>(s, [&](lv2_socket& sock)
{
type = sock.type;
if (sock.type == SYS_NET_SOCK_DGRAM_P2P)
{
const u16 daport = reinterpret_cast<const sys_net_sockaddr_in*>(addr.get_ptr())->sin_port;
const u16 davport = reinterpret_cast<const sys_net_sockaddr_in_p2p*>(addr.get_ptr())->sin_vport;
sys_net.error("Sending a P2P packet to %s:%d:%d", inet_ntoa(name.sin_addr), daport, davport);
name.sin_port = std::bit_cast<u16, be_t<u16>>(daport + davport); // htons(daport + davport)
}
std::lock_guard lock(sock.mutex);
//if (!(sock.events & lv2_socket::poll::write))
{
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (nph->is_dns(s))
{
const s32 ret_analyzer = nph->analyze_dns_packet(s, static_cast<const u8*>(buf.get_ptr()), len);
// Check if the packet is intercepted
if (ret_analyzer >= 0)
{
native_result = ret_analyzer;
return true;
}
}
native_result = ::sendto(sock.socket, reinterpret_cast<const char*>(buf.get_ptr()), len, native_flags, addr ? reinterpret_cast<struct sockaddr*>(&name) : nullptr, addr ? namelen : 0);
if (native_result >= 0)
@ -1253,16 +1369,20 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 l
if (!sock)
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error sendto(bad socket)");
return -SYS_NET_EBADF;
}
if (!sock.ret && result)
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error sendto(early result): %d", result);
if (result == SYS_NET_EWOULDBLOCK)
{
return not_an_error(-result);
}
return -result;
}
@ -1280,16 +1400,23 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 l
if (result)
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error sendto(result): %d", result);
return -result;
}
if (ppu.gpr[3] == static_cast<u64>(-SYS_NET_EINTR))
{
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Error sendto(interrupted)");
return -SYS_NET_EINTR;
}
}
// Length
if (type == SYS_NET_SOCK_DGRAM_P2P)
sys_net.error("Ok sendto: %d", native_result);
return not_an_error(native_result);
}
@ -1576,7 +1703,7 @@ error_code sys_net_bnet_socket(ppu_thread& ppu, s32 family, s32 type, s32 protoc
return -get_last_error(false);
}
const s32 s = idm::import_existing<lv2_socket>(std::make_shared<lv2_socket>(native_socket));
const s32 s = idm::import_existing<lv2_socket>(std::make_shared<lv2_socket>(native_socket, type));
if (s == id_manager::id_traits<lv2_socket>::invalid)
{
@ -1602,6 +1729,9 @@ error_code sys_net_bnet_close(ppu_thread& ppu, s32 s)
if (!sock->queue.empty())
sys_net.error("CLOSE");
const auto nph = g_fxo->get<named_thread<np_handler>>();
nph->remove_dns_spy(s);
return CELL_OK;
}
@ -1638,7 +1768,12 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 n
if (auto sock = idm::check_unlocked<lv2_socket>(fds[i].fd))
{
if (fds[i].events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT))
// Check for fake packet for dns interceptions
const auto nph = g_fxo->get<named_thread<np_handler>>();
if (fds[i].events & SYS_NET_POLLIN && nph->is_dns(fds[i].fd) && nph->is_dns_queue(fds[i].fd))
fds[i].revents |= SYS_NET_POLLIN;
if (fds[i].events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT | SYS_NET_POLLERR))
sys_net.error("sys_net_bnet_poll(fd=%d): events=0x%x", fds[i].fd, fds[i].events);
_fds[i].fd = sock->socket;
if (fds[i].events & SYS_NET_POLLIN)

View File

@ -328,7 +328,7 @@ struct lv2_socket final
__bitset_enum_max
};
lv2_socket(socket_type s);
lv2_socket(socket_type s, s32 s_type);
~lv2_socket();
shared_mutex mutex;
@ -353,6 +353,8 @@ struct lv2_socket final
// Unsupported option
s32 so_tcp_maxseg = 1500;
s32 type = 0;
// Value keepers
#ifdef _WIN32
s32 so_reuseaddr = 0;

405
rpcs3/Emu/NP/np_handler.cpp Normal file
View File

@ -0,0 +1,405 @@
#include "stdafx.h"
#include <thread>
#include "Emu/system_config.h"
#include "np_handler.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
#include "Emu/Cell/Modules/cellNetCtl.h"
#include "Utilities/StrUtil.h"
#include "Emu/Cell/Modules/cellSysutil.h"
#include "Emu/IdManager.h"
#ifdef _WIN32
#include <winsock2.h>
#include <WS2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
extern logs::channel sys_net;
extern logs::channel sceNp2;
extern logs::channel sceNp;
np_handler::np_handler()
{
is_connected = (g_cfg.net.net_active == np_internet_status::enabled);
is_psn_active = (g_cfg.net.psn_status >= np_psn_status::fake);
// Validate IP/Get from host?
if (get_net_status() == CELL_NET_CTL_STATE_IPObtained)
{
// cur_ip = g_cfg.net.ip_address;
// Attempt to get actual IP address
const char* google_dns_server = "8.8.8.8";
const int dns_port = 53;
struct sockaddr_in serv;
const int sock = socket(AF_INET, SOCK_DGRAM, 0);
ASSERT(sock >= 0);
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr(google_dns_server);
serv.sin_port = std::bit_cast<u16, be_t<u16>>(dns_port); // htons(dns_port)
int err = connect(sock, reinterpret_cast<const struct sockaddr*>(&serv), sizeof(serv));
if (err < 0)
{
sys_net.error("Failed to connect to google dns for IP discovery");
is_connected = false;
cur_ip = "0.0.0.0";
}
else
{
struct sockaddr_in name;
socklen_t namelen = sizeof(name);
err = getsockname(sock, reinterpret_cast<struct sockaddr*>(&name), &namelen);
char buffer[80];
const char* p = inet_ntop(AF_INET, &name.sin_addr, buffer, 80);
if (p == nullptr)
{
sys_net.error("Failed to convert address for IP discovery");
is_connected = false;
cur_ip = "0.0.0.0";
}
cur_ip = p;
struct in_addr addr;
inet_pton(AF_INET, cur_ip.c_str(), &addr);
cur_addr = addr.s_addr;
}
#ifdef _WIN32
closesocket(sock);
#else
close(sock);
#endif
// Convert dns address
std::string s_dns = g_cfg.net.dns;
in_addr conv;
if (!inet_pton(AF_INET, s_dns.c_str(), &conv))
{
sys_net.error("Provided IP(%s) address for DNS is invalid!", s_dns);
is_connected = false;
conv.s_addr = 0;
cur_ip = "0.0.0.0";
}
dns = conv.s_addr;
// Init switch map for dns
auto swaps = fmt::split(g_cfg.net.swap_list, {"&&"});
for (std::size_t i = 0; i < swaps.size(); i++)
{
auto host_and_ip = fmt::split(swaps[i], {"="});
if (host_and_ip.size() != 2)
continue;
in_addr conv;
if (!inet_pton(AF_INET, host_and_ip[1].c_str(), &conv))
{
sys_net.error("IP(%s) provided for %s in the switch list is invalid!", host_and_ip[1], host_and_ip[0]);
conv.s_addr = 0;
}
switch_map[host_and_ip[0]] = conv.s_addr;
}
}
else
{
cur_ip = "0.0.0.0";
dns = 0;
}
}
void np_handler::init_NP(u32 poolsize, vm::ptr<void> poolptr)
{
// Init memory pool
mpool = poolptr;
mpool_size = poolsize;
mpool_avail = poolsize;
mpool_allocs.clear();
memset(&npid, 0, sizeof(npid));
memset(&online_name, 0, sizeof(online_name));
memset(&avatar_url, 0, sizeof(avatar_url));
if (g_cfg.net.psn_status >= np_psn_status::fake)
{
std::string s_npid = g_cfg.net.psn_npid;
ASSERT(s_npid != ""); // It should be generated in settings window if empty
strncpy(npid.handle.data, s_npid.c_str(), sizeof(npid.handle.data));
}
switch (g_cfg.net.psn_status)
{
case np_psn_status::disabled:
break;
case np_psn_status::fake:
{
strncpy(online_name.data, "RPCS3's user", sizeof(online_name.data));
strncpy(avatar_url.data, "https://i.imgur.com/AfWIyQP.jpg", sizeof(avatar_url.data));
break;
}
default:
break;
}
}
void np_handler::terminate_NP()
{
is_psn_active = false;
// Reset memory pool
mpool.set(0);
mpool_size = 0;
mpool_avail = 0;
mpool_allocs.clear();
}
vm::addr_t np_handler::allocate(u32 size)
{
// Align allocs
const u32 alloc_size = ::align(size, 4);
if (alloc_size > mpool_avail)
{
sceNp.error("Not enough memory available in NP pool!");
return vm::cast<u32>(0);
}
u32 last_free = 0;
bool found_space = false;
for (auto& a : mpool_allocs)
{
if ((a.first - last_free) >= alloc_size)
{
found_space = true;
break;
}
last_free = a.first + a.second;
}
if (!found_space)
{
if ((mpool_size - last_free) < alloc_size)
{
sceNp.error("Not enough memory available in NP pool(continuous block)!");
return vm::cast<u32>(0);
}
}
mpool_allocs.emplace(last_free, alloc_size);
mpool_avail -= alloc_size;
memset((static_cast<u8*>(mpool.get_ptr())) + last_free, 0, alloc_size);
return vm::cast(mpool.addr() + last_free);
}
void np_handler::operator()()
{
}
s32 np_handler::get_net_status() const
{
return is_connected ? CELL_NET_CTL_STATE_IPObtained : CELL_NET_CTL_STATE_Disconnected;
}
s32 np_handler::get_psn_status() const
{
return is_psn_active ? SCE_NP_MANAGER_STATUS_ONLINE : SCE_NP_MANAGER_STATUS_OFFLINE;
}
const std::string& np_handler::get_ip() const
{
return cur_ip;
}
u32 np_handler::get_dns() const
{
return dns;
}
const SceNpId& np_handler::get_npid() const
{
return npid;
}
const SceNpOnlineId& np_handler::get_online_id() const
{
return npid.handle;
}
const SceNpOnlineName& np_handler::get_online_name() const
{
return online_name;
}
const SceNpAvatarUrl& np_handler::get_avatar_url() const
{
return avatar_url;
}
void np_handler::add_dns_spy(u32 sock)
{
dns_spylist.emplace(std::make_pair(sock, std::queue<std::vector<u8>>()));
}
void np_handler::remove_dns_spy(u32 sock)
{
dns_spylist.erase(sock);
}
bool np_handler::is_dns(u32 sock) const
{
return dns_spylist.count(sock) != 0;
}
bool np_handler::is_dns_queue(u32 sock) const
{
return !dns_spylist.at(sock).empty();
}
std::vector<u8> np_handler::get_dns_packet(u32 sock)
{
auto ret_vec = std::move(dns_spylist.at(sock).front());
dns_spylist.at(sock).pop();
return ret_vec;
}
s32 np_handler::analyze_dns_packet(s32 s, const u8* buf, u32 len)
{
if (sys_net.enabled == logs::level::trace)
{
std::string datrace;
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (u32 index = 0; index < len; index++)
{
if ((index % 16) == 0)
datrace += '\n';
datrace += hex[(buf[index] >> 4) & 15];
datrace += hex[(buf[index]) & 15];
datrace += ' ';
}
sys_net.trace("DNS REQUEST: %s", datrace);
}
struct dns_header
{
u16 id; // identification number
u8 rd : 1; // recursion desired
u8 tc : 1; // truncated message
u8 aa : 1; // authoritive answer
u8 opcode : 4; // purpose of message
u8 qr : 1; // query/response flag
u8 rcode : 4; // response code
u8 cd : 1; // checking disabled
u8 ad : 1; // authenticated data
u8 z : 1; // its z! reserved
u8 ra : 1; // recursion available
be_t<u16> q_count; // number of question entries
be_t<u16> ans_count; // number of answer entries
be_t<u16> auth_count; // number of authority entries
be_t<u16> add_count; // number of resource entries
};
if (len < sizeof(dns_header))
return -1;
const dns_header* dhead = reinterpret_cast<const dns_header*>(buf);
// We are only looking for queries not truncated(todo?), only handle one dns query at a time(todo?)
if (dhead->qr != 0 || dhead->tc != 0 || dhead->q_count != 1 || dhead->ans_count != 0 || dhead->auth_count != 0 || dhead->add_count != 0)
return -1;
// Get the actual address
u8 count = 0;
std::string host{};
for (u32 i = sizeof(dns_header); (i < len) && buf[i] != 0; i++)
{
if (count == 0)
{
count = buf[i];
if (i != sizeof(dns_header))
{
host += '.';
}
}
else
{
host += static_cast<char>(buf[i]);
count--;
}
}
sys_net.warning("DNS query for %s", host);
if (switch_map.count(host))
{
// design fake packet
std::vector<u8> fake(len);
memcpy(fake.data(), buf, len);
dns_header* fake_header = reinterpret_cast<dns_header*>(fake.data());
fake_header->qr = 1;
fake_header->ra = 1;
fake_header->ans_count = 1;
fake.insert(fake.end(), {0xC0, 0x0C}); // Ref to name in header
fake.insert(fake.end(), {0x00, 0x01}); // IPv4
fake.insert(fake.end(), {0x00, 0x01}); // Class?
fake.insert(fake.end(), {0x00, 0x00, 0x00, 0x3B}); // TTL
fake.insert(fake.end(), {0x00, 0x04}); // Size of data
u32 ip = switch_map[host];
u8* ptr_ip = reinterpret_cast<u8*>(&ip);
fake.insert(fake.end(), ptr_ip, ptr_ip + 4); // IP
sys_net.warning("Solving %s to %d.%d.%d.%d", host, ptr_ip[0], ptr_ip[1], ptr_ip[2], ptr_ip[3]);
dns_spylist[s].push(std::move(fake));
return len;
}
return -1;
}
s32 np_handler::create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
return static_cast<s32>(idm::make<score_ctx>(communicationId, passphrase));
}
bool np_handler::destroy_score_context(s32 ctx_id)
{
return idm::remove<score_ctx>(static_cast<u32>(ctx_id));
}
u16 np_handler::create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase));
}
bool np_handler::destroy_match2_context(u16 ctx_id)
{
return idm::remove<match2_ctx>(static_cast<u32>(ctx_id));
}
s32 np_handler::create_lookup_context(vm::cptr<SceNpCommunicationId> communicationId)
{
return static_cast<s32>(idm::make<lookup_ctx>(communicationId));
}
bool np_handler::destroy_lookup_context(s32 ctx_id)
{
return idm::remove<match2_ctx>(static_cast<u32>(ctx_id));
}

128
rpcs3/Emu/NP/np_handler.h Normal file
View File

@ -0,0 +1,128 @@
#pragma once
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
#include <queue>
#include <map>
class np_handler
{
public:
np_handler();
s32 get_psn_status() const;
s32 get_net_status() const;
const std::string& get_ip() const;
u32 get_dns() const;
const SceNpId& get_npid() const;
const SceNpOnlineId& get_online_id() const;
const SceNpOnlineName& get_online_name() const;
const SceNpAvatarUrl& get_avatar_url() const;
// DNS hooking functions
void add_dns_spy(u32 sock);
void remove_dns_spy(u32 sock);
bool is_dns(u32 sock) const;
bool is_dns_queue(u32 sock) const;
std::vector<u8> get_dns_packet(u32 sock);
s32 analyze_dns_packet(s32 s, const u8* buf, u32 len);
void operator()();
void init_NP(u32 poolsize, vm::ptr<void> poolptr);
void terminate_NP();
bool is_netctl_init = false;
bool is_NP_init = false;
bool is_NP_Lookup_init = false;
bool is_NP_Score_init = false;
bool is_NP2_init = false;
bool is_NP2_Match2_init = false;
bool is_NP_Auth_init = false;
// Score related
struct score_ctx
{
score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
}
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32;
SceNpCommunicationId communicationId;
SceNpCommunicationPassphrase passphrase;
};
s32 create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
bool destroy_score_context(s32 ctx_id);
// Match2 related
struct match2_ctx
{
match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
}
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 255;
SceNpCommunicationId communicationId;
SceNpCommunicationPassphrase passphrase;
};
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
bool destroy_match2_context(u16 ctx_id);
struct lookup_ctx
{
lookup_ctx(vm::cptr<SceNpCommunicationId> communicationId)
{
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
}
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32;
SceNpCommunicationId communicationId;
SceNpCommunicationPassphrase passphrase;
};
s32 create_lookup_context(vm::cptr<SceNpCommunicationId> communicationId);
bool destroy_lookup_context(s32 ctx_id);
static constexpr std::string_view thread_name = "NP Handler Thread";
protected:
bool is_connected = false;
bool is_psn_active = false;
// Net infos
std::string cur_ip{};
u32 cur_addr = 0;
u32 dns = 0x08080808;
// User infos
SceNpId npid{};
SceNpOnlineName online_name{};
SceNpAvatarUrl avatar_url{};
// DNS related
std::map<s32, std::queue<std::vector<u8>>> dns_spylist{};
std::map<std::string, u32> switch_map{};
// Memory pool for sceNp/sceNp2
vm::ptr<void> mpool{};
u32 mpool_size = 0;
u32 mpool_avail = 0;
std::map<u32, u32> mpool_allocs{}; // offset/size
vm::addr_t allocate(u32 size);
};

View File

@ -234,11 +234,15 @@ struct cfg_root : cfg::node
{
node_net(cfg::node* _this) : cfg::node(_this, "Net") {}
cfg::_enum<CellNetCtlState> net_status{ this, "Connection status" };
cfg::string ip_address{ this, "IP address", "192.168.1.1" };
} net{ this };
cfg::_enum<np_internet_status> net_active{this, "Internet enabled", np_internet_status::disabled};
cfg::string ip_address{this, "IP address", "0.0.0.0"};
cfg::string dns{this, "DNS address", "8.8.8.8"};
cfg::string swap_list{this, "IP swap list", ""};
cfg::_enum<np_psn_status> psn_status{this, "PSN status", np_psn_status::disabled};
cfg::string psn_npid{this, "NPID", ""};
} net{this};
struct node_misc : cfg::node
{
node_misc(cfg::node* _this) : cfg::node(_this, "Miscellaneous") {}

View File

@ -205,3 +205,34 @@ void fmt_class_string<enter_button_assign>::format(std::string& out, u64 arg)
return unknown;
});
}
template <>
void fmt_class_string<np_internet_status>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](np_internet_status value)
{
switch (value)
{
case np_internet_status::disabled: return "Disconnected";
case np_internet_status::enabled: return "Connected";
}
return unknown;
});
}
template <>
void fmt_class_string<np_psn_status>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](np_psn_status value)
{
switch (value)
{
case np_psn_status::disabled: return "Disconnected";
case np_psn_status::fake: return "Simulated";
}
return unknown;
});
}

View File

@ -167,3 +167,15 @@ enum class enter_button_assign
circle, // CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE
cross // CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS
};
enum class np_internet_status
{
disabled,
enabled,
};
enum np_psn_status
{
disabled,
fake,
};

View File

@ -80,6 +80,7 @@
<ClCompile Include="Emu\system_config_types.cpp" />
<ClCompile Include="Emu\title.cpp" />
<ClCompile Include="Emu\system_config.cpp" />
<ClCompile Include="Emu\NP\np_handler.cpp" />
<ClCompile Include="util\atomic.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
@ -426,6 +427,7 @@
<ClInclude Include="Emu\Io\Keyboard.h" />
<ClInclude Include="Emu\Io\pad_config.h" />
<ClInclude Include="Emu\Io\pad_config_types.h" />
<ClInclude Include="Emu\NP\np_handler.h" />
<ClInclude Include="Emu\RSX\Common\texture_cache_helpers.h" />
<ClInclude Include="Emu\RSX\Overlays\overlay_fonts.h" />
<ClInclude Include="Emu\RSX\Overlays\overlay_message_dialog.h" />

View File

@ -72,6 +72,9 @@
<Filter Include="Emu\GPU\RSX\Overlays\Shaders">
<UniqueIdentifier>{f368580d-07bc-4c8b-b488-a4198f2dd17d}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\NP">
<UniqueIdentifier>{652ce43e-72db-42cd-831a-0e194f67e731}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Crypto\aes.cpp">
@ -911,6 +914,9 @@
<ClCompile Include="Emu\RSX\Overlays\overlay_utils.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\NP\np_handler.cpp">
<Filter>Emu\NP</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -1741,5 +1747,8 @@
<ClInclude Include="Emu\Io\GHLtar.h">
<Filter>Emu\Io</Filter>
</ClInclude>
<ClInclude Include="Emu\NP\np_handler.h">
<Filter>Emu\NP</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -10,6 +10,7 @@
#include "Utilities/StrUtil.h"
#include <QMessageBox>
#include <QLineEdit>
#if defined(_WIN32) || defined(HAVE_VULKAN)
#include "Emu/RSX/VK/VKHelpers.h"
@ -551,6 +552,23 @@ void emu_settings::EnhanceDoubleSpinBox(QDoubleSpinBox* spinbox, SettingsType ty
});
}
void emu_settings::EnhanceEdit(QLineEdit* edit, SettingsType type)
{
if (!edit)
{
cfg_log.fatal("EnhanceEdit '%s' was used with an invalid object", GetSettingName(type));
return;
}
const std::string set_text = GetSetting(type);
edit->setText(qstr(set_text));
connect(edit, &QLineEdit::textChanged, [=, this](const QString &text)
{
SetSetting(type, sstr(text));
});
}
std::vector<std::string> emu_settings::GetLoadedLibraries()
{
return m_currentSettings["Core"]["Load libraries"].as<std::vector<std::string>, std::initializer_list<std::string>>({});

View File

@ -138,7 +138,11 @@ public:
WindowTitleFormat,
// Network
ConnectionStatus,
InternetStatus,
DNSAddress,
IpSwapList,
PSNStatus,
PSNNPID,
// System
Language,
@ -228,6 +232,9 @@ public:
/** Connects a double spin box with the target settings type*/
void EnhanceDoubleSpinBox(QDoubleSpinBox* slider, SettingsType type, const QString& prefix = "", const QString& suffix = "");
/** Connects a line edit with the target settings type*/
void EnhanceEdit(QLineEdit* edit, SettingsType type);
std::vector<std::string> GetLoadedLibraries();
void SaveSelectedLibraries(const std::vector<std::string>& libs);
@ -379,7 +386,11 @@ private:
{ WindowTitleFormat, { "Miscellaneous", "Window Title Format" }},
// Networking
{ ConnectionStatus, { "Net", "Connection status"}},
{ InternetStatus, { "Net", "Internet enabled"}},
{ DNSAddress, { "Net", "DNS address"}},
{ IpSwapList, { "Net", "IP swap list"}},
{ PSNStatus, { "Net", "PSN status"}},
{ PSNNPID, { "Net", "NPID"}},
// System
{ Language, { "System", "Language"}},

View File

@ -902,11 +902,52 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
// | |\ | __/ |_ \ V V / (_) | | | < | | (_| | |_) |
// |_| \_|\___|\__| \_/\_/ \___/|_| |_|\_\ |_|\__,_|_.__/
// Edits
xemu_settings->EnhanceEdit(ui->edit_dns, emu_settings::DNSAddress);
SubscribeTooltip(ui->edit_dns, tooltips.settings.dns);
xemu_settings->EnhanceEdit(ui->edit_npid, emu_settings::PSNNPID);
SubscribeTooltip(ui->edit_npid, tooltips.settings.psn_npid);
xemu_settings->EnhanceEdit(ui->edit_swaps, emu_settings::IpSwapList);
SubscribeTooltip(ui->edit_swaps, tooltips.settings.dns_swap);
// Comboboxes
xemu_settings->EnhanceComboBox(ui->netStatusBox, emu_settings::ConnectionStatus);
SubscribeTooltip(ui->gb_network_status, tooltips.settings.net_status);
xemu_settings->EnhanceComboBox(ui->netStatusBox, emu_settings::InternetStatus);
SubscribeTooltip(ui->netStatusBox, tooltips.settings.net_status);
connect(ui->netStatusBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index)
{
ui->edit_dns->setEnabled(index > 0);
});
ui->edit_dns->setEnabled(ui->netStatusBox->currentIndex() > 0);
connect(ui->psnStatusBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index)
{
ui->edit_npid->setEnabled(index > 0);
if (index > 0 && ui->edit_npid->text() == "")
{
QString gen_npid = "RPCS3_";
constexpr char list_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
std::srand(time(0));
for (int i = 0; i < 10; i++)
{
gen_npid += list_chars[std::rand() % (sizeof(list_chars) - 1)];
}
ui->edit_npid->setText(gen_npid);
}
});
xemu_settings->EnhanceComboBox(ui->psnStatusBox, emu_settings::PSNStatus);
SubscribeTooltip(ui->psnStatusBox, tooltips.settings.psn_status);
// _ _ _______ _
// /\ | | | | |__ __| | |

View File

@ -1487,24 +1487,145 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_40">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16" stretch="1,1,1">
<layout class="QHBoxLayout" name="horizontalLayout_16" stretch="0,0">
<item>
<widget class="QGroupBox" name="gb_network_status">
<property name="title">
<string>Network Status</string>
<string>Network Configuration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_38">
<layout class="QVBoxLayout" name="verticalLayout_38" stretch="0,0,0,0">
<item>
<widget class="QComboBox" name="netStatusBox"/>
<widget class="QGroupBox" name="groupBox_10">
<property name="title">
<string>Network Status</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_90">
<item>
<widget class="QComboBox" name="netStatusBox"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_12">
<property name="title">
<string>DNS</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_92">
<item>
<widget class="QLineEdit" name="edit_dns">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_13">
<property name="title">
<string>IP/Hosts switches</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_93">
<item>
<widget class="QLineEdit" name="edit_swaps">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_24">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_10" native="true"/>
</item>
<item>
<widget class="QWidget" name="widget_5" native="true"/>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>PSN Configuration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_88">
<item>
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>PSN Status</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_91">
<item>
<widget class="QComboBox" name="psnStatusBox"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_15">
<property name="title">
<string>PSN settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_95">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_31">
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>NPID:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="edit_npid">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxLength">
<number>16</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_25">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>

View File

@ -170,7 +170,11 @@ public:
// network
const QString net_status = tr("Leave as disconnected unless you're debugging.\nRPCS3 has no online support.");
const QString net_status = tr("If set to Connected, RPCS3 will allow programs to use your internet connection.");
const QString psn_status = tr("If set to Simulated, RPCS3 will fake PSN connection as best as it can.");
const QString dns = tr("DNS used to resolve hostnames by applications");
const QString psn_npid = tr("Identifier representing your account");
const QString dns_swap = tr("DNS Swap List");
// system