mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 08:41:20 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37e4861e1d |
No files matched your search
@@ -133,6 +133,10 @@ bool IsNetworkConnected() {
|
|||||||
return g_config->network_connected;
|
return g_config->network_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PsnEmulationEnabled() {
|
||||||
|
return g_config->psn_emulation_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShaderValidationEnabled() {
|
bool ShaderValidationEnabled() {
|
||||||
return g_config->shader_validation_enabled;
|
return g_config->shader_validation_enabled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ struct ConfigOptions {
|
|||||||
bool vr_enabled = false;
|
bool vr_enabled = false;
|
||||||
bool amd_cpu_enabled = false;
|
bool amd_cpu_enabled = false;
|
||||||
bool network_connected = false;
|
bool network_connected = false;
|
||||||
|
bool psn_emulation_enabled = false;
|
||||||
uint32_t vblank_frequency = 60;
|
uint32_t vblank_frequency = 60;
|
||||||
uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE;
|
uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE;
|
||||||
bool vulkan_validation_enabled = false;
|
bool vulkan_validation_enabled = false;
|
||||||
@@ -130,6 +131,7 @@ bool StretchEnabled();
|
|||||||
bool VrEnabled();
|
bool VrEnabled();
|
||||||
bool AmdCpuEnabled();
|
bool AmdCpuEnabled();
|
||||||
bool IsNetworkConnected();
|
bool IsNetworkConnected();
|
||||||
|
bool PsnEmulationEnabled();
|
||||||
uint32_t GetVblankFrequency();
|
uint32_t GetVblankFrequency();
|
||||||
uint32_t GetConsoleLanguage();
|
uint32_t GetConsoleLanguage();
|
||||||
bool VulkanValidationEnabled();
|
bool VulkanValidationEnabled();
|
||||||
|
|||||||
@@ -406,6 +406,11 @@
|
|||||||
<property name="text"><string>Enable network connection</string></property>
|
<property name="text"><string>Enable network connection</string></property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBox_psn_emulation">
|
||||||
|
<property name="text"><string>Emulate PSN (compatibility)</string></property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="networkSpacer">
|
<spacer name="networkSpacer">
|
||||||
<property name="orientation"><enum>Qt::Vertical</enum></property>
|
<property name="orientation"><enum>Qt::Vertical</enum></property>
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ public:
|
|||||||
bool perf_overlay_enabled = false;
|
bool perf_overlay_enabled = false;
|
||||||
bool skip_notice_screen = false;
|
bool skip_notice_screen = false;
|
||||||
bool network_connected = false;
|
bool network_connected = false;
|
||||||
|
bool psn_emulation_enabled = false;
|
||||||
int vblank_frequency = 60;
|
int vblank_frequency = 60;
|
||||||
int console_language = DEFAULT_CONSOLE_LANGUAGE;
|
int console_language = DEFAULT_CONSOLE_LANGUAGE;
|
||||||
bool vulkan_validation_enabled = false;
|
bool vulkan_validation_enabled = false;
|
||||||
@@ -171,6 +172,7 @@ public:
|
|||||||
perf_overlay_enabled = other.perf_overlay_enabled;
|
perf_overlay_enabled = other.perf_overlay_enabled;
|
||||||
skip_notice_screen = other.skip_notice_screen;
|
skip_notice_screen = other.skip_notice_screen;
|
||||||
network_connected = other.network_connected;
|
network_connected = other.network_connected;
|
||||||
|
psn_emulation_enabled = other.psn_emulation_enabled;
|
||||||
vblank_frequency = other.vblank_frequency;
|
vblank_frequency = other.vblank_frequency;
|
||||||
console_language = other.console_language;
|
console_language = other.console_language;
|
||||||
vulkan_validation_enabled = other.vulkan_validation_enabled;
|
vulkan_validation_enabled = other.vulkan_validation_enabled;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ QVariantMap Configuration::GameSettings() const {
|
|||||||
KYTY_CFG_SET(perf_overlay_enabled);
|
KYTY_CFG_SET(perf_overlay_enabled);
|
||||||
KYTY_CFG_SET(skip_notice_screen);
|
KYTY_CFG_SET(skip_notice_screen);
|
||||||
KYTY_CFG_SET(network_connected);
|
KYTY_CFG_SET(network_connected);
|
||||||
|
KYTY_CFG_SET(psn_emulation_enabled);
|
||||||
KYTY_CFG_SET(vblank_frequency);
|
KYTY_CFG_SET(vblank_frequency);
|
||||||
KYTY_CFG_SET(console_language);
|
KYTY_CFG_SET(console_language);
|
||||||
KYTY_CFG_SET(vulkan_validation_enabled);
|
KYTY_CFG_SET(vulkan_validation_enabled);
|
||||||
@@ -96,6 +97,7 @@ void Configuration::ReadGameSettingsValues(const Settings& s) {
|
|||||||
KYTY_CFG_GET(perf_overlay_enabled);
|
KYTY_CFG_GET(perf_overlay_enabled);
|
||||||
KYTY_CFG_GET(skip_notice_screen);
|
KYTY_CFG_GET(skip_notice_screen);
|
||||||
KYTY_CFG_GET(network_connected);
|
KYTY_CFG_GET(network_connected);
|
||||||
|
KYTY_CFG_GET(psn_emulation_enabled);
|
||||||
vblank_frequency = s.value("vblank_frequency", vblank_frequency).toInt();
|
vblank_frequency = s.value("vblank_frequency", vblank_frequency).toInt();
|
||||||
console_language = s.value("console_language", console_language).toInt();
|
console_language = s.value("console_language", console_language).toInt();
|
||||||
if (console_language < 0 || console_language > MAX_CONSOLE_LANGUAGE) {
|
if (console_language < 0 || console_language > MAX_CONSOLE_LANGUAGE) {
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ void ConfigurationEditDialog::Init(const Configuration& info) {
|
|||||||
m_ui->checkBox_shader_cache->setChecked(info.shader_cache_enabled);
|
m_ui->checkBox_shader_cache->setChecked(info.shader_cache_enabled);
|
||||||
m_ui->checkBox_skip_notice_screen->setChecked(info.skip_notice_screen);
|
m_ui->checkBox_skip_notice_screen->setChecked(info.skip_notice_screen);
|
||||||
m_ui->checkBox_network_connected->setChecked(info.network_connected);
|
m_ui->checkBox_network_connected->setChecked(info.network_connected);
|
||||||
|
m_ui->checkBox_psn_emulation->setChecked(info.psn_emulation_enabled);
|
||||||
m_ui->checkBox_trophy_notifications->setChecked(info.trophy_enabled);
|
m_ui->checkBox_trophy_notifications->setChecked(info.trophy_enabled);
|
||||||
m_ui->spinBox_trophy_duration->setValue(info.trophy_duration_seconds);
|
m_ui->spinBox_trophy_duration->setValue(info.trophy_duration_seconds);
|
||||||
m_ui->checkBox_perf_overlay->setChecked(info.perf_overlay_enabled);
|
m_ui->checkBox_perf_overlay->setChecked(info.perf_overlay_enabled);
|
||||||
@@ -533,6 +534,7 @@ static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui, boo
|
|||||||
info.shader_cache_enabled = ui.checkBox_shader_cache->isChecked();
|
info.shader_cache_enabled = ui.checkBox_shader_cache->isChecked();
|
||||||
info.skip_notice_screen = ui.checkBox_skip_notice_screen->isChecked();
|
info.skip_notice_screen = ui.checkBox_skip_notice_screen->isChecked();
|
||||||
info.network_connected = ui.checkBox_network_connected->isChecked();
|
info.network_connected = ui.checkBox_network_connected->isChecked();
|
||||||
|
info.psn_emulation_enabled = ui.checkBox_psn_emulation->isChecked();
|
||||||
info.trophy_enabled = ui.checkBox_trophy_notifications->isChecked();
|
info.trophy_enabled = ui.checkBox_trophy_notifications->isChecked();
|
||||||
info.trophy_duration_seconds = ui.spinBox_trophy_duration->value();
|
info.trophy_duration_seconds = ui.spinBox_trophy_duration->value();
|
||||||
info.perf_overlay_enabled = ui.checkBox_perf_overlay->isChecked();
|
info.perf_overlay_enabled = ui.checkBox_perf_overlay->isChecked();
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ static QStringList CreateEmulatorArgs(const Configuration& info) {
|
|||||||
AddFlag(args, info.perf_overlay_enabled, "--perf-overlay");
|
AddFlag(args, info.perf_overlay_enabled, "--perf-overlay");
|
||||||
AddFlag(args, info.skip_notice_screen, "--skip-notice-screen");
|
AddFlag(args, info.skip_notice_screen, "--skip-notice-screen");
|
||||||
AddFlag(args, info.network_connected, "--network-connected");
|
AddFlag(args, info.network_connected, "--network-connected");
|
||||||
|
AddFlag(args, info.psn_emulation_enabled, "--emulate-psn");
|
||||||
AddFlag(args, info.tessellation_enabled, "--tessellation");
|
AddFlag(args, info.tessellation_enabled, "--tessellation");
|
||||||
AddFlag(args, info.occlusion_queries_enabled, "--occlusion-queries");
|
AddFlag(args, info.occlusion_queries_enabled, "--occlusion-queries");
|
||||||
AddFlag(args, info.shader_cache_enabled, "--shader-cache");
|
AddFlag(args, info.shader_cache_enabled, "--shader-cache");
|
||||||
|
|||||||
+54
-32
@@ -1685,12 +1685,34 @@ LIB_VERSION("NpAuth", 1, "NpAuth", 1, 1);
|
|||||||
constexpr int NP_AUTH_MAX_REQUEST_NUM = 16;
|
constexpr int NP_AUTH_MAX_REQUEST_NUM = 16;
|
||||||
constexpr int NP_AUTH_REQUEST_ID_OFFSET = 0x10000000;
|
constexpr int NP_AUTH_REQUEST_ID_OFFSET = 0x10000000;
|
||||||
constexpr int NP_AUTH_ERROR_INVALID_ARGUMENT = -2141912319; /* 0x80550301 */
|
constexpr int NP_AUTH_ERROR_INVALID_ARGUMENT = -2141912319; /* 0x80550301 */
|
||||||
|
constexpr int NP_AUTH_ERROR_INVALID_SIZE = -2141912318; /* 0x80550302 */
|
||||||
constexpr int NP_AUTH_ERROR_ABORTED = -2141912316; /* 0x80550304 */
|
constexpr int NP_AUTH_ERROR_ABORTED = -2141912316; /* 0x80550304 */
|
||||||
constexpr int NP_AUTH_ERROR_REQUEST_MAX = -2141912315; /* 0x80550305 */
|
constexpr int NP_AUTH_ERROR_REQUEST_MAX = -2141912315; /* 0x80550305 */
|
||||||
constexpr int NP_AUTH_ERROR_REQUEST_NOT_FOUND = -2141912314; /* 0x80550306 */
|
constexpr int NP_AUTH_ERROR_REQUEST_NOT_FOUND = -2141912314; /* 0x80550306 */
|
||||||
constexpr int NP_AUTH_ERROR_INVALID_ID = -2141912313; /* 0x80550307 */
|
constexpr int NP_AUTH_ERROR_INVALID_ID = -2141912313; /* 0x80550307 */
|
||||||
|
constexpr int NP_AUTH_ERROR_SERVICE_DOWN = -2141912063; /* 0x80550401 */
|
||||||
constexpr int NP_ERROR_SIGNED_OUT = -2141913082; /* 0x80550006 */
|
constexpr int NP_ERROR_SIGNED_OUT = -2141913082; /* 0x80550006 */
|
||||||
|
|
||||||
|
struct NpAuthGetAuthorizationCodeParameterV3 {
|
||||||
|
size_t size;
|
||||||
|
int user_id;
|
||||||
|
uint8_t padding[4];
|
||||||
|
const void* client_id;
|
||||||
|
const char* scope;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NpAuthGetIdTokenParameterV3 {
|
||||||
|
size_t size;
|
||||||
|
int user_id;
|
||||||
|
uint8_t padding[4];
|
||||||
|
const void* client_id;
|
||||||
|
const void* client_secret;
|
||||||
|
const char* scope;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(NpAuthGetAuthorizationCodeParameterV3) == 32);
|
||||||
|
static_assert(sizeof(NpAuthGetIdTokenParameterV3) == 40);
|
||||||
|
|
||||||
enum class NpAuthRequestState {
|
enum class NpAuthRequestState {
|
||||||
None = 0,
|
None = 0,
|
||||||
Ready,
|
Ready,
|
||||||
@@ -1822,7 +1844,7 @@ static int np_auth_wait_or_poll_async(int req_id, int* result) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int np_auth_complete_signed_out(NpAuthRequest* request) {
|
static int np_auth_complete_unavailable(NpAuthRequest* request, int user_id) {
|
||||||
if (request->state == NpAuthRequestState::Complete) {
|
if (request->state == NpAuthRequestState::Complete) {
|
||||||
request->result = NP_AUTH_ERROR_INVALID_ARGUMENT;
|
request->result = NP_AUTH_ERROR_INVALID_ARGUMENT;
|
||||||
return NP_AUTH_ERROR_INVALID_ARGUMENT;
|
return NP_AUTH_ERROR_INVALID_ARGUMENT;
|
||||||
@@ -1833,9 +1855,11 @@ static int np_auth_complete_signed_out(NpAuthRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
request->state = NpAuthRequestState::Complete;
|
request->state = NpAuthRequestState::Complete;
|
||||||
request->result = NP_ERROR_SIGNED_OUT;
|
// Emulating sign-in cannot provide a real authorization code or ID token.
|
||||||
|
request->result = Network::NpManager::IsSignedIn(user_id) ? NP_AUTH_ERROR_SERVICE_DOWN
|
||||||
|
: NP_ERROR_SIGNED_OUT;
|
||||||
|
|
||||||
return request->async ? 0 : NP_ERROR_SIGNED_OUT;
|
return request->async ? 0 : request->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int KYTY_SYSV_ABI NpAuthWaitAsync(int req_id, int* result) {
|
static int KYTY_SYSV_ABI NpAuthWaitAsync(int req_id, int* result) {
|
||||||
@@ -1856,8 +1880,9 @@ static int KYTY_SYSV_ABI NpAuthPollAsync(int req_id, int* result) {
|
|||||||
return np_auth_wait_or_poll_async(req_id, result);
|
return np_auth_wait_or_poll_async(req_id, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int KYTY_SYSV_ABI NpAuthGetAuthorizationCodeV3(int req_id, const void* param,
|
static int KYTY_SYSV_ABI NpAuthGetAuthorizationCodeV3(
|
||||||
void* auth_code, int* issuer_id) {
|
int req_id, const NpAuthGetAuthorizationCodeParameterV3* param, void* auth_code,
|
||||||
|
int* issuer_id) {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
LOGF("\t req_id = %d\n", req_id);
|
LOGF("\t req_id = %d\n", req_id);
|
||||||
@@ -1865,9 +1890,17 @@ static int KYTY_SYSV_ABI NpAuthGetAuthorizationCodeV3(int req_id, const void* pa
|
|||||||
LOGF("\t auth_code = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(auth_code));
|
LOGF("\t auth_code = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(auth_code));
|
||||||
LOGF("\t issuer_id = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(issuer_id));
|
LOGF("\t issuer_id = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(issuer_id));
|
||||||
|
|
||||||
if (auth_code != nullptr) {
|
if (req_id <= 0 || param == nullptr || auth_code == nullptr) {
|
||||||
memset(auth_code, 0, 136);
|
return NP_AUTH_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
if (param->size < sizeof(*param)) {
|
||||||
|
return NP_AUTH_ERROR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
if (param->client_id == nullptr || param->scope == nullptr) {
|
||||||
|
return NP_AUTH_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(auth_code, 0, 136);
|
||||||
if (issuer_id != nullptr) {
|
if (issuer_id != nullptr) {
|
||||||
*issuer_id = 0;
|
*issuer_id = 0;
|
||||||
}
|
}
|
||||||
@@ -1877,46 +1910,35 @@ static int KYTY_SYSV_ABI NpAuthGetAuthorizationCodeV3(int req_id, const void* pa
|
|||||||
if (request == nullptr) {
|
if (request == nullptr) {
|
||||||
return NP_AUTH_ERROR_REQUEST_NOT_FOUND;
|
return NP_AUTH_ERROR_REQUEST_NOT_FOUND;
|
||||||
}
|
}
|
||||||
if (request->state == NpAuthRequestState::Aborted) {
|
return np_auth_complete_unavailable(request, param->user_id);
|
||||||
// request->result = 0;
|
|
||||||
// return 0;
|
|
||||||
request->result = NP_AUTH_ERROR_ABORTED;
|
|
||||||
return NP_AUTH_ERROR_ABORTED;
|
|
||||||
}
|
|
||||||
// request->state = NpAuthRequestState::Complete;
|
|
||||||
// request->result = 0;
|
|
||||||
|
|
||||||
// return 0;
|
|
||||||
return np_auth_complete_signed_out(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int KYTY_SYSV_ABI NpAuthGetIdTokenV3(int req_id, const void* param, void* id_token) {
|
static int KYTY_SYSV_ABI NpAuthGetIdTokenV3(int req_id, const NpAuthGetIdTokenParameterV3* param,
|
||||||
|
void* id_token) {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
LOGF("\t req_id = %d\n", req_id);
|
LOGF("\t req_id = %d\n", req_id);
|
||||||
LOGF("\t param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(param));
|
LOGF("\t param = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(param));
|
||||||
LOGF("\t id_token = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(id_token));
|
LOGF("\t id_token = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(id_token));
|
||||||
|
|
||||||
if (id_token != nullptr) {
|
if (req_id <= 0 || param == nullptr || id_token == nullptr) {
|
||||||
memset(id_token, 0, 4104);
|
return NP_AUTH_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
if (param->size < sizeof(*param)) {
|
||||||
|
return NP_AUTH_ERROR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
if (param->client_id == nullptr || param->client_secret == nullptr || param->scope == nullptr) {
|
||||||
|
return NP_AUTH_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(id_token, 0, 4104);
|
||||||
|
|
||||||
std::scoped_lock lock(g_np_auth_request_mutex);
|
std::scoped_lock lock(g_np_auth_request_mutex);
|
||||||
auto* request = np_auth_find_request(req_id);
|
auto* request = np_auth_find_request(req_id);
|
||||||
if (request == nullptr) {
|
if (request == nullptr) {
|
||||||
return NP_AUTH_ERROR_REQUEST_NOT_FOUND;
|
return NP_AUTH_ERROR_REQUEST_NOT_FOUND;
|
||||||
}
|
}
|
||||||
if (request->state == NpAuthRequestState::Aborted) {
|
return np_auth_complete_unavailable(request, param->user_id);
|
||||||
// request->result = 0;
|
|
||||||
// return 0;
|
|
||||||
request->result = NP_AUTH_ERROR_ABORTED;
|
|
||||||
return NP_AUTH_ERROR_ABORTED;
|
|
||||||
}
|
|
||||||
// request->state = NpAuthRequestState::Complete;
|
|
||||||
// request->result = 0;
|
|
||||||
|
|
||||||
// return 0;
|
|
||||||
return np_auth_complete_signed_out(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIB_DEFINE(InitNet_1_NpAuth) {
|
LIB_DEFINE(InitNet_1_NpAuth) {
|
||||||
|
|||||||
+70
-46
@@ -4002,6 +4002,11 @@ struct NpCountryCode {
|
|||||||
char padding[1];
|
char padding[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NpLanguageCode {
|
||||||
|
char code[36];
|
||||||
|
char padding[12];
|
||||||
|
};
|
||||||
|
|
||||||
struct NpAgeRestriction {
|
struct NpAgeRestriction {
|
||||||
NpCountryCode country_code;
|
NpCountryCode country_code;
|
||||||
int8_t age;
|
int8_t age;
|
||||||
@@ -4056,8 +4061,23 @@ constexpr int np_error_aborted = -2141913070; /* 0x8055
|
|||||||
constexpr int np_error_request_max = -2141913069; /* 0x80550013 */
|
constexpr int np_error_request_max = -2141913069; /* 0x80550013 */
|
||||||
constexpr int np_error_request_not_found = -2141913068; /* 0x80550014 */
|
constexpr int np_error_request_not_found = -2141913068; /* 0x80550014 */
|
||||||
constexpr int np_error_invalid_id = -2141913067; /* 0x80550015 */
|
constexpr int np_error_invalid_id = -2141913067; /* 0x80550015 */
|
||||||
|
constexpr int np_error_network_not_available = -2141872086; /* 0x8055a02a */
|
||||||
constexpr int np_request_max = 128;
|
constexpr int np_request_max = 128;
|
||||||
constexpr uint32_t np_state_signed_out = 1;
|
constexpr uint32_t np_state_signed_out = 1;
|
||||||
|
constexpr uint32_t np_state_signed_in = 2;
|
||||||
|
|
||||||
|
// A simulated account belongs only to the primary user and survives network loss.
|
||||||
|
bool IsSignedIn(int user_id) {
|
||||||
|
return Config::PsnEmulationEnabled() && user_id == Config::GetUserId();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int np_reachability_result(int user_id) {
|
||||||
|
if (!IsSignedIn(user_id)) {
|
||||||
|
return np_error_signed_out;
|
||||||
|
}
|
||||||
|
// This is an explicit compatibility simulation, not a connection to PSN.
|
||||||
|
return NetCtl::NetCtlConnected() ? OK : np_error_network_not_available;
|
||||||
|
}
|
||||||
|
|
||||||
struct NpStateCallback {
|
struct NpStateCallback {
|
||||||
NpStateCallbackA callback = nullptr;
|
NpStateCallbackA callback = nullptr;
|
||||||
@@ -4117,7 +4137,7 @@ static NpRequest* np_get_request_locked(int req_id) {
|
|||||||
return &g_np_requests[index];
|
return &g_np_requests[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int np_complete_signed_out_locked(NpRequest* request) {
|
static int np_complete_locked(NpRequest* request, int result) {
|
||||||
if (request->state == NpRequestState::Complete) {
|
if (request->state == NpRequestState::Complete) {
|
||||||
request->result = np_error_invalid_argument;
|
request->result = np_error_invalid_argument;
|
||||||
return np_error_invalid_argument;
|
return np_error_invalid_argument;
|
||||||
@@ -4128,9 +4148,9 @@ static int np_complete_signed_out_locked(NpRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
request->state = NpRequestState::Complete;
|
request->state = NpRequestState::Complete;
|
||||||
request->result = np_error_signed_out;
|
request->result = result;
|
||||||
|
|
||||||
return (request->async ? OK : np_error_signed_out);
|
return (request->async ? OK : result);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpCheckCallback() {
|
int KYTY_SYSV_ABI NpCheckCallback() {
|
||||||
@@ -4144,7 +4164,9 @@ int KYTY_SYSV_ABI NpCheckCallback() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& entry: pending) {
|
for (const auto& entry: pending) {
|
||||||
entry.callback(Config::GetUserId(), np_state_signed_out, entry.userdata);
|
entry.callback(Config::GetUserId(),
|
||||||
|
IsSignedIn(Config::GetUserId()) ? np_state_signed_in : np_state_signed_out,
|
||||||
|
entry.userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -4239,12 +4261,13 @@ int KYTY_SYSV_ABI NpGetNpId(int user_id, NpId* np_id) {
|
|||||||
|
|
||||||
EXIT_NOT_IMPLEMENTED(np_id == nullptr);
|
EXIT_NOT_IMPLEMENTED(np_id == nullptr);
|
||||||
|
|
||||||
// int s = snprintf(np_id->handle.data, 16, "Kyty");
|
|
||||||
// EXIT_NOT_IMPLEMENTED(s >= 16);
|
|
||||||
// np_id->handle.term = 0;
|
|
||||||
std::memset(np_id, 0, sizeof(*np_id));
|
std::memset(np_id, 0, sizeof(*np_id));
|
||||||
|
|
||||||
// return OK;
|
if (IsSignedIn(user_id)) {
|
||||||
|
std::memcpy(np_id->handle.data, "Kyty", 4);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
return np_error_signed_out;
|
return np_error_signed_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4255,12 +4278,13 @@ int KYTY_SYSV_ABI NpGetOnlineId(int user_id, NpOnlineId* online_id) {
|
|||||||
|
|
||||||
EXIT_NOT_IMPLEMENTED(online_id == nullptr);
|
EXIT_NOT_IMPLEMENTED(online_id == nullptr);
|
||||||
|
|
||||||
// int s = snprintf(online_id->data, 16, "Kyty");
|
|
||||||
// EXIT_NOT_IMPLEMENTED(s >= 16);
|
|
||||||
// online_id->term = 0;
|
|
||||||
std::memset(online_id, 0, sizeof(*online_id));
|
std::memset(online_id, 0, sizeof(*online_id));
|
||||||
|
|
||||||
// return OK;
|
if (IsSignedIn(user_id)) {
|
||||||
|
std::memcpy(online_id->data, "Kyty", 4);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
return np_error_signed_out;
|
return np_error_signed_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4271,10 +4295,13 @@ int KYTY_SYSV_ABI NpGetAccountIdA(int user_id, uint64_t* account_id) {
|
|||||||
|
|
||||||
EXIT_NOT_IMPLEMENTED(account_id == nullptr);
|
EXIT_NOT_IMPLEMENTED(account_id == nullptr);
|
||||||
|
|
||||||
// *account_id = 0x00000000feedfaceull;
|
|
||||||
*account_id = 0;
|
*account_id = 0;
|
||||||
|
|
||||||
// return OK;
|
if (IsSignedIn(user_id)) {
|
||||||
|
*account_id = 0x00000000feedfaceull;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
return np_error_signed_out;
|
return np_error_signed_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4287,10 +4314,12 @@ int KYTY_SYSV_ABI NpGetAccountCountryA(int user_id, void* country_code) {
|
|||||||
|
|
||||||
auto* code = static_cast<NpCountryCode*>(country_code);
|
auto* code = static_cast<NpCountryCode*>(country_code);
|
||||||
std::memset(code, 0, sizeof(*code));
|
std::memset(code, 0, sizeof(*code));
|
||||||
// code->data[0] = '';
|
|
||||||
// code->data[1] = 'S';
|
|
||||||
|
|
||||||
// return OK;
|
if (IsSignedIn(user_id)) {
|
||||||
|
std::memcpy(code->data, "US", 2);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
return np_error_signed_out;
|
return np_error_signed_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4305,11 +4334,14 @@ int KYTY_SYSV_ABI NpGetAccountAge(int req_id, int user_id, uint8_t* age) {
|
|||||||
return np_error_invalid_argument;
|
return np_error_invalid_argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *age = 21;
|
std::lock_guard lock(g_np_request_mutex);
|
||||||
*age = 0;
|
auto* request = np_get_request_locked(req_id);
|
||||||
|
if (request == nullptr) {
|
||||||
|
return np_error_request_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
// return OK;
|
*age = IsSignedIn(user_id) ? 21 : 0;
|
||||||
return np_error_signed_out;
|
return np_complete_locked(request, IsSignedIn(user_id) ? OK : np_error_signed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpGetAccountLanguage2(int req_id, int user_id, void* language_code) {
|
int KYTY_SYSV_ABI NpGetAccountLanguage2(int req_id, int user_id, void* language_code) {
|
||||||
@@ -4325,11 +4357,17 @@ int KYTY_SYSV_ABI NpGetAccountLanguage2(int req_id, int user_id, void* language_
|
|||||||
|
|
||||||
std::lock_guard lock(g_np_request_mutex);
|
std::lock_guard lock(g_np_request_mutex);
|
||||||
|
|
||||||
if (np_get_request_locked(req_id) == nullptr) {
|
auto* request = np_get_request_locked(req_id);
|
||||||
|
if (request == nullptr) {
|
||||||
return np_error_request_not_found;
|
return np_error_request_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
return np_error_signed_out;
|
auto* code = static_cast<NpLanguageCode*>(language_code);
|
||||||
|
std::memset(code, 0, sizeof(*code));
|
||||||
|
if (IsSignedIn(user_id)) {
|
||||||
|
std::memcpy(code->code, "en-US", 5);
|
||||||
|
}
|
||||||
|
return np_complete_locked(request, IsSignedIn(user_id) ? OK : np_error_signed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpCreateRequest() {
|
int KYTY_SYSV_ABI NpCreateRequest() {
|
||||||
@@ -4428,8 +4466,9 @@ int KYTY_SYSV_ABI NpCheckNpAvailability(int req_id, const char* user, void* resu
|
|||||||
return np_error_request_not_found;
|
return np_error_request_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return OK;
|
return np_complete_locked(request, std::strcmp(user, "Kyty") == 0
|
||||||
return np_complete_signed_out_locked(request);
|
? np_reachability_result(Config::GetUserId())
|
||||||
|
: np_error_signed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpCheckNpReachability(int req_id, int user_id) {
|
int KYTY_SYSV_ABI NpCheckNpReachability(int req_id, int user_id) {
|
||||||
@@ -4451,8 +4490,7 @@ int KYTY_SYSV_ABI NpCheckNpReachability(int req_id, int user_id) {
|
|||||||
return np_error_request_not_found;
|
return np_error_request_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return OK;
|
return np_complete_locked(request, np_reachability_result(user_id));
|
||||||
return np_complete_signed_out_locked(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpPollAsync(int req_id, int* result) {
|
int KYTY_SYSV_ABI NpPollAsync(int req_id, int* result) {
|
||||||
@@ -4509,23 +4547,10 @@ int KYTY_SYSV_ABI NpCheckPremium(int req_id, const NpCheckPremiumParameter* para
|
|||||||
return np_error_request_not_found;
|
return np_error_request_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->state == NpRequestState::Complete) {
|
|
||||||
request->result = np_error_invalid_argument;
|
|
||||||
return np_error_invalid_argument;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request->state == NpRequestState::Aborted) {
|
|
||||||
return np_error_aborted;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::memset(result, 0, sizeof(*result));
|
std::memset(result, 0, sizeof(*result));
|
||||||
// result->authorized = true;
|
|
||||||
|
|
||||||
// request->state = NpRequestState::Complete;
|
// The simulated account has no premium eligibility.
|
||||||
// request->result = OK;
|
return np_complete_locked(request, np_reachability_result(param->user_id));
|
||||||
|
|
||||||
// return OK;
|
|
||||||
return np_complete_signed_out_locked(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state) {
|
int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state) {
|
||||||
@@ -4535,7 +4560,7 @@ int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state) {
|
|||||||
|
|
||||||
LOGF("\t user_id = %d\n", user_id);
|
LOGF("\t user_id = %d\n", user_id);
|
||||||
|
|
||||||
*state = np_state_signed_out;
|
*state = IsSignedIn(user_id) ? np_state_signed_in : np_state_signed_out;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -4549,8 +4574,7 @@ int KYTY_SYSV_ABI NpGetNpReachabilityState(int user_id, uint32_t* state) {
|
|||||||
|
|
||||||
LOGF("\t user_id = %d\n", user_id);
|
LOGF("\t user_id = %d\n", user_id);
|
||||||
|
|
||||||
// *state = 2; // SCE_NP_REACHABILITY_STATE_REACHABLE
|
*state = np_reachability_result(user_id) == OK ? 2 : 0; // REACHABLE / UNAVAILABLE
|
||||||
*state = 0; // SCE_NP_REACHABILITY_STATE_UNAVAILABLE
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -4564,7 +4588,7 @@ int KYTY_SYSV_ABI NpHasSignedUp(int user_id, bool* has_signed_up) {
|
|||||||
|
|
||||||
LOGF("\t user_id = %d\n", user_id);
|
LOGF("\t user_id = %d\n", user_id);
|
||||||
|
|
||||||
*has_signed_up = false;
|
*has_signed_up = IsSignedIn(user_id);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,8 @@ struct NpCheckPremiumResult;
|
|||||||
|
|
||||||
using NpStateCallbackA = KYTY_SYSV_ABI void (*)(int user_id, uint32_t state, void* userdata);
|
using NpStateCallbackA = KYTY_SYSV_ABI void (*)(int user_id, uint32_t state, void* userdata);
|
||||||
|
|
||||||
|
bool IsSignedIn(int user_id);
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NpCheckCallback();
|
int KYTY_SYSV_ABI NpCheckCallback();
|
||||||
int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret);
|
int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret);
|
||||||
int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction);
|
int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction);
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ static void PrintUsage() {
|
|||||||
::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n");
|
::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n");
|
||||||
::printf(" --vulkan-validation Enable Vulkan validation.\n");
|
::printf(" --vulkan-validation Enable Vulkan validation.\n");
|
||||||
::printf(" --network-connected Use the host local network.\n");
|
::printf(" --network-connected Use the host local network.\n");
|
||||||
|
::printf(" --emulate-psn Simulate PSN sign-in for compatibility.\n");
|
||||||
::printf(" --gpu-assisted-validation Bounds-check shader accesses on the GPU.\n"
|
::printf(" --gpu-assisted-validation Bounds-check shader accesses on the GPU.\n"
|
||||||
" Implies --vulkan-validation; very slow.\n");
|
" Implies --vulkan-validation; very slow.\n");
|
||||||
::printf(" --shader-validation Enable shader validation.\n");
|
::printf(" --shader-validation Enable shader validation.\n");
|
||||||
@@ -206,6 +207,7 @@ static constexpr Flag FLAGS[] = {
|
|||||||
{"--vr", &ConfigOptions::vr_enabled},
|
{"--vr", &ConfigOptions::vr_enabled},
|
||||||
{"--amd-cpu", &ConfigOptions::amd_cpu_enabled},
|
{"--amd-cpu", &ConfigOptions::amd_cpu_enabled},
|
||||||
{"--network-connected", &ConfigOptions::network_connected},
|
{"--network-connected", &ConfigOptions::network_connected},
|
||||||
|
{"--emulate-psn", &ConfigOptions::psn_emulation_enabled},
|
||||||
{"--vulkan-validation", &ConfigOptions::vulkan_validation_enabled},
|
{"--vulkan-validation", &ConfigOptions::vulkan_validation_enabled},
|
||||||
{"--gpu-assisted-validation", &ConfigOptions::gpu_assisted_validation_enabled},
|
{"--gpu-assisted-validation", &ConfigOptions::gpu_assisted_validation_enabled},
|
||||||
{"--shader-validation", &ConfigOptions::shader_validation_enabled},
|
{"--shader-validation", &ConfigOptions::shader_validation_enabled},
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ namespace Libs::LibNpCommerce {
|
|||||||
void InitNet_1_NpCommerce(Loader::SymbolDatabase *symbols);
|
void InitNet_1_NpCommerce(Loader::SymbolDatabase *symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Libs::LibNpAuth {
|
||||||
|
void InitNet_1_NpAuth(Loader::SymbolDatabase *symbols);
|
||||||
|
}
|
||||||
|
|
||||||
namespace Libs::LibNpEntitlementAccess {
|
namespace Libs::LibNpEntitlementAccess {
|
||||||
void InitNet_1_NpEntitlementAccess(Loader::SymbolDatabase *symbols);
|
void InitNet_1_NpEntitlementAccess(Loader::SymbolDatabase *symbols);
|
||||||
}
|
}
|
||||||
@@ -2082,6 +2086,256 @@ void TestNetCtlHostIpv4() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <int Mode>
|
||||||
|
void KYTY_SYSV_ABI RecordNpState(int user_id, uint32_t state, void* arg) {
|
||||||
|
auto& event = *static_cast<std::array<int, 3>*>(arg);
|
||||||
|
++event[0];
|
||||||
|
event[1] = user_id;
|
||||||
|
event[2] = static_cast<int>(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestNpEmulation() {
|
||||||
|
using namespace Libs::Network::NpManager;
|
||||||
|
using namespace Libs::Network::NetCtl;
|
||||||
|
constexpr int SignedOut = static_cast<int>(0x80550006u);
|
||||||
|
constexpr int NetworkUnavailable = static_cast<int>(0x8055a02au);
|
||||||
|
constexpr int Aborted = static_cast<int>(0x80550012u);
|
||||||
|
struct AsyncParameters {
|
||||||
|
size_t size = sizeof(AsyncParameters);
|
||||||
|
uint64_t affinity = 0;
|
||||||
|
int priority = 0;
|
||||||
|
uint8_t padding[4] {};
|
||||||
|
} async_parameters;
|
||||||
|
struct PremiumParameters {
|
||||||
|
size_t size = sizeof(PremiumParameters);
|
||||||
|
int user_id = 0;
|
||||||
|
uint8_t padding[4] {};
|
||||||
|
uint64_t features = 1;
|
||||||
|
uint8_t reserved[32] {};
|
||||||
|
} premium_parameters;
|
||||||
|
struct PremiumResult {
|
||||||
|
bool authorized = true;
|
||||||
|
uint8_t reserved[32] {};
|
||||||
|
} premium_result;
|
||||||
|
|
||||||
|
const auto create_request = [&] (bool async) {
|
||||||
|
const int request = async
|
||||||
|
? NpCreateAsyncRequest(reinterpret_cast<const NpCreateAsyncRequestParameter*>(
|
||||||
|
&async_parameters))
|
||||||
|
: NpCreateRequest();
|
||||||
|
Check(request > 0, "create NP request");
|
||||||
|
return request;
|
||||||
|
};
|
||||||
|
const auto check_request = [&] (bool async, int expected, auto operation) {
|
||||||
|
const int request = create_request(async);
|
||||||
|
Check(operation(request) == (async ? OK : expected),
|
||||||
|
"NP call separates asynchronous submission from its execution result");
|
||||||
|
if (async) {
|
||||||
|
int result = 123;
|
||||||
|
Check(NpPollAsync(request, &result) == OK && result == expected,
|
||||||
|
"NP polling reports the completed operation result");
|
||||||
|
}
|
||||||
|
Check(NpDeleteRequest(request) == OK, "release completed NP request");
|
||||||
|
};
|
||||||
|
|
||||||
|
Config::ConfigOptions options;
|
||||||
|
options.printf_direction = Config::LogDirection::Silent;
|
||||||
|
Check(!options.network_connected && !options.psn_emulation_enabled,
|
||||||
|
"host networking and PSN emulation both require explicit opt-in");
|
||||||
|
static std::array<std::array<int, 3>, 4> events {};
|
||||||
|
const std::array<NpStateCallbackA, 4> callbacks {
|
||||||
|
RecordNpState<0>, RecordNpState<1>, RecordNpState<2>, RecordNpState<3>};
|
||||||
|
int mode = 0;
|
||||||
|
for (bool network : {false, true}) {
|
||||||
|
int previous_network_state = -1;
|
||||||
|
for (bool emulate : {false, true}) {
|
||||||
|
options.network_connected = network;
|
||||||
|
options.psn_emulation_enabled = emulate;
|
||||||
|
Config::Load(options);
|
||||||
|
Check(Config::IsNetworkConnected() == network && Config::PsnEmulationEnabled() == emulate,
|
||||||
|
"loading PSN emulation does not change the independent network option");
|
||||||
|
Check(NetCtlInit() == OK, "initialize network state for NP mode");
|
||||||
|
int network_state = -1;
|
||||||
|
Check(NetCtlGetState(&network_state) == OK && (network || network_state == 0),
|
||||||
|
"PSN emulation cannot connect disabled host networking");
|
||||||
|
Check(previous_network_state == -1 || previous_network_state == network_state,
|
||||||
|
"PSN emulation does not change host network connectivity");
|
||||||
|
previous_network_state = network_state;
|
||||||
|
const bool connected = network_state == 3;
|
||||||
|
|
||||||
|
Check(NpRegisterStateCallbackA(callbacks[mode], &events[mode]) > 0 &&
|
||||||
|
NpCheckCallback() == OK && events[mode][0] == 1 &&
|
||||||
|
events[mode][1] == Config::GetUserId() &&
|
||||||
|
events[mode][2] == (emulate ? 2 : 1),
|
||||||
|
"initial NP callback matches the selected emulated sign-in state");
|
||||||
|
++mode;
|
||||||
|
for (int player = 0; player < Config::MAX_PLAYERS; ++player) {
|
||||||
|
const int user_id = Config::GetPlayerUserId(player);
|
||||||
|
const bool signed_in = emulate && player == 0;
|
||||||
|
const int identity_result = signed_in ? OK : SignedOut;
|
||||||
|
const int online_result = !signed_in ? SignedOut : connected ? OK : NetworkUnavailable;
|
||||||
|
uint32_t state = 99;
|
||||||
|
bool signed_up = false;
|
||||||
|
Check(NpGetState(user_id, &state) == OK && state == (signed_in ? 2u : 1u) &&
|
||||||
|
NpHasSignedUp(user_id, &signed_up) == OK && signed_up == signed_in,
|
||||||
|
"only the primary emulated user has a persistent signed-in account");
|
||||||
|
Check(NpGetNpReachabilityState(user_id, &state) == OK &&
|
||||||
|
state == (signed_in && connected ? 2u : 0u),
|
||||||
|
"NP reachability requires both the emulated account and host connectivity");
|
||||||
|
|
||||||
|
uint64_t account_id = 0;
|
||||||
|
std::array<char, 20> online_id {};
|
||||||
|
std::array<char, 36> np_id {};
|
||||||
|
std::array<char, 4> country {};
|
||||||
|
Check(NpGetAccountIdA(user_id, &account_id) == identity_result &&
|
||||||
|
NpGetOnlineId(user_id, reinterpret_cast<NpOnlineId*>(online_id.data())) ==
|
||||||
|
identity_result &&
|
||||||
|
NpGetNpId(user_id, reinterpret_cast<NpId*>(np_id.data())) == identity_result &&
|
||||||
|
NpGetAccountCountryA(user_id, country.data()) == identity_result,
|
||||||
|
"NP identity and account-country getters agree on primary and guest sign-in");
|
||||||
|
if (signed_in) {
|
||||||
|
Check(account_id != 0 && online_id[0] != 0 && online_id[16] == 0 &&
|
||||||
|
std::strcmp(online_id.data(), np_id.data()) == 0 &&
|
||||||
|
country[0] != 0 && country[1] != 0 && country[2] == 0,
|
||||||
|
"emulated account identity and country remain usable while disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bool async : {false, true}) {
|
||||||
|
check_request(async, online_result, [&] (int request) {
|
||||||
|
return NpCheckNpReachability(request, user_id);
|
||||||
|
});
|
||||||
|
uint8_t age = 0;
|
||||||
|
check_request(async, identity_result, [&] (int request) {
|
||||||
|
return NpGetAccountAge(request, user_id, &age);
|
||||||
|
});
|
||||||
|
std::array<char, 48> language {};
|
||||||
|
check_request(async, identity_result, [&] (int request) {
|
||||||
|
return NpGetAccountLanguage2(request, user_id, language.data());
|
||||||
|
});
|
||||||
|
Check(!signed_in || (age > 0 && language[0] != 0 && language[35] == 0),
|
||||||
|
"signed-in account metadata is available independently of host networking");
|
||||||
|
premium_parameters.user_id = user_id;
|
||||||
|
premium_result.authorized = true;
|
||||||
|
check_request(async, online_result, [&] (int request) {
|
||||||
|
return NpCheckPremium(request,
|
||||||
|
reinterpret_cast<const NpCheckPremiumParameter*>(&premium_parameters),
|
||||||
|
reinterpret_cast<NpCheckPremiumResult*>(&premium_result));
|
||||||
|
});
|
||||||
|
Check(!premium_result.authorized, "PSN emulation does not grant premium eligibility");
|
||||||
|
if (player == 0) {
|
||||||
|
check_request(async, online_result, [&] (int request) {
|
||||||
|
return NpCheckNpAvailability(request, "Kyty", nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int aborted = create_request(true);
|
||||||
|
int result = 123;
|
||||||
|
Check(NpAbortRequest(aborted) == OK &&
|
||||||
|
NpCheckNpReachability(aborted, Config::GetUserId()) == Aborted &&
|
||||||
|
NpPollAsync(aborted, &result) == OK && result == Aborted &&
|
||||||
|
NpDeleteRequest(aborted) == OK,
|
||||||
|
"NP emulation does not turn an aborted request into a successful one");
|
||||||
|
NetCtlTerm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Config::Load(Config::ConfigOptions {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestNpAuthEmulation() {
|
||||||
|
Loader::SymbolDatabase symbols;
|
||||||
|
Libs::LibNpAuth::InitNet_1_NpAuth(&symbols);
|
||||||
|
const auto resolve = [&] (const char* nid) {
|
||||||
|
const auto* symbol = symbols.FindByNid(nid, Loader::SymbolType::Func);
|
||||||
|
Check(symbol != nullptr, "resolve NP authentication exports");
|
||||||
|
return symbol->vaddr;
|
||||||
|
};
|
||||||
|
const auto create = reinterpret_cast<int(KYTY_SYSV_ABI*)()>(resolve("6bwFkosYRQg"));
|
||||||
|
const auto create_async = reinterpret_cast<int(KYTY_SYSV_ABI*)(const void*)>(
|
||||||
|
resolve("N+mr7GjTvr8"));
|
||||||
|
const auto destroy = reinterpret_cast<int(KYTY_SYSV_ABI*)(int)>(resolve("H8wG9Bk-nPc"));
|
||||||
|
const auto poll = reinterpret_cast<int(KYTY_SYSV_ABI*)(int, int*)>(resolve("gjSyfzSsDcE"));
|
||||||
|
const auto get_code = reinterpret_cast<int(KYTY_SYSV_ABI*)(int, const void*, void*, int*)>(
|
||||||
|
resolve("KI4dHLlTNl0"));
|
||||||
|
const auto get_token = reinterpret_cast<int(KYTY_SYSV_ABI*)(int, const void*, void*)>(
|
||||||
|
resolve("RdsFVsgSpZY"));
|
||||||
|
constexpr int InvalidArgument = static_cast<int>(0x80550301u);
|
||||||
|
constexpr int InvalidSize = static_cast<int>(0x80550302u);
|
||||||
|
constexpr int ServiceUnavailable = static_cast<int>(0x80550401u);
|
||||||
|
constexpr int SignedOut = static_cast<int>(0x80550006u);
|
||||||
|
struct AuthorizationCodeParameters {
|
||||||
|
size_t size = sizeof(AuthorizationCodeParameters);
|
||||||
|
int user_id = 0;
|
||||||
|
uint8_t padding[4] {};
|
||||||
|
const void* client_id = "test-client";
|
||||||
|
const char* scope = "test-scope";
|
||||||
|
} code_parameters;
|
||||||
|
struct IdTokenParameters {
|
||||||
|
size_t size = sizeof(IdTokenParameters);
|
||||||
|
int user_id = 0;
|
||||||
|
uint8_t padding[4] {};
|
||||||
|
const void* client_id = "test-client";
|
||||||
|
const void* client_secret = "test-secret";
|
||||||
|
const char* scope = "test-scope";
|
||||||
|
} token_parameters;
|
||||||
|
std::array<uint8_t, 136> code {};
|
||||||
|
std::array<uint8_t, 4104> token {};
|
||||||
|
const std::array<uint64_t, 3> async_parameters {24, 0, 0};
|
||||||
|
int issuer = 0;
|
||||||
|
const int invalid_request = create();
|
||||||
|
code_parameters.size = 0;
|
||||||
|
token_parameters.size = 0;
|
||||||
|
Check(invalid_request > 0 &&
|
||||||
|
get_code(invalid_request, nullptr, code.data(), &issuer) == InvalidArgument &&
|
||||||
|
get_token(invalid_request, nullptr, token.data()) == InvalidArgument &&
|
||||||
|
get_code(invalid_request, &code_parameters, code.data(), &issuer) == InvalidSize &&
|
||||||
|
get_token(invalid_request, &token_parameters, token.data()) == InvalidSize &&
|
||||||
|
destroy(invalid_request) == OK,
|
||||||
|
"NP authentication rejects missing and undersized user parameters");
|
||||||
|
code_parameters.size = sizeof(code_parameters);
|
||||||
|
token_parameters.size = sizeof(token_parameters);
|
||||||
|
|
||||||
|
Config::ConfigOptions options;
|
||||||
|
options.printf_direction = Config::LogDirection::Silent;
|
||||||
|
for (bool network : {false, true}) {
|
||||||
|
for (bool emulate : {false, true}) {
|
||||||
|
options.network_connected = network;
|
||||||
|
options.psn_emulation_enabled = emulate;
|
||||||
|
Config::Load(options);
|
||||||
|
for (int player = 0; player < Config::MAX_PLAYERS; ++player) {
|
||||||
|
code_parameters.user_id = Config::GetPlayerUserId(player);
|
||||||
|
token_parameters.user_id = code_parameters.user_id;
|
||||||
|
const int expected = emulate && player == 0 ? ServiceUnavailable : SignedOut;
|
||||||
|
for (bool async : {false, true}) {
|
||||||
|
for (bool id_token : {false, true}) {
|
||||||
|
const int request = async ? create_async(async_parameters.data()) : create();
|
||||||
|
Check(request > 0, "create NP authentication request");
|
||||||
|
code.fill(0xff);
|
||||||
|
token.fill(0xff);
|
||||||
|
issuer = -1;
|
||||||
|
const int result = id_token
|
||||||
|
? get_token(request, &token_parameters, token.data())
|
||||||
|
: get_code(request, &code_parameters, code.data(), &issuer);
|
||||||
|
Check(result == (async ? OK : expected),
|
||||||
|
"NP authentication distinguishes an unavailable service from sign-out");
|
||||||
|
if (async) {
|
||||||
|
int completion = 123;
|
||||||
|
Check(poll(request, &completion) == OK && completion == expected,
|
||||||
|
"asynchronous NP authentication delivers the actual failure");
|
||||||
|
}
|
||||||
|
const auto zero = [] (uint8_t value) { return value == 0; };
|
||||||
|
Check(id_token ? std::all_of(token.begin(), token.end(), zero)
|
||||||
|
: std::all_of(code.begin(), code.end(), zero) && issuer == 0,
|
||||||
|
"PSN emulation does not fabricate authorization codes or ID tokens");
|
||||||
|
Check(destroy(request) == OK, "release NP authentication request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Config::Load(Config::ConfigOptions {});
|
||||||
|
}
|
||||||
|
|
||||||
void CheckEtherAddressFormatting() {
|
void CheckEtherAddressFormatting() {
|
||||||
Loader::SymbolDatabase symbols;
|
Loader::SymbolDatabase symbols;
|
||||||
Libs::LibNet::InitNet_1_Net(&symbols);
|
Libs::LibNet::InitNet_1_Net(&symbols);
|
||||||
@@ -2458,6 +2712,17 @@ int main(int argc, char** argv) {
|
|||||||
Config::Load(options);
|
Config::Load(options);
|
||||||
subsystems.Initialize<Log::Lifecycle>();
|
subsystems.Initialize<Log::Lifecycle>();
|
||||||
|
|
||||||
|
if (argc == 2 && std::string_view(argv[1]) == "--network-only") {
|
||||||
|
#if defined(__linux__)
|
||||||
|
TestNetCtlHostIpv4();
|
||||||
|
#endif
|
||||||
|
TestNpEmulation();
|
||||||
|
TestNpAuthEmulation();
|
||||||
|
subsystems.Destroy();
|
||||||
|
std::printf("KernelFileSystemTests: network cases passed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
TestMutexHandoff();
|
TestMutexHandoff();
|
||||||
if (argc == 2 && std::string_view(argv[1]) == "--mutex-only") {
|
if (argc == 2 && std::string_view(argv[1]) == "--mutex-only") {
|
||||||
subsystems.Destroy();
|
subsystems.Destroy();
|
||||||
@@ -2503,6 +2768,8 @@ int main(int argc, char** argv) {
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
TestNetCtlHostIpv4();
|
TestNetCtlHostIpv4();
|
||||||
#endif
|
#endif
|
||||||
|
TestNpEmulation();
|
||||||
|
TestNpAuthEmulation();
|
||||||
TestNpWebApi2Memory();
|
TestNpWebApi2Memory();
|
||||||
TestNpCommerceDialog();
|
TestNpCommerceDialog();
|
||||||
graphics.reset();
|
graphics.reset();
|
||||||
|
|||||||
Reference in new issue
Block a user