├── .gitignore ├── PsPcSdkEmulator ├── external │ └── detours │ │ ├── src │ │ ├── disolarm.cpp │ │ ├── disolx64.cpp │ │ ├── disolx86.cpp │ │ ├── disolarm64.cpp │ │ ├── disolia64.cpp │ │ └── uimports.cpp │ │ ├── include │ │ └── detver.h │ │ └── LICENSE ├── src │ ├── loader │ │ ├── cert.pfx │ │ ├── dllmain.h │ │ ├── hooks.h │ │ ├── proxy.def │ │ ├── procs.h │ │ ├── procs.c │ │ ├── resource.rc │ │ ├── dllmain.cpp │ │ ├── proxy.asm │ │ └── hooks.cpp │ ├── sdk │ │ ├── np │ │ │ ├── auth.h │ │ │ ├── session.h │ │ │ ├── misc.h │ │ │ ├── uds.h │ │ │ ├── webapi2.h │ │ │ ├── account.h │ │ │ ├── callback.h │ │ │ ├── trophy.cpp │ │ │ ├── misc.cpp │ │ │ ├── callback.cpp │ │ │ ├── account.cpp │ │ │ ├── session.cpp │ │ │ ├── auth.cpp │ │ │ ├── webapi2.cpp │ │ │ └── uds.cpp │ │ ├── sce.h │ │ ├── dialog │ │ │ ├── signin.h │ │ │ ├── common.h │ │ │ ├── common.cpp │ │ │ ├── msg.cpp │ │ │ └── signin.cpp │ │ ├── service │ │ │ ├── system.h │ │ │ ├── user.h │ │ │ ├── system.cpp │ │ │ └── user.cpp │ │ ├── pc.h │ │ ├── rudp │ │ │ └── rudp.cpp │ │ ├── pc.cpp │ │ ├── voicechat │ │ │ └── voicechat.cpp │ │ └── sceerror.h │ ├── net │ │ ├── net.h │ │ ├── psscloud.h │ │ ├── http.h │ │ ├── pssresponses.h │ │ ├── psscloud.cpp │ │ ├── net.cpp │ │ └── http.cpp │ ├── utils.cpp │ └── utils.h ├── RunMakeCert.bat ├── MakeCert.ps1 └── PsPcSdkEmulator.vcxproj ├── PsPcSdkEmulator.sln ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/* 2 | **/x64/* 3 | *.aps 4 | *.vcxproj.filters 5 | *.vcxproj.user 6 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/src/disolarm.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_ARM_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/src/disolx64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_X64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/src/disolx86.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_X86_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/src/disolarm64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_ARM64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/src/disolia64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_IA64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/cert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LNDF/PsPcSdkEmulator/HEAD/PsPcSdkEmulator/src/loader/cert.pfx -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/auth.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | void np_auth_reset(); 11 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/dllmain.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | extern wchar_t* g_cuurent_dll_path; -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/session.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | void np_session_reset(); 11 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/net.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | void pspcsdk_net_setup(); 11 | void pspcsdk_net_cleanup(); 12 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/hooks.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | void pspcsdk_hooks_setup(); 11 | void pspcsdk_hooks_cleanup(); 12 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/psscloud.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #define PSSCLOUD_SERVER_PORT 21563 11 | 12 | void psscloud_server_start(); 13 | void psscloud_server_stop(); 14 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/proxy.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | GetFileVersionInfoA 3 | GetFileVersionInfoByHandle 4 | GetFileVersionInfoExA 5 | GetFileVersionInfoExW 6 | GetFileVersionInfoSizeA 7 | GetFileVersionInfoSizeExA 8 | GetFileVersionInfoSizeExW 9 | GetFileVersionInfoSizeW 10 | GetFileVersionInfoW 11 | VerFindFileA 12 | VerFindFileW 13 | VerInstallFileA 14 | VerInstallFileW 15 | VerLanguageNameA 16 | VerLanguageNameW 17 | VerQueryValueA 18 | VerQueryValueW 19 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/misc.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | struct SceNpPremiumInfo { 13 | int64_t unknown; 14 | int64_t unknown2; 15 | int64_t unknown3; 16 | int64_t unknown4; 17 | char reserved[0x18]; 18 | }; 19 | 20 | void np_reset(); 21 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/uds.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | struct SceNpUniversalDataSystemInitParams { 13 | uint64_t size; // apparently always 0x118 14 | uint64_t unknown2; // non-zero 15 | char path[272]; 16 | }; 17 | 18 | void np_uds_reset(); 19 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/sce.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "sceerror.h" 11 | #include 12 | 13 | #define PSPCSDK_API extern "C" __declspec(dllexport) 14 | 15 | #define PSPCSDK_STUB(name) PSPCSDK_API SceResult name() {printf("(STUBBED) " #name "()\n");return SCE_OK;} 16 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/procs.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | extern const char* g_exports_dll_proc_names[17]; 17 | extern FARPROC g_version_dll_procs[17]; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/webapi2.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #define SCE_NP_WEB_API2_MAX_CONTEXTS 0X7fff 13 | 14 | struct SceNpNpWebApi2ContextNode { 15 | int16_t context = 0; 16 | SceNpNpWebApi2ContextNode* next = nullptr; 17 | }; 18 | 19 | void np_web_api2_reset(); 20 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/account.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | #include 10 | 11 | typedef uint32_t SceNpState; 12 | 13 | struct SceNpOnlineId { 14 | char name[16]; 15 | char term; 16 | char reserved[3]; 17 | }; 18 | 19 | #define SCE_NP_STATUS_UNKNOW 0x0 20 | #define SCE_NP_STATUS_LOGGED_OUT 0x1 21 | #define SCE_NP_STATUS_LOGGED_IN 0x2 22 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/dialog/signin.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "common.h" 11 | 12 | struct SceSigninDialogParam { 13 | SceDialogCommonParam common; 14 | int unknown0; 15 | int desired_user_id; 16 | void* unknown1; 17 | char reserved[8]; 18 | }; 19 | 20 | struct SceSigninDialogResult { 21 | int error; 22 | int user_id; 23 | uint64_t account_id; 24 | char reserved[8]; 25 | }; 26 | 27 | void signin_dialog_reset(); 28 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/RunMakeCert.bat: -------------------------------------------------------------------------------- 1 | REM This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | REM If a copy of the MPL was not distributed with this file, you can obtain one at 3 | REM https://mozilla.org/MPL/2.0/. 4 | REM 5 | REM Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | 7 | @echo off 8 | 9 | for /f "tokens=*" %%i in ('powershell.exe -NoProfile -Command "Get-ExecutionPolicy -Scope Process"') do set CurrentPolicy=%%i 10 | powershell.exe -NoProfile -Command "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force" 11 | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0MakeCert.ps1" 12 | powershell.exe -NoProfile -Command "Set-ExecutionPolicy -Scope Process -ExecutionPolicy %CurrentPolicy% -Force" 13 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/callback.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "account.h" 11 | #include 12 | 13 | typedef void (*SceNpCallback)(int user_id, SceNpState status, void* userdata); 14 | 15 | struct SceNpCallbackEntry { 16 | SceNpCallback callback = nullptr; 17 | void* userdata = nullptr; 18 | std::unordered_map user_states; 19 | };; 20 | 21 | void remove_user_from_callbacks(int user_id); 22 | 23 | void np_callback_reset(); 24 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/service/system.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | struct SceFriendsListDialogParam { 13 | uint64_t unknown0; 14 | uint32_t unknown1; 15 | uint32_t unknown2; 16 | uint64_t unknown3; 17 | }; 18 | 19 | struct ScePlayerDialogParam { 20 | uint64_t unknown0; 21 | uint32_t unknown1; 22 | uint32_t unknown2; 23 | uint64_t unknown3; 24 | uint64_t unknown4; 25 | uint64_t unknown5; 26 | uint64_t unknown6; 27 | uint64_t unknown7; 28 | uint64_t unknown8; 29 | uint64_t unknown9; 30 | }; 31 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/include/detver.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Common version parameters. 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #define _USING_V110_SDK71_ 1 11 | #include "winver.h" 12 | #if 0 13 | #include 14 | #include 15 | #else 16 | #ifndef DETOURS_STRINGIFY 17 | #define DETOURS_STRINGIFY_(x) #x 18 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 19 | #endif 20 | 21 | #define VER_FILEFLAGSMASK 0x3fL 22 | #define VER_FILEFLAGS 0x0L 23 | #define VER_FILEOS 0x00040004L 24 | #define VER_FILETYPE 0x00000002L 25 | #define VER_FILESUBTYPE 0x00000000L 26 | #endif 27 | #define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS) 28 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/dialog/common.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | typedef uint32_t SceDialogStatus; 14 | 15 | #define SCE_DIALOG_STATUS_NOT_INITIALIZED 0 16 | #define SCE_DIALOG_STATUS_INITIALIZED 1 17 | #define SCE_DIALOG_STATUS_RUNNING 2 18 | #define SCE_DIALOG_STATUS_FINISHED 3 19 | 20 | extern bool g_common_dialog_initialized; 21 | extern bool g_common_dialog_busy; 22 | 23 | struct SceDialogCommonParam { 24 | uint64_t unknown0; 25 | HWND* hwnd; 26 | char reserved[36]; 27 | int check; 28 | }; 29 | 30 | void common_dialog_reset(); 31 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/procs.c: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "procs.h" 9 | 10 | const char* g_exports_dll_proc_names[17] = { 11 | "GetFileVersionInfoA", 12 | "GetFileVersionInfoByHandle", 13 | "GetFileVersionInfoExA", 14 | "GetFileVersionInfoExW", 15 | "GetFileVersionInfoSizeA", 16 | "GetFileVersionInfoSizeExA", 17 | "GetFileVersionInfoSizeExW", 18 | "GetFileVersionInfoSizeW", 19 | "GetFileVersionInfoW", 20 | "VerFindFileA", 21 | "VerFindFileW", 22 | "VerInstallFileA", 23 | "VerInstallFileW", 24 | "VerLanguageNameA", 25 | "VerLanguageNameW", 26 | "VerQueryValueA", 27 | "VerQueryValueW" 28 | }; 29 | 30 | FARPROC g_version_dll_procs[17]; 31 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/service/user.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | #define DEFAULT_FAKE_ACCOUNT_ID 0x1234567890ABCDEF 14 | 15 | struct SceNpAccount { 16 | int user_id; 17 | uint64_t account_id; 18 | bool is_logged_in; 19 | }; 20 | 21 | void load_fake_account(uint64_t account_id); 22 | void load_fake_account(uint64_t account_id, int user_id); 23 | SceNpAccount* get_fake_account(int user_id); 24 | SceNpAccount* get_fake_account_by_account_id(uint64_t account_id); 25 | const std::vector& get_fake_accounts(); 26 | bool unload_fake_account(int user_id); 27 | 28 | void service_user_reset(); 29 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/pc.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | typedef uint32_t ScePsPcPropertyType; 13 | 14 | #define SCE_PSPC_PROPERTY_TYPE_STRING 0 15 | #define SCE_PSPC_PROPERTY_TYPE_INT 1 16 | #define SCE_PSPC_PROPERTY_TYPE_BOOL 2 17 | #define SCE_PSPC_PROPERTY_TYPE_DATA 3 18 | 19 | typedef struct ScePsPcProperty { 20 | const char* name; 21 | ScePsPcPropertyType type; 22 | union { 23 | char* string; 24 | int integer; 25 | bool boolean; 26 | void* data; 27 | }; 28 | } ScePsPcProperty; 29 | 30 | struct ScePsPcInitializeInternalParam { 31 | ScePsPcProperty* properties; 32 | int property_count; 33 | uint64_t unknown1; 34 | }; 35 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/dialog/common.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "common.h" 9 | 10 | #include "../sce.h" 11 | #include "signin.h" 12 | 13 | bool g_common_dialog_initialized = false; 14 | bool g_common_dialog_busy = false; 15 | 16 | PSPCSDK_API SceResult sceCommonDialogInitialize() { 17 | if (g_common_dialog_initialized) { 18 | return SCE_ERROR_COMMON_DIALOG_ALREADY_INITIALIZED; 19 | } 20 | g_common_dialog_initialized = true; 21 | return SCE_OK; 22 | } 23 | 24 | PSPCSDK_API bool sceCommonDialogIsUsed() { 25 | return g_common_dialog_busy; 26 | } 27 | 28 | void common_dialog_reset() { 29 | signin_dialog_reset(); 30 | g_common_dialog_initialized = false; 31 | g_common_dialog_busy = false; 32 | } 33 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/trophy.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "../sce.h" 9 | 10 | PSPCSDK_API SceResult sceNpTrophy2CreateContext(int* unknown1, int unknown2, uint32_t unknown3, uint64_t unknown4) { 11 | // Invalid param checking 12 | printf("(STUBBED) sceNpTrophy2CreateContext(%p, %x, %x, %llx)\n", unknown1, unknown2, unknown3, unknown4); 13 | return SCE_OK; 14 | } 15 | 16 | PSPCSDK_API SceResult sceNpTrophy2DestroyContext(int unknown1) { 17 | // Invalid param checking 18 | printf("(STUBBED) sceNpTrophy2DestroyContext(%d)\n", unknown1); 19 | return SCE_OK; 20 | } 21 | 22 | PSPCSDK_API SceResult sceNpTrophy2ShowTrophyList(void* unknown1, int unknown2) { 23 | // Invalid param checking 24 | printf("(STUBBED) sceNpTrophy2ShowTrophyList(%p, %d)\n", unknown1, unknown2); 25 | return SCE_OK; 26 | } 27 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/resource.rc: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | // If a copy of the MPL was not distributed with this file, you can obtain one at 3 | // https://mozilla.org/MPL/2.0/. 4 | // 5 | // Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | 7 | 1 VERSIONINFO 8 | FILEVERSION 0,0,4,441 9 | PRODUCTVERSION 3,50,0,11 10 | FILEOS 0x40004 11 | FILETYPE 0x2 12 | 13 | BEGIN 14 | BLOCK "StringFileInfo" 15 | BEGIN 16 | BLOCK "000004b0" 17 | BEGIN 18 | VALUE "CompanyName", "Sony Interactive Entertainment Inc." 19 | VALUE "FileDescription", "PlayStation(R) PC SDK Runtime 24.12-03.50.00.11" 20 | VALUE "InternalName", "PsPcSdk.dll" 21 | VALUE "LegalCopyright", "Copyright (C) 2024 Sony Interactive Entertainment Inc." 22 | VALUE "OriginalFilename", "PsPcSdk.dll" 23 | VALUE "ProductName", "PlayStation(R) PC SDK Runtime 24.12-03.50.00.11" 24 | VALUE "ProductVersion", "24.12-03.50.00.11-00.00.00.0.1" 25 | END 26 | END 27 | 28 | BLOCK "VarFileInfo" 29 | BEGIN 30 | VALUE "Translation", 0x0000 0x04B0 31 | END 32 | END 33 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/utils.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "utils.h" 9 | 10 | #include 11 | 12 | bool strendswith(const char* str, const char* suffix) { 13 | size_t str_len = strlen(str); 14 | size_t suffix_len = strlen(suffix); 15 | if (str_len < suffix_len) { 16 | return false; 17 | } 18 | return strcmp(str + str_len - suffix_len, suffix) == 0; 19 | } 20 | 21 | bool wstrendswith(const wchar_t* str, const wchar_t* suffix) { 22 | size_t str_len = wcslen(str); 23 | size_t suffix_len = wcslen(suffix); 24 | if (str_len < suffix_len) { 25 | return false; 26 | } 27 | return wcscmp(str + str_len - suffix_len, suffix) == 0; 28 | } 29 | 30 | bool ismemzero(void* ptr, size_t size) { 31 | if (!ptr) { 32 | return false; 33 | } 34 | char* p = (char*)ptr; 35 | char* q = p + size; 36 | while (p < q) { 37 | if (*p++ != 0) { 38 | return false; 39 | } 40 | } 41 | return true; 42 | } 43 | -------------------------------------------------------------------------------- /PsPcSdkEmulator.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35527.113 d17.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PsPcSdkEmulator", "PsPcSdkEmulator\PsPcSdkEmulator.vcxproj", "{8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Debug|x64.ActiveCfg = Debug|x64 17 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Debug|x64.Build.0 = Debug|x64 18 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Debug|x86.ActiveCfg = Debug|Win32 19 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Debug|x86.Build.0 = Debug|Win32 20 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Release|x64.ActiveCfg = Release|x64 21 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Release|x64.Build.0 = Release|x64 22 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Release|x86.ActiveCfg = Release|Win32 23 | {8A87CAF8-E44B-4759-89D6-BF45C9F1ED95}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/misc.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "misc.h" 9 | 10 | #include "../sce.h" 11 | #include "auth.h" 12 | #include "callback.h" 13 | #include "uds.h" 14 | #include "webapi2.h" 15 | #include "session.h" 16 | #include 17 | 18 | PSPCSDK_API SceResult sceNpNotifyPremiumFeature(SceNpPremiumInfo* info) { 19 | if (!info) { 20 | return SCE_ERROR_NP_INVALID_PARAM; 21 | } 22 | printf("(STUBBED) sceNpNotifyPremiumFeature(%p)\n", info); 23 | return SCE_OK; 24 | } 25 | 26 | PSPCSDK_API SceResult sceNpSetAdditionalScope(void* scpe) { 27 | if (!scpe) { 28 | return SCE_ERROR_NP_NULL_PARAMETER; 29 | } 30 | printf("(STUBBED) sceNpSetAdditionalScope(%p)\n", scpe); 31 | return SCE_OK; 32 | } 33 | 34 | PSPCSDK_API SceResult sceNpGetPlatformError(uint32_t unknown1, HRESULT* error, uint64_t four) { 35 | if (!error || !unknown1 || four != 4) { 36 | return SCE_ERROR_NP_INVALID_PARAM; 37 | } 38 | printf("(STUBBED) sceNpGetPlatformError(%u, %p, %llu)\n", unknown1, error, four); 39 | *error = 0; 40 | return SCE_OK; 41 | } 42 | 43 | void np_reset() { 44 | np_auth_reset(); 45 | np_callback_reset(); 46 | np_uds_reset(); 47 | np_web_api2_reset(); 48 | np_session_reset(); 49 | } 50 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/rudp/rudp.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "../sce.h" 9 | 10 | PSPCSDK_STUB(sceRudpInit) 11 | PSPCSDK_STUB(sceRudpEnd) 12 | PSPCSDK_STUB(sceRudpEnableInternalIOThread) 13 | PSPCSDK_STUB(sceRudpEnableInternalIOThread2) 14 | PSPCSDK_STUB(sceRudpSetEventHandler) 15 | PSPCSDK_STUB(sceRudpSetMaxSegmentSize) 16 | PSPCSDK_STUB(sceRudpGetMaxSegmentSize) 17 | PSPCSDK_STUB(sceRudpProcessEvents) 18 | PSPCSDK_STUB(sceRudpCreateContext) 19 | PSPCSDK_STUB(sceRudpBind) 20 | PSPCSDK_STUB(sceRudpActivate) 21 | PSPCSDK_STUB(sceRudpInitiate) 22 | PSPCSDK_STUB(sceRudpTerminate) 23 | PSPCSDK_STUB(sceRudpWrite) 24 | PSPCSDK_STUB(sceRudpRead) 25 | PSPCSDK_STUB(sceRudpGetSizeWritable) 26 | PSPCSDK_STUB(sceRudpGetSizeReadable) 27 | PSPCSDK_STUB(sceRudpGetNumberOfPacketsToRead) 28 | PSPCSDK_STUB(sceRudpFlush) 29 | PSPCSDK_STUB(sceRudpNetFlush) 30 | PSPCSDK_STUB(sceRudpNetReceived) 31 | PSPCSDK_STUB(sceRudpSetOption) 32 | PSPCSDK_STUB(sceRudpGetOption) 33 | PSPCSDK_STUB(sceRudpGetLocalInfo) 34 | PSPCSDK_STUB(sceRudpGetRemoteInfo) 35 | PSPCSDK_STUB(sceRudpGetContextStatus) 36 | PSPCSDK_STUB(sceRudpPollCreate) 37 | PSPCSDK_STUB(sceRudpPollDestroy) 38 | PSPCSDK_STUB(sceRudpPollControl) 39 | PSPCSDK_STUB(sceRudpPollWait) 40 | PSPCSDK_STUB(sceRudpPollCancel) 41 | PSPCSDK_STUB(sceRudpGetStatus) 42 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/service/system.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "system.h" 9 | 10 | #include "../sce.h" 11 | #include 12 | 13 | PSPCSDK_API void sceSystemServiceInitializeFriendsListDialogParam(SceFriendsListDialogParam* param) { 14 | if (!param) { 15 | return; 16 | } 17 | memset(param, 0, sizeof(SceFriendsListDialogParam)); 18 | param->unknown0 = 0x18; 19 | param->unknown2 = 0xffffffff; 20 | } 21 | 22 | PSPCSDK_API void sceSystemServiceInitializePlayerDialogParam(ScePlayerDialogParam* param) { 23 | if (!param) { 24 | return; 25 | } 26 | memset(param, 0, sizeof(ScePlayerDialogParam)); 27 | param->unknown0 = 0x48; 28 | param->unknown2 = 0xffffffff; 29 | } 30 | 31 | PSPCSDK_API SceResult sceSystemServiceLaunchFriendsListDialog(SceFriendsListDialogParam* param) { 32 | if (!param || !param->unknown2) { 33 | return SCE_ERROR_SYSTEM_SERVICE_INVALID_PARAM; 34 | } 35 | printf("(STUBBED) sceSystemServiceLaunchFriendsListDialog(%p)\n", param); 36 | return SCE_OK; 37 | } 38 | 39 | PSPCSDK_API SceResult sceSystemServiceLaunchPlayerDialog(ScePlayerDialogParam* param) { 40 | if (!param || !param->unknown2) { 41 | return SCE_ERROR_SYSTEM_SERVICE_INVALID_PARAM; 42 | } 43 | printf("(STUBBED) sceSystemServiceLaunchPlayerDialog(%p)\n", param); 44 | return SCE_OK; 45 | } 46 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/dialog/msg.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "../sce.h" 9 | #include "common.h" 10 | 11 | PSPCSDK_API SceResult sceMsgDialogInitialize() { 12 | if (!g_common_dialog_initialized) { 13 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 14 | } 15 | printf("(STUBBED) sceMsgDialogInitialize\n"); 16 | return SCE_OK; 17 | } 18 | 19 | PSPCSDK_API SceResult sceMsgDialogTerminate() { 20 | if (!g_common_dialog_initialized) { 21 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 22 | } 23 | printf("(STUBBED) sceMsgDialogTerminate\n"); 24 | return SCE_OK; 25 | } 26 | 27 | PSPCSDK_API SceResult sceMsgDialogOpen(void* params) { 28 | if (!params) { 29 | return SCE_ERROR_COMMON_DIALOG_NULL_PARAMETER; 30 | } 31 | if (!g_common_dialog_initialized) { 32 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 33 | } 34 | printf("(STUBBED) sceMsgDialogOpen(%p)\n", params); 35 | return SCE_OK; 36 | } 37 | 38 | PSPCSDK_API SceResult sceMsgDialogClose() { 39 | if (!g_common_dialog_initialized) { 40 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 41 | } 42 | printf("(STUBBED) sceMsgDialogClose\n"); 43 | return SCE_OK; 44 | } 45 | 46 | PSPCSDK_API SceResult sceMsgDialogGetResult(void* result) { 47 | if (!result) { 48 | return SCE_ERROR_COMMON_DIALOG_NULL_PARAMETER; 49 | } 50 | if (!g_common_dialog_initialized) { 51 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 52 | } 53 | printf("(STUBBED) sceMsgDialogGetResult(%p)\n", result); 54 | return SCE_OK; 55 | } 56 | 57 | PSPCSDK_API SceDialogStatus sceMsgDialogGetStatus() { 58 | printf("(STUBBED) sceMsgDialogGetStatus\n"); 59 | return SCE_DIALOG_STATUS_NOT_INITIALIZED; 60 | } 61 | 62 | PSPCSDK_API SceDialogStatus sceMsgDialogUpdateStatus() { 63 | printf("(STUBBED) sceMsgDialogUpdateStatus\n"); 64 | return SCE_DIALOG_STATUS_NOT_INITIALIZED; 65 | } 66 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/dllmain.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "dllmain.h" 9 | 10 | #include "hooks.h" 11 | #include "procs.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static HMODULE g_version_dll = nullptr; 18 | 19 | wchar_t* g_cuurent_dll_path = nullptr; 20 | 21 | static void get_current_dll_path(HMODULE mod) { 22 | DWORD size = MAX_PATH; 23 | g_cuurent_dll_path = new wchar_t[size]; 24 | retry: 25 | GetModuleFileNameW(mod, g_cuurent_dll_path, size); 26 | if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 27 | size *= 2; 28 | delete[] g_cuurent_dll_path; 29 | g_cuurent_dll_path = new wchar_t[size]; 30 | goto retry; 31 | } 32 | } 33 | 34 | BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { 35 | switch (ul_reason_for_call) { 36 | case DLL_PROCESS_ATTACH: { 37 | 38 | char system_path[MAX_PATH] = {}; 39 | char version_dll_path[MAX_PATH] = {}; 40 | 41 | if (SHGetFolderPathA(nullptr, CSIDL_SYSTEM, nullptr, SHGFP_TYPE_CURRENT, system_path) == S_OK) { 42 | PathCombineA(version_dll_path, system_path, "version.dll"); 43 | g_version_dll = LoadLibraryA(version_dll_path); 44 | 45 | if (g_version_dll) { 46 | for (std::uint32_t i = 0; i < sizeof(g_version_dll_procs) / sizeof(g_version_dll_procs[0]); ++i) { 47 | g_version_dll_procs[i] = GetProcAddress(g_version_dll, g_exports_dll_proc_names[i]); 48 | } 49 | } 50 | 51 | } 52 | get_current_dll_path(hModule); 53 | pspcsdk_hooks_setup(); 54 | break; 55 | } 56 | case DLL_PROCESS_DETACH: 57 | pspcsdk_hooks_cleanup(); 58 | 59 | if (g_version_dll) { 60 | FreeLibrary(g_version_dll); 61 | } 62 | 63 | if (g_cuurent_dll_path) { 64 | delete[] g_cuurent_dll_path; 65 | } 66 | break; 67 | } 68 | return TRUE; 69 | } 70 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/proxy.asm: -------------------------------------------------------------------------------- 1 | ; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | ; If a copy of the MPL was not distributed with this file, you can obtain one at 3 | ; https://mozilla.org/MPL/2.0/. 4 | ; 5 | ; Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | 7 | .code 8 | extern g_version_dll_procs:QWORD 9 | GetFileVersionInfoA proc 10 | jmp QWORD ptr g_version_dll_procs[0 * 8] 11 | GetFileVersionInfoA endp 12 | GetFileVersionInfoByHandle proc 13 | jmp QWORD ptr g_version_dll_procs[1 * 8] 14 | GetFileVersionInfoByHandle endp 15 | GetFileVersionInfoExA proc 16 | jmp QWORD ptr g_version_dll_procs[2 * 8] 17 | GetFileVersionInfoExA endp 18 | GetFileVersionInfoExW proc 19 | jmp QWORD ptr g_version_dll_procs[3 * 8] 20 | GetFileVersionInfoExW endp 21 | GetFileVersionInfoSizeA proc 22 | jmp QWORD ptr g_version_dll_procs[4 * 8] 23 | GetFileVersionInfoSizeA endp 24 | GetFileVersionInfoSizeExA proc 25 | jmp QWORD ptr g_version_dll_procs[5 * 8] 26 | GetFileVersionInfoSizeExA endp 27 | GetFileVersionInfoSizeExW proc 28 | jmp QWORD ptr g_version_dll_procs[6 * 8] 29 | GetFileVersionInfoSizeExW endp 30 | GetFileVersionInfoSizeW proc 31 | jmp QWORD ptr g_version_dll_procs[7 * 8] 32 | GetFileVersionInfoSizeW endp 33 | GetFileVersionInfoW proc 34 | jmp QWORD ptr g_version_dll_procs[8 * 8] 35 | GetFileVersionInfoW endp 36 | VerFindFileA proc 37 | jmp QWORD ptr g_version_dll_procs[9 * 8] 38 | VerFindFileA endp 39 | VerFindFileW proc 40 | jmp QWORD ptr g_version_dll_procs[10 * 8] 41 | VerFindFileW endp 42 | VerInstallFileA proc 43 | jmp QWORD ptr g_version_dll_procs[11 * 8] 44 | VerInstallFileA endp 45 | VerInstallFileW proc 46 | jmp QWORD ptr g_version_dll_procs[12 * 8] 47 | VerInstallFileW endp 48 | VerLanguageNameA proc 49 | jmp QWORD ptr g_version_dll_procs[13 * 8] 50 | VerLanguageNameA endp 51 | VerLanguageNameW proc 52 | jmp QWORD ptr g_version_dll_procs[14 * 8] 53 | VerLanguageNameW endp 54 | VerQueryValueA proc 55 | jmp QWORD ptr g_version_dll_procs[15 * 8] 56 | VerQueryValueA endp 57 | VerQueryValueW proc 58 | jmp QWORD ptr g_version_dll_procs[16 * 8] 59 | VerQueryValueW endp 60 | end 61 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/utils.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | bool ismemzero(void* ptr, size_t size); 16 | bool strendswith(const char* str, const char* suffix); 17 | bool wstrendswith(const wchar_t* str, const wchar_t* suffix); 18 | 19 | #define DETOUR_CALL(x) { LONG e = x; if (e != NO_ERROR) { DetourTransactionAbort(); return; } } 20 | 21 | template 22 | static void HookFunction(T* originalFunction, T newFunction) { 23 | DETOUR_CALL(DetourTransactionBegin()); 24 | DETOUR_CALL(DetourUpdateThread(GetCurrentThread())); 25 | DETOUR_CALL(DetourAttach(originalFunction, newFunction)); 26 | DETOUR_CALL(DetourTransactionCommit()); 27 | } 28 | 29 | template 30 | static void UnhookFunction(T* originalFunction, T newFunction) { 31 | DETOUR_CALL(DetourTransactionBegin()); 32 | DETOUR_CALL(DetourUpdateThread(GetCurrentThread())); 33 | DETOUR_CALL(DetourDetach(originalFunction, newFunction)); 34 | DETOUR_CALL(DetourTransactionCommit()); 35 | } 36 | 37 | template, int> = 0> 38 | class IdProvider { 39 | private: 40 | T next_id; 41 | std::vector free_ids; 42 | public: 43 | IdProvider() : next_id(1) {} 44 | T new_id() { 45 | if (free_ids.empty()) { 46 | return next_id++; 47 | } 48 | T id = free_ids.back(); 49 | free_ids.pop_back(); 50 | return id; 51 | } 52 | 53 | void free_id(T id) { 54 | if (!is_used(id)) { 55 | return; 56 | } 57 | free_ids.push_back(id); 58 | auto it = std::find(free_ids.begin(), free_ids.end(), next_id - 1); 59 | while (it != free_ids.end()) { 60 | free_ids.erase(it); 61 | next_id--; 62 | it = std::find(free_ids.begin(), free_ids.end(), next_id - 1); 63 | } 64 | } 65 | 66 | void reset() { 67 | next_id = 1; 68 | free_ids.clear(); 69 | } 70 | 71 | bool is_used(T id) { 72 | return id < next_id && std::find(free_ids.begin(), free_ids.end(), id) == free_ids.end(); 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/pc.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "pc.h" 9 | 10 | #include "sce.h" 11 | #include "dialog/common.h" 12 | #include "np/misc.h" 13 | #include "service/user.h" 14 | #include "../net/net.h" 15 | 16 | static void pc_sdk_reset() { 17 | common_dialog_reset(); 18 | np_reset(); 19 | service_user_reset(); 20 | } 21 | 22 | static void print_property(ScePsPcProperty* property) { 23 | switch (property->type) { 24 | case SCE_PSPC_PROPERTY_TYPE_STRING: 25 | printf(" %s: %s\n", property->name, property->string); 26 | break; 27 | case SCE_PSPC_PROPERTY_TYPE_INT: 28 | printf(" %s: %d\n", property->name, property->integer); 29 | break; 30 | case SCE_PSPC_PROPERTY_TYPE_BOOL: 31 | printf(" %s: %s\n", property->name, property->boolean ? "true" : "false"); 32 | break; 33 | case SCE_PSPC_PROPERTY_TYPE_DATA: 34 | printf(" %s: %p\n", property->name, property->data); 35 | break; 36 | } 37 | } 38 | 39 | PSPCSDK_API SceResult scePsPcInitializeInternal(ScePsPcInitializeInternalParam param) { 40 | pc_sdk_reset(); 41 | load_fake_account(DEFAULT_FAKE_ACCOUNT_ID); 42 | pspcsdk_net_setup(); 43 | printf("PsPcSdkEmulator initialized\n"); 44 | printf("Properties:\n"); 45 | for (int i = 0; i < param.property_count; i++) { 46 | print_property(¶m.properties[i]); 47 | } 48 | return SCE_OK; 49 | } 50 | 51 | PSPCSDK_API SceResult scePsPcTerminate() { 52 | pc_sdk_reset(); 53 | pspcsdk_net_cleanup(); 54 | return SCE_OK; 55 | } 56 | 57 | PSPCSDK_API bool scePsPcIsSupportedPlatform() { 58 | return true; 59 | } 60 | 61 | PSPCSDK_API void scePsPcHookApiCall(char* name) { 62 | // The game calls this function before calling 63 | // any other PsPcSdk function. The parameter is 64 | // the name of the function that is about to be 65 | // called. 66 | #ifndef NDEBUG 67 | printf("[PsPcSdkEmulator] called %s\n", name); 68 | #endif 69 | } 70 | 71 | PSPCSDK_API SceResult scePsPcSetDeviceDataCollectionSetting(uint32_t mode) { 72 | if (mode != 0 && mode != 1) { 73 | return SCE_ERROR_PC_INVALID_DATA_COLLECTION_MODE; 74 | } 75 | printf("(STUBBED) scePsPcSetDeviceDataCollectionSetting(%d)\n", mode); 76 | return SCE_OK; 77 | } 78 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/MakeCert.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 3 | If a copy of the MPL was not distributed with this file, you can obtain one at 4 | https://mozilla.org/MPL/2.0/. 5 | 6 | Copyright (c) 2025 Lander Gallastegi (LNDF) 7 | #> 8 | 9 | $ErrorActionPreference = "Stop" 10 | 11 | # Define variables 12 | $CertSubject = "CN=Sony Interactive Entertainment LLC" 13 | $CertFriendlyName = "Sony Interactive Entertainment LLC" 14 | $CertEKU = "1.3.6.1.5.5.7.3.3" 15 | $CertPassword = "PsPcSdk Emulator" 16 | $CertRelativePath = "src\loader\cert.pfx" 17 | $CertAbsolutePath = Join-Path -Path (Get-Location) -ChildPath $CertRelativePath 18 | 19 | # Ensure the target directory exists 20 | $CertDirectory = Split-Path -Path $CertAbsolutePath -Parent 21 | if (-not (Test-Path -Path $CertDirectory)) { 22 | Write-Host "Creating directory: $CertDirectory" 23 | New-Item -ItemType Directory -Path $CertDirectory | Out-Null 24 | } 25 | 26 | # Check if a certificate with the same subject already exists 27 | Write-Host "Checking for existing certificates with the same subject..." 28 | $ExistingCert = Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -eq $CertSubject } 29 | if ($ExistingCert) { 30 | Write-Host "Existing certificate found. Deleting it to avoid duplicates..." 31 | Remove-Item -Path "Cert:\CurrentUser\My\$($ExistingCert.Thumbprint)" -Force 32 | } 33 | 34 | # Create the self-signed certificate 35 | Write-Host "Creating self-signed certificate..." 36 | $Certificate = New-SelfSignedCertificate ` 37 | -Subject $CertSubject ` 38 | -CertStoreLocation Cert:\CurrentUser\My ` 39 | -KeyUsage DigitalSignature ` 40 | -Type CodeSigning ` 41 | -FriendlyName $CertFriendlyName ` 42 | -NotAfter (Get-Date).AddYears(100) ` 43 | -TextExtension @("2.5.29.37={text}$CertEKU") ` 44 | -KeyExportPolicy Exportable 45 | 46 | # Export the certificate as a .pfx file 47 | if (Test-Path -Path $CertAbsolutePath) { 48 | Write-Host "Existing PFX file found. Overwriting: $CertAbsolutePath" 49 | Remove-Item -Path $CertAbsolutePath -Force 50 | } 51 | 52 | Write-Host "Exporting certificate to $CertAbsolutePath..." 53 | $SecurePassword = ConvertTo-SecureString -String $CertPassword -Force -AsPlainText 54 | Export-PfxCertificate ` 55 | -Cert $Certificate ` 56 | -FilePath $CertAbsolutePath ` 57 | -Password $SecurePassword 58 | 59 | Write-Host "Certificate successfully created and stored at: $CertAbsolutePath" 60 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/callback.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "callback.h" 9 | 10 | #include "../sce.h" 11 | #include "../service/user.h" 12 | #include 13 | 14 | static std::array g_callbacks; 15 | 16 | void remove_user_from_callbacks(int user_id) { 17 | for (auto& entry : g_callbacks) { 18 | entry.user_states.erase(user_id); 19 | } 20 | } 21 | 22 | PSPCSDK_API int sceNpRegisterStateCallbackA(SceNpCallback callback, void* userdata) { 23 | int index = -1; 24 | for (int i = 0; i < g_callbacks.size(); ++i) { 25 | if (g_callbacks[i].callback == callback) { 26 | return SCE_ERROR_NP_CALLBACK_ALREADY_REGISTERED; 27 | } 28 | if (!g_callbacks[i].callback && index == -1) { 29 | index = i; 30 | } 31 | } 32 | if (index == -1) { 33 | return SCE_ERROR_NP_CALLBACK_NO_FREE_SLOT; 34 | } 35 | g_callbacks[index].callback = callback; 36 | g_callbacks[index].userdata = userdata; 37 | g_callbacks[index].user_states.clear(); 38 | return index; 39 | } 40 | 41 | PSPCSDK_API SceResult sceNpUnregisterStateCallbackA(int callback_id) { 42 | if (callback_id < 0 || callback_id >= g_callbacks.size() || !g_callbacks[callback_id].callback) { 43 | return SCE_ERROR_NP_CALLBACK_NOT_REGISTERED; 44 | } 45 | g_callbacks[callback_id].callback = nullptr; 46 | g_callbacks[callback_id].userdata = nullptr; 47 | g_callbacks[callback_id].user_states.clear(); 48 | return SCE_OK; 49 | } 50 | 51 | PSPCSDK_API void sceNpCheckCallback() { 52 | const auto& accounts = get_fake_accounts(); 53 | for (const auto& account : accounts) { 54 | for (auto& entry : g_callbacks) { 55 | if (!entry.callback) { 56 | continue; 57 | } 58 | auto it = entry.user_states.find(account.user_id); 59 | bool call = false; 60 | if (it == entry.user_states.end()) { 61 | call = true; 62 | entry.user_states[account.user_id] = account.is_logged_in; 63 | } else if (it->second != account.is_logged_in) { 64 | call = true; 65 | it->second = account.is_logged_in; 66 | } 67 | if (call) { 68 | SceNpState status = account.is_logged_in ? SCE_NP_STATUS_LOGGED_IN : SCE_NP_STATUS_LOGGED_OUT; 69 | entry.callback(account.user_id, status, entry.userdata); 70 | } 71 | } 72 | } 73 | } 74 | 75 | void np_callback_reset() { 76 | g_callbacks.fill({}); 77 | } 78 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/voicechat/voicechat.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "../sce.h" 9 | 10 | PSPCSDK_STUB(sceVoiceChatInitialize) 11 | PSPCSDK_STUB(sceVoiceChatTerminate) 12 | PSPCSDK_STUB(sceVoiceChatRequestRegisterSession) 13 | PSPCSDK_STUB(sceVoiceChatRequestUnregisterSession) 14 | PSPCSDK_STUB(sceVoiceChatRegisterHandlers) 15 | PSPCSDK_STUB(sceVoiceChatRegisterMicEventHandler) 16 | PSPCSDK_STUB(sceVoiceChatUnregisterMicEventHandler) 17 | PSPCSDK_STUB(sceVoiceChatProcessEvent) 18 | PSPCSDK_STUB(sceVoiceChatCreateRequest) 19 | PSPCSDK_STUB(sceVoiceChatDeleteRequest) 20 | PSPCSDK_STUB(sceVoiceChatAbortRequest) 21 | PSPCSDK_STUB(sceVoiceChatRequestCreatePlayerSessionVoiceChatChannel) 22 | PSPCSDK_STUB(sceVoiceChatRequestDeletePlayerSessionVoiceChatChannel) 23 | PSPCSDK_STUB(sceVoiceChatRequestJoinPlayerSessionVoiceChatChannel) 24 | PSPCSDK_STUB(sceVoiceChatRequestLeavePlayerSessionVoiceChatChannel) 25 | PSPCSDK_STUB(sceVoiceChatRequestUpdatePlayerSessionVoiceChatChannelName) 26 | PSPCSDK_STUB(sceVoiceChatRequestCreateGameSessionVoiceChatChannel) 27 | PSPCSDK_STUB(sceVoiceChatRequestDeleteGameSessionVoiceChatChannel) 28 | PSPCSDK_STUB(sceVoiceChatRequestJoinGameSessionVoiceChatChannel) 29 | PSPCSDK_STUB(sceVoiceChatRequestLeaveGameSessionVoiceChatChannel) 30 | PSPCSDK_STUB(sceVoiceChatRequestUpdateGameSessionVoiceChatChannelName) 31 | PSPCSDK_STUB(sceVoiceChatRequestCreateVoiceChatGroup) 32 | PSPCSDK_STUB(sceVoiceChatRequestDeleteVoiceChatGroup) 33 | PSPCSDK_STUB(sceVoiceChatRequestJoinVoiceChatGroup) 34 | PSPCSDK_STUB(sceVoiceChatRequestLeaveVoiceChatGroup) 35 | PSPCSDK_STUB(sceVoiceChatGetChatChannelMemberInfoList) 36 | PSPCSDK_STUB(sceVoiceChatGetChatGroupMemberInfoList) 37 | PSPCSDK_STUB(sceVoiceChatGetChannelMemberActiveChannelMatchingState) 38 | PSPCSDK_STUB(sceVoiceChatGetChannelMemberVoiceConnectionState) 39 | PSPCSDK_STUB(sceVoiceChatGetMicState) 40 | PSPCSDK_STUB(sceVoiceChatRequestSetChannelMute) 41 | PSPCSDK_STUB(sceVoiceChatRequestSetMemberMute) 42 | PSPCSDK_STUB(sceVoiceChatRequestSetMemberVolume) 43 | PSPCSDK_STUB(sceVoiceChatRegisterMicEventHandler2) 44 | PSPCSDK_STUB(sceVoiceChatUnregisterMicEventHandler2) 45 | PSPCSDK_STUB(sceVoiceChatGetActiveChannel) 46 | PSPCSDK_STUB(sceVoiceChatRequestSetActiveChannel) 47 | PSPCSDK_STUB(sceVoiceChatRequestSetMicMute) 48 | PSPCSDK_STUB(sceVoiceChatRequestSetMicVolume) 49 | PSPCSDK_STUB(sceVoiceChatGetActiveDeviceInfo) 50 | PSPCSDK_STUB(sceVoiceChatRegisterDeviceEventHandler) 51 | PSPCSDK_STUB(sceVoiceChatUnregisterDeviceEventHandler) 52 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/service/user.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "user.h" 9 | 10 | #include "../sce.h" 11 | #include "../np/callback.h" 12 | 13 | static std::vector g_accounts; 14 | 15 | void load_fake_account(uint64_t account_id) { 16 | load_fake_account(account_id, (int) g_accounts.size()); 17 | } 18 | 19 | void load_fake_account(uint64_t account_id, int user_id) { 20 | SceNpAccount account; 21 | account.user_id = user_id; 22 | account.account_id = account_id; 23 | account.is_logged_in = true; 24 | g_accounts.push_back(account); 25 | } 26 | 27 | SceNpAccount* get_fake_account(int user_id) { 28 | for (auto& account : g_accounts) { 29 | if (account.user_id == user_id) { 30 | return &account; 31 | } 32 | } 33 | return nullptr; 34 | } 35 | 36 | SceNpAccount* get_fake_account_by_account_id(uint64_t account_id) { 37 | for (auto& account : g_accounts) { 38 | if (account.account_id == account_id) { 39 | return &account; 40 | } 41 | } 42 | return nullptr; 43 | } 44 | 45 | const std::vector& get_fake_accounts() { 46 | return g_accounts; 47 | } 48 | 49 | bool unload_fake_account(int user_id) { 50 | for (auto it = g_accounts.begin(); it != g_accounts.end(); ++it) { 51 | if (it->user_id == user_id) { 52 | g_accounts.erase(it); 53 | remove_user_from_callbacks(user_id); 54 | return true; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | PSPCSDK_API SceResult sceUserServiceLoadLastSignInUser(int* user_id) { 61 | if (g_accounts.empty()) { 62 | return SCE_ERROR_USER_SERVICE_INVALID_PARAM; 63 | } 64 | SceNpAccount* account = get_fake_account_by_account_id(DEFAULT_FAKE_ACCOUNT_ID); 65 | if (!account) { 66 | load_fake_account(DEFAULT_FAKE_ACCOUNT_ID); 67 | account = get_fake_account_by_account_id(DEFAULT_FAKE_ACCOUNT_ID); 68 | } 69 | *user_id = account->user_id; 70 | return SCE_OK; 71 | } 72 | 73 | PSPCSDK_API SceResult sceUserServiceLoadUserByAccountId(uint64_t account_id, int* user_id) { 74 | if (g_accounts.empty()) { 75 | return SCE_ERROR_USER_SERVICE_INVALID_PARAM; 76 | } 77 | SceNpAccount* account = get_fake_account_by_account_id(account_id); 78 | if (!account) { 79 | load_fake_account(account_id); 80 | account = get_fake_account_by_account_id(account_id); 81 | } 82 | *user_id = account->user_id; 83 | return SCE_OK; 84 | } 85 | 86 | PSPCSDK_API SceResult sceUserServiceUnloadUser(int user_id) { 87 | if (!unload_fake_account(user_id)) { 88 | return SCE_ERROR_USER_SERVICE_INVALID_PARAM; 89 | } 90 | return SCE_OK; 91 | } 92 | 93 | void service_user_reset() { 94 | g_accounts.clear(); 95 | } 96 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/http.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | struct HttpResponse { 22 | std::string status; 23 | std::string body; 24 | std::unordered_map headers; 25 | 26 | void send_response(SOCKET client_socket); 27 | }; 28 | 29 | using HttpReuestHandler = std::function& headers, const std::string& body, HttpResponse& response)>; 30 | 31 | #include 32 | 33 | class HttpServer { 34 | private: 35 | enum HttpParseResult { 36 | OK, 37 | MALFORMED, 38 | METHOD_UNSUPPORTED, 39 | PROTO_UNSUPPORTED, 40 | };; 41 | 42 | static constexpr int max_connections = 20; 43 | static constexpr int max_headers_size = 8192; 44 | static constexpr int max_body_size = 10 * 1024 * 1024; 45 | static constexpr int timeout = 5000; 46 | 47 | static int server_count; 48 | 49 | static bool wsa_init(); 50 | static void wsa_cleanup(); 51 | 52 | SOCKET server_socket; 53 | std::string address; 54 | uint16_t port; 55 | std::atomic server_running; 56 | std::atomic active_connections; 57 | std::mutex connection_mutex; 58 | std::condition_variable connection_cv; 59 | std::thread listener; 60 | std::optional request_handler; 61 | 62 | std::unordered_map parse_headers(const std::string& request); 63 | HttpParseResult parse_request(const std::string& request, std::string& method, std::string& uri, std::unordered_map& headers); 64 | bool check_and_adjust_time(const std::chrono::time_point& start_time, SOCKET client_socket); 65 | 66 | void send_400_response(SOCKET client_socket); 67 | void send_404_response(SOCKET client_socket); 68 | void send_405_response(SOCKET client_socket); 69 | void send_413_response(SOCKET client_socket); 70 | void send_503_response(SOCKET client_socket); 71 | void send_505_response(SOCKET client_socket); 72 | 73 | void client_handler(SOCKET client_socket); 74 | void client_thread(SOCKET client_socket); 75 | void listener_thread(); 76 | public: 77 | HttpServer(const std::string& address, uint16_t port); 78 | ~HttpServer(); 79 | void start(); 80 | void stop(); 81 | 82 | void set_request_handler(HttpReuestHandler handler); 83 | void remove_request_handler(); 84 | }; 85 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/pssresponses.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #define PSSCLOUD_RESPONSE_CONFIG_MAIN_DATA "{\"registration\":{\"enabled\":true}}" 11 | 12 | #define PSSCLOUD_RESPONSE_AUTH_PART1 "{\"token\":\"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkdW1teS1pc3N1ZXIubmV0Iiwic3ViIjoiZHVtbXlTdWJqZWN0IiwiZXhwIjoxNzM4MDkyNDY3LCJuYmYiOjE3MzgwODg4NjcsImlhdCI6MTczODA4ODg2NywianRpIjoiZHVtbXlKVEkiLCJucyI6ImR1bW15TmFtZXNwYWNlIiwicm9sIjpbImR1bW15Um9sZSJdLCJkbiI6ImR1bW15RE4ifQopjPjc84hKCpjdy34CD2tc.hZXlisfZ6dRjmNdUn0sj5Q7i42CZFoF_9GMIVinsdVEaZLxPH1ohNxN-vdZg18ovcw7FlecY6XlXBzpU382CIjpKss6Drm7mYRfYl9p2M1Lv-Bh0iZcKcj_XZwOtJZZbQM2Fj-xmXC7wFoGiWIWlOEaYB-TTjteZ0uGKBBV6PaRpykW3kcBrfdiB92WrwlbazVRdg62_BSfN_wGQSAxZ9tdQlRqVjI0V4eTo1Gl7ZdVZy9l0xciDxhpYg0kaRs-wYZ6wZMODhtdhNYX12MCdIuVDhEU2NqAU7GX8djKLSjMeCM09vfBwVjcgy87Zrj8LX1zJQS9fJZkW-M9LstIDzA\",\"account\":{\"name\":\"ns/" 13 | #define PSSCLOUD_RESPONSE_AUTH_PART2 "/accounts/2mcc1pdmkRPXeP6jpAa48tcNFWz\",\"id\":\"2mcc1pdmkRPXeP6jpAa48tcNFWz\",\"origin\":{\"platform\":\"STEAM\",\"id\":\"46231443256534370\",\"attributes\":{}},\"displayName\":\"steamuser\",\"createTime\":\"1970-01-01T00:00:00Z\",\"updateTime\":\"1970-01-01T00:00:00Z\"}}" 14 | 15 | #define PSSCLOUD_RESPONSE_REGISTRATION_PRODUCT_PART1 "{\"clientId\":\"143561c1-4b3d-4c13-8b3a-9e419d96b9c4\",\"scope\":\"openid id_token:psn.basic_claims id_token:is_child psn:passiveLink.steam.s2s\",\"redirectUri\":\"orbis://games\",\"smcid\":\"pc:STEAM:" 16 | #define PSSCLOUD_RESPONSE_REGISTRATION_PRODUCT_PART2 ":PPSA25000_00\"}" 17 | 18 | #define PSSCLOUD_RESPONSE_REGISTERED_ACCOUNT_PART1 "{\"name\":\"ns/shared/accounts/23k19CI2nclpPj3np00dnCy2n1x\",\"id\":\"23k19CI2nclpPj3np00dnCy2n1x\",\"origin\":{\"platform\":\"PSN_NP\",\"id\":\"" 19 | #define PSSCLOUD_RESPONSE_REGISTERED_ACCOUNT_PART2 "\",\"attributes\":{\"is_child\":false,\"legal_country\":\"US\",\"locale\":\"en-US\",\"signin_id\":\"example@example.com\"}},\"displayName\":\"Player\",\"createTime\":\"1970-00-00T00:00:00Z\",\"updateTime\":\"1970-00-00T00:00:00Z\"}" 20 | 21 | #define PSSCLOUD_RESPONSE_NEW_REGISTRATION_URL_PART1 "{\"url\":\"https://pss-cloud.net/gs/accounts/v1/ns/" 22 | #define PSSCLOUD_RESPONSE_NEW_REGISTRATION_URL_PART2 ":register?linkToken=jcqc34rNp41PAx1lN34mcyx1mDv\"}" 23 | 24 | #define PSSCLOUD_RESPONSE_LINK_PART1 "{\"account\":{\"name\":\"ns/shared/accounts/23k19CI2nclpPj3np00dnCy2n1x\",\"id\":\"23k19CI2nclpPj3np00dnCy2n1x\",\"origin\":{\"platform\":\"PSN_NP\",\"id\":\"" 25 | #define PSSCLOUD_RESPONSE_LINK_PART2 "\",\"attributes\":{\"is_child\":false,\"legal_country\":\"US\",\"locale\":\"en-US\",\"signin_id\":\"example@example.com\"}},\"displayName\":\"Player\",\"createTime\":\"1970-00-00T00:00:00.000000000Z\",\"updateTime\":\"1970-00-00T00:00:00.000000000Z\"}}" 26 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/account.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "account.h" 9 | 10 | #include "../sce.h" 11 | #include "../service/user.h" 12 | 13 | PSPCSDK_API SceResult sceNpGetAccountAge(int unknown1, int user_id, void* age) { 14 | if (unknown1 < 1 || user_id == -1 || !age) { 15 | return SCE_ERROR_NP_INVALID_PARAM; 16 | } 17 | printf("(STUBBED) sceNpGetAccountAge(%d, %d, %p)\n", unknown1, user_id, age); 18 | return SCE_OK; 19 | } 20 | 21 | PSPCSDK_API SceResult sceNpGetAccountCountryA(int user_id, int* country) { 22 | if (user_id == -1 || !country) { 23 | return SCE_ERROR_NP_INVALID_PARAM; 24 | } 25 | printf("(STUBBED) sceNpGetAccountCountryA(%x, %p)\n", user_id, country); 26 | return SCE_OK; 27 | } 28 | 29 | PSPCSDK_API SceResult sceNpGetAccountIdA(int user_id, uint64_t* id) { 30 | if (user_id == -1 || !id) { 31 | return SCE_ERROR_NP_INVALID_PARAM; 32 | } 33 | SceNpAccount* account = get_fake_account(user_id); 34 | if (!account) { 35 | return SCE_ERROR_NP_INVALID_PARAM; // this is not the correct error code 36 | } 37 | *id = account->account_id; 38 | return SCE_OK; 39 | } 40 | 41 | PSPCSDK_API SceResult sceNpGetAccountLanguage2(int user_id, int account, void* language) { 42 | if (user_id < 1 || account == -1 || !language) { 43 | return SCE_ERROR_NP_INVALID_PARAM; 44 | } 45 | printf("(STUBBED) sceNpGetAccountLanguage2(%d, %d, %p)\n", user_id, account, language); 46 | return SCE_OK; 47 | } 48 | 49 | PSPCSDK_API SceResult sceNpGetOnlineId(int user_id, SceNpOnlineId* id) { 50 | if (user_id == -1 || !id) { 51 | return SCE_ERROR_NP_INVALID_PARAM; 52 | } 53 | SceNpAccount* account = get_fake_account(user_id); 54 | if (!account) { 55 | return SCE_ERROR_NP_INVALID_PARAM; // this is not the correct error code 56 | } 57 | memset(id, 0, sizeof(SceNpOnlineId)); 58 | strcpy_s(id->name, "Player"); 59 | return SCE_OK; 60 | } 61 | 62 | PSPCSDK_API SceResult sceNpGetState(int user_id, SceNpState* state) { 63 | if (user_id == -1 || !state) { 64 | return SCE_ERROR_NP_INVALID_PARAM; 65 | } 66 | SceNpAccount* account = get_fake_account(user_id); 67 | if (!account) { 68 | *state = SCE_NP_STATUS_UNKNOW; 69 | } else { 70 | *state = account->is_logged_in ? SCE_NP_STATUS_LOGGED_IN : SCE_NP_STATUS_LOGGED_OUT; 71 | } 72 | return SCE_OK; 73 | } 74 | 75 | PSPCSDK_API SceResult sceNpGetUserIdByAccountId(uint64_t id, int* user_id) { 76 | if (!id || !user_id) { 77 | return SCE_ERROR_NP_INVALID_PARAM; 78 | } 79 | SceNpAccount* account = get_fake_account_by_account_id(id); 80 | if (!account) { 81 | return SCE_ERROR_NP_INVALID_PARAM; // this is not the correct error code 82 | } 83 | *user_id = account->user_id; 84 | return SCE_OK; 85 | } 86 | 87 | PSPCSDK_API SceResult sceNpSignOut(int unknown1, int user_id) { 88 | if (unknown1 < 1 || user_id == -1) { 89 | return SCE_ERROR_NP_INVALID_PARAM; 90 | } 91 | SceNpAccount* account = get_fake_account(user_id); 92 | if (!account) { 93 | return SCE_ERROR_NP_INVALID_PARAM; // this is not the correct error code 94 | } 95 | account->is_logged_in = false; 96 | return SCE_OK; 97 | } 98 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/psscloud.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "psscloud.h" 9 | 10 | #include "../sdk/service/user.h" 11 | #include "pssresponses.h" 12 | #include "http.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | static HttpServer g_psscloud_server("127.0.0.1", PSSCLOUD_SERVER_PORT); 20 | 21 | static std::optional get_response_string(const std::string_view uri) { 22 | if (uri.find("config/v1/ns/") == 0 && uri.rfind("/config/main:data") != std::string_view::npos) { 23 | return PSSCLOUD_RESPONSE_CONFIG_MAIN_DATA; 24 | } 25 | size_t pos = uri.find("accounts/v1/ns/"); 26 | if (pos == 0) { 27 | size_t colon = uri.find(':', pos + 15); 28 | std::string_view product_id = uri.substr(pos + 15, colon - pos - 15); 29 | std::string_view action = uri.substr(colon + 1); 30 | if (action == "auth") { 31 | std::ostringstream ss; 32 | ss << PSSCLOUD_RESPONSE_AUTH_PART1; 33 | ss << product_id; 34 | ss << PSSCLOUD_RESPONSE_AUTH_PART2; 35 | return ss.str(); 36 | } else if (action == "registrationProduct") { 37 | std::ostringstream ss; 38 | ss << PSSCLOUD_RESPONSE_REGISTRATION_PRODUCT_PART1; 39 | ss << product_id; 40 | ss << PSSCLOUD_RESPONSE_REGISTRATION_PRODUCT_PART2; 41 | return ss.str(); 42 | } else if (action == "registeredAccount") { 43 | std::ostringstream ss; 44 | ss << PSSCLOUD_RESPONSE_REGISTERED_ACCOUNT_PART1; 45 | ss << DEFAULT_FAKE_ACCOUNT_ID; 46 | ss << PSSCLOUD_RESPONSE_REGISTERED_ACCOUNT_PART2; 47 | return ss.str(); 48 | } else if (action == "newRegistrationURL") { 49 | std::ostringstream ss; 50 | ss << PSSCLOUD_RESPONSE_NEW_REGISTRATION_URL_PART1; 51 | ss << product_id; 52 | ss << PSSCLOUD_RESPONSE_NEW_REGISTRATION_URL_PART2; 53 | return ss.str(); 54 | } else if (action == "link") { 55 | std::ostringstream ss; 56 | ss << PSSCLOUD_RESPONSE_LINK_PART1; 57 | ss << DEFAULT_FAKE_ACCOUNT_ID; 58 | ss << PSSCLOUD_RESPONSE_LINK_PART2; 59 | return ss.str(); 60 | } 61 | } 62 | return std::nullopt; 63 | } 64 | 65 | static void psscloud_request_handler(const std::string& method, const std::string& uri, const std::unordered_map& headers, const std::string& body, HttpResponse& response) { 66 | if (uri.find("/gs") == 0) { 67 | std::string_view uri_view = std::string_view(uri).substr(3); 68 | size_t slash = uri_view.find('/'); 69 | if (slash != std::string_view::npos) { 70 | uri_view = uri_view.substr(slash + 1); 71 | auto response_str = get_response_string(uri_view); 72 | if (response_str) { 73 | response.status = "200 OK"; 74 | response.body = *response_str; 75 | response.headers["Content-Type"] = "application/json"; 76 | return; 77 | } 78 | } 79 | } 80 | response.status = "404 Not Found"; 81 | response.body = "Not Found"; 82 | } 83 | 84 | void psscloud_server_start() { 85 | g_psscloud_server.set_request_handler(psscloud_request_handler); 86 | g_psscloud_server.start(); 87 | } 88 | 89 | void psscloud_server_stop() { 90 | g_psscloud_server.stop(); 91 | } 92 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/net.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "net.h" 9 | 10 | #include "../utils.h" 11 | #include "psscloud.h" 12 | #include 13 | #include 14 | #include 15 | 16 | static decltype(WinHttpOpen)* OriginalWinHttpOpen = nullptr; 17 | static decltype(WinHttpConnect)* OriginalWinHttpConnect = nullptr; 18 | static decltype(WinHttpOpenRequest)* OriginalWinHttpOpenRequest = nullptr; 19 | static decltype(WinHttpCloseHandle)* OriginalWinHttpCloseHandle = nullptr; 20 | 21 | static HMODULE g_winhttp_dll = nullptr; 22 | 23 | static std::unordered_set g_tracked_handles; 24 | static std::mutex g_tracked_handles_mutex; 25 | 26 | static HINTERNET WINAPI HookWinHttpOpen(LPCWSTR pszAgentW, DWORD dwAccessType, LPCWSTR pszProxyW, LPCWSTR pszProxyBypassW, DWORD dwFlags) { 27 | if (pszAgentW && wcscmp(pszAgentW, L"PSNAccountLinking") == 0) { 28 | if (dwFlags & WINHTTP_FLAG_SECURE_DEFAULTS) { 29 | dwFlags = WINHTTP_FLAG_ASYNC; 30 | } 31 | } 32 | return OriginalWinHttpOpen(pszAgentW, dwAccessType, pszProxyW, pszProxyBypassW, dwFlags); 33 | } 34 | 35 | static HINTERNET WINAPI HookWinHttpConnect(HINTERNET hSession, LPCWSTR pswzServerName, INTERNET_PORT nServerPort, DWORD dwReserved) { 36 | HINTERNET result = 0; 37 | if (pswzServerName && wcscmp(pswzServerName, L"pss-cloud.net") == 0) { 38 | result = OriginalWinHttpConnect(hSession, L"localhost", PSSCLOUD_SERVER_PORT, dwReserved); 39 | { 40 | std::lock_guard lock(g_tracked_handles_mutex); 41 | g_tracked_handles.insert(result); 42 | } 43 | } else { 44 | result = OriginalWinHttpConnect(hSession, pswzServerName, nServerPort, dwReserved); 45 | } 46 | return result; 47 | } 48 | 49 | static HINTERNET WINAPI HookWinHttpOpenRequest(HINTERNET hConnect, LPCWSTR pwszVerb, LPCWSTR pwszObjectName, LPCWSTR pwszVersion, LPCWSTR pwszReferrer, LPCWSTR FAR* ppwszAcceptTypes, DWORD dwFlags) { 50 | bool is_tracked = false; 51 | { 52 | std::lock_guard lock(g_tracked_handles_mutex); 53 | is_tracked = g_tracked_handles.find(hConnect) != g_tracked_handles.end(); 54 | } 55 | if (is_tracked) { 56 | dwFlags &= ~WINHTTP_FLAG_SECURE; 57 | } 58 | return OriginalWinHttpOpenRequest(hConnect, pwszVerb, pwszObjectName, pwszVersion, pwszReferrer, ppwszAcceptTypes, dwFlags); 59 | } 60 | 61 | static BOOL WINAPI HookWinHttpCloseHandle(HINTERNET hInternet) { 62 | { 63 | std::lock_guard lock(g_tracked_handles_mutex); 64 | g_tracked_handles.erase(hInternet); 65 | } 66 | return OriginalWinHttpCloseHandle(hInternet); 67 | } 68 | 69 | void pspcsdk_net_setup() { 70 | if (g_winhttp_dll) { 71 | return; 72 | } 73 | 74 | g_winhttp_dll = LoadLibrary(L"winhttp.dll"); 75 | 76 | if (!g_winhttp_dll) { 77 | return; 78 | } 79 | 80 | OriginalWinHttpOpen = (decltype(OriginalWinHttpOpen))GetProcAddress(g_winhttp_dll, "WinHttpOpen"); 81 | OriginalWinHttpConnect = (decltype(OriginalWinHttpConnect))GetProcAddress(g_winhttp_dll, "WinHttpConnect"); 82 | OriginalWinHttpOpenRequest = (decltype(OriginalWinHttpOpenRequest))GetProcAddress(g_winhttp_dll, "WinHttpOpenRequest"); 83 | 84 | HookFunction(&OriginalWinHttpOpen, HookWinHttpOpen); 85 | HookFunction(&OriginalWinHttpConnect, HookWinHttpConnect); 86 | HookFunction(&OriginalWinHttpOpenRequest, HookWinHttpOpenRequest); 87 | 88 | psscloud_server_start(); 89 | g_tracked_handles.clear(); 90 | } 91 | 92 | void pspcsdk_net_cleanup() { 93 | if (!g_winhttp_dll) { 94 | return; 95 | } 96 | 97 | psscloud_server_stop(); 98 | g_tracked_handles.clear(); 99 | 100 | UnhookFunction(&OriginalWinHttpOpen, HookWinHttpOpen); 101 | UnhookFunction(&OriginalWinHttpConnect, HookWinHttpConnect); 102 | UnhookFunction(&OriginalWinHttpOpenRequest, HookWinHttpOpenRequest); 103 | 104 | FreeLibrary(g_winhttp_dll); 105 | g_winhttp_dll = nullptr; 106 | } 107 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/dialog/signin.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "signin.h" 9 | 10 | #include "../sce.h" 11 | #include "../../utils.h" 12 | #include "../service/user.h" 13 | #include 14 | 15 | static SceDialogStatus g_signin_dialog_status = SCE_DIALOG_STATUS_NOT_INITIALIZED; 16 | 17 | PSPCSDK_API SceResult sceSigninDialogInitialize() { 18 | if (!g_common_dialog_initialized) { 19 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 20 | } 21 | if (g_signin_dialog_status != SCE_DIALOG_STATUS_NOT_INITIALIZED) { 22 | return SCE_ERROR_SIGNIN_DIALOG_ALREADY_INITIALIZED; 23 | } 24 | g_signin_dialog_status = SCE_DIALOG_STATUS_INITIALIZED; 25 | return SCE_OK; 26 | } 27 | 28 | PSPCSDK_API SceResult sceSigninDialogTerminate() { 29 | if (g_signin_dialog_status == SCE_DIALOG_STATUS_NOT_INITIALIZED) { 30 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 31 | } 32 | if (g_signin_dialog_status != SCE_DIALOG_STATUS_INITIALIZED) { 33 | g_common_dialog_busy = false; 34 | } 35 | g_signin_dialog_status = SCE_DIALOG_STATUS_NOT_INITIALIZED; 36 | return SCE_OK; 37 | } 38 | 39 | PSPCSDK_API SceResult sceSigninDialogGetPlatformError(HRESULT* error, uint64_t four) { 40 | if (!error) { 41 | return SCE_ERROR_COMMON_DIALOG_NULL_PARAMETER; 42 | } 43 | if (four != 4) { 44 | return SCE_ERROR_COMMON_DIALOG_INVALID_PARAM; 45 | } 46 | printf("(STUBBED) sceSigninDialogGetPlatformError(%p, %llu)\n", error, four); 47 | *error = 0; 48 | return SCE_OK; 49 | } 50 | 51 | PSPCSDK_API SceResult sceSigninDialogOpen(SceSigninDialogParam* params) { 52 | if (!params) { 53 | return SCE_ERROR_COMMON_DIALOG_NULL_PARAMETER; 54 | } 55 | #pragma warning(push) 56 | #pragma warning(disable: 4311) 57 | #pragma warning(disable: 4302) 58 | int expected_check = ((int) params) - 0x3f2e5ef7; 59 | #pragma warning(pop) 60 | if (params->common.check != expected_check || params->common.unknown0 != 0x38) { 61 | return SCE_ERROR_COMMON_DIALOG_INVALID_PARAM; 62 | } 63 | if (!ismemzero(params->common.reserved, sizeof(params->common.reserved))) { 64 | return SCE_ERROR_COMMON_DIALOG_INVALID_PARAM; 65 | } 66 | if (params->unknown0 != 0x50) { 67 | return SCE_ERROR_COMMON_DIALOG_INVALID_PARAM; 68 | } 69 | if (!ismemzero(params->reserved, sizeof(params->reserved))) { 70 | return SCE_ERROR_COMMON_DIALOG_INVALID_PARAM; 71 | } 72 | if (g_signin_dialog_status == SCE_DIALOG_STATUS_NOT_INITIALIZED) { 73 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 74 | } 75 | if (!params->common.hwnd) { 76 | return SCE_ERROR_COMMON_DIALOG_INVALID_PARAM; 77 | } 78 | if (g_signin_dialog_status != SCE_DIALOG_STATUS_INITIALIZED) { 79 | return SCE_ERROR_COMMON_DIALOG_ALREADY_RUNNING; 80 | } 81 | if (g_common_dialog_busy) { 82 | return SCE_ERROR_COMMON_DIALOG_BUSY; 83 | } 84 | g_common_dialog_busy = true; 85 | g_signin_dialog_status = SCE_DIALOG_STATUS_RUNNING; 86 | return SCE_OK; 87 | } 88 | 89 | PSPCSDK_API SceResult sceSigninDialogClose() { 90 | if (g_signin_dialog_status != SCE_DIALOG_STATUS_RUNNING && g_signin_dialog_status != SCE_DIALOG_STATUS_FINISHED) { 91 | return SCE_ERROR_COMMON_DIALOG_NOT_RUNNING; 92 | } 93 | g_common_dialog_busy = false; 94 | g_signin_dialog_status = SCE_DIALOG_STATUS_INITIALIZED; 95 | return SCE_OK; 96 | } 97 | 98 | PSPCSDK_API SceResult sceSigninDialogGetResult(SceSigninDialogResult* result) { 99 | if (!result) { 100 | return SCE_ERROR_COMMON_DIALOG_NULL_PARAMETER; 101 | } 102 | if (g_signin_dialog_status == SCE_DIALOG_STATUS_NOT_INITIALIZED) { 103 | return SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED; 104 | } 105 | if (g_signin_dialog_status != SCE_DIALOG_STATUS_FINISHED) { 106 | return SCE_ERROR_COMMON_DIALOG_STILL_RUNNING; 107 | } 108 | SceNpAccount* account = get_fake_account_by_account_id(DEFAULT_FAKE_ACCOUNT_ID); 109 | result->error = 0; 110 | result->user_id = account->user_id; 111 | result->account_id = account->account_id; 112 | return SCE_OK; 113 | } 114 | 115 | PSPCSDK_API SceDialogStatus sceSigninDialogGetStatus() { 116 | return g_signin_dialog_status; 117 | } 118 | 119 | PSPCSDK_API SceDialogStatus sceSigninDialogUpdateStatus() { 120 | SceDialogStatus status = g_signin_dialog_status; 121 | if (status == SCE_DIALOG_STATUS_RUNNING) { 122 | SceNpAccount* account = get_fake_account_by_account_id(DEFAULT_FAKE_ACCOUNT_ID); 123 | if (!account) { 124 | load_fake_account(DEFAULT_FAKE_ACCOUNT_ID); 125 | account = get_fake_account_by_account_id(DEFAULT_FAKE_ACCOUNT_ID); 126 | } 127 | account->is_logged_in = true; 128 | g_signin_dialog_status = SCE_DIALOG_STATUS_FINISHED; 129 | } 130 | return status; 131 | } 132 | 133 | void signin_dialog_reset() { 134 | g_signin_dialog_status = SCE_DIALOG_STATUS_NOT_INITIALIZED; 135 | } 136 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/session.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "session.h" 9 | 10 | #include "../sce.h" 11 | #include 12 | 13 | static bool g_session_initialized = false; 14 | 15 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayInitialize(void* param) { 16 | if (!param) { 17 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 18 | } 19 | printf("(STUBBED) sceNpSessionSignalingCrossplayInitialize(%p)\n", param); 20 | g_session_initialized = true; 21 | return SCE_OK; 22 | } 23 | 24 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayTerminate(void) { 25 | if (!g_session_initialized) { 26 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 27 | } 28 | printf("(STUBBED) sceNpSessionSignalingCrossplayTerminate()\n"); 29 | g_session_initialized = false; 30 | return SCE_OK; 31 | } 32 | 33 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayCreateContext(void* param, uint64_t* context) { 34 | if (!g_session_initialized) { 35 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 36 | } 37 | if (!param || !context) { 38 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 39 | } 40 | printf("(STUBBED) sceNpSessionSignalingCrossplayCreateContext(%p, %p)\n", param, context); 41 | return SCE_OK; 42 | } 43 | 44 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayDestroyContext(uint64_t context) { 45 | if (!g_session_initialized) { 46 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 47 | } 48 | printf("(STUBBED) sceNpSessionSignalingCrossplayDestroyContext(%llu)\n", context); 49 | return SCE_OK; 50 | } 51 | 52 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayActivateUser(uint64_t context, uint64_t* param, uint64_t unknown3) { 53 | if (!g_session_initialized) { 54 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 55 | } 56 | if (!param || !unknown3 || !param[0] || !param[1]) { 57 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 58 | } 59 | printf("(STUBBED) sceNpSessionSignalingCrossplayActivateUser(%llx, %p, %llx)\n", context, param, unknown3); 60 | return SCE_OK; 61 | } 62 | 63 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayActivateSession(uint64_t context, void* unknown2, uint64_t unknown3, void* unknown4, void* unknown5) { 64 | if (!unknown2 || !unknown4 || !unknown5) { 65 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 66 | } 67 | if (!g_session_initialized) { 68 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 69 | } 70 | printf("(STUBBED) sceNpSessionSignalingCrossplayActivateSession(%llx, %p, %llx, %p, %p)\n", context, unknown2, unknown3, unknown4, unknown5); 71 | return SCE_OK; 72 | } 73 | 74 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayDeactivate(uint64_t context, uint64_t unknown2) { 75 | if (!g_session_initialized) { 76 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 77 | } 78 | printf("(STUBBED) sceNpSessionSignalingCrossplayDeactivate(%llx, %llx)\n", context, unknown2); 79 | return SCE_OK; 80 | } 81 | 82 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayRequestPrepare(uint64_t context, void* params) { 83 | if (!params) { 84 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 85 | } 86 | if (!g_session_initialized) { 87 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 88 | } 89 | printf("(STUBBED) sceNpSessionSignalingCrossplayPrepareRequest(%llx, %p)\n", context, params); 90 | return SCE_OK; 91 | } 92 | 93 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayEstablishConnection(uint64_t context, void* unknown2, void* unknown3, uint64_t* unknown4, void* unknown5, uint64_t unknown6, void* unknown7) { 94 | if (!g_session_initialized) { 95 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 96 | } 97 | if (!unknown4 || !unknown4[0] || !unknown4[1] || unknown6 > 0x40 || !unknown7) { 98 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 99 | } 100 | printf("(STUBBED) sceNpSessionSignalingCrossplayEstablishConnection(%llx, %p, %p, %p, %p, %llx, %p)\n", context, unknown2, unknown3, unknown4, unknown5, unknown6, unknown7); 101 | return SCE_OK; 102 | } 103 | 104 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayAbortConnection(uint64_t context, uint64_t unknown2) { 105 | if (!g_session_initialized) { 106 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 107 | } 108 | printf("(STUBBED) sceNpSessionSignalingCrossplayAbortConnection(%llx, %llx)\n", context, unknown2); 109 | return SCE_OK; 110 | } 111 | 112 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayGetMemoryInfo(void* out) { 113 | if (!out) { 114 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 115 | } 116 | if (!g_session_initialized) { 117 | return SCE_ERROR_NP_SESSION_NOT_INITIALIZED; 118 | } 119 | printf("(STUBBED) sceNpSessionSignalingCrossplayGetMemoryInfo(%p)\n", out); 120 | return SCE_OK; 121 | } 122 | 123 | PSPCSDK_API SceResult sceNpSessionSignalingCrossplayGetPlatformError(HRESULT* error, uint64_t four) { 124 | if (!error || four != 4) { 125 | return SCE_ERROR_NP_SESSION_NULL_PARAM; 126 | } 127 | printf("(STUBBED) sceNpSessionSignalingCrossplayGetPlatformError(%p, %llx)\n", error, four); 128 | return SCE_OK; 129 | } 130 | 131 | void np_session_reset() { 132 | g_session_initialized = false; 133 | } 134 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/auth.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "auth.h" 9 | 10 | #include "../sce.h" 11 | #include "../../utils.h" 12 | #include 13 | 14 | static IdProvider g_auth_requests; 15 | 16 | PSPCSDK_API SceResult sceNpAuthAbortRequest(uint32_t request) { 17 | if (!request) { 18 | return SCE_ERROR_NP_INVALID_PARAM; 19 | } 20 | g_auth_requests.free_id(request); 21 | printf("(STUBBED) sceNpAuthAbortRequest(%d)\n", request); 22 | return SCE_OK; 23 | } 24 | 25 | PSPCSDK_API SceResult sceNpAuthCreateAsyncRequest(uint32_t request) { 26 | if (request) { 27 | return SCE_ERROR_NP_INVALID_PARAM; 28 | } 29 | printf("(STUBBED) sceNpAuthCreateAsyncRequest(%d)\n", request); 30 | return SCE_OK; 31 | } 32 | 33 | PSPCSDK_API uint32_t sceNpAuthCreateRequest() { 34 | return g_auth_requests.new_id(); 35 | } 36 | 37 | PSPCSDK_API SceResult sceNpAuthDeleteRequest(int request) { 38 | if (request) { 39 | return SCE_ERROR_NP_INVALID_PARAM; 40 | } 41 | g_auth_requests.free_id(request); 42 | printf("(STUBBED) sceNpAuthDeleteRequest(%d)\n", request); 43 | return SCE_OK; 44 | } 45 | 46 | PSPCSDK_API SceResult sceNpAuthGetAuthorizationCodeV3(uint32_t request, void** data, char* auth_code, uint64_t* environment) { 47 | if (!request || !data || !auth_code || !environment) { 48 | return SCE_ERROR_NP_INVALID_PARAM; 49 | } 50 | // we need to check request id here 51 | *environment = 256; // environemnt can be 1 or 256. We must set to 100. (maybe 1 is for dev environment) 52 | strcpy_s(auth_code, 135, "v3.AbCdEf"); 53 | printf("(STUBBED) sceNpAuthGetAuthorizationCodeV3(%d, %p, %p, %p)\n", request, data, auth_code, environment); 54 | return SCE_OK; 55 | } 56 | 57 | PSPCSDK_API SceResult sceNpAuthGetPlatformError(int unkdown1, HRESULT* error, uint64_t unknown3) { 58 | if (!unkdown1 || !error || unknown3 != 4) { 59 | return SCE_ERROR_NP_INVALID_PARAM; 60 | } 61 | printf("(STUBBED) sceNpAuthGetPlatformError(%x, %p, %llx)\n", unkdown1, error, unknown3); 62 | return SCE_OK; 63 | } 64 | 65 | PSPCSDK_API SceResult sceNpAuthPollAsync(int unknown1, uint64_t unknown2) { 66 | if (!unknown1 || !unknown2) { 67 | return SCE_ERROR_NP_INVALID_PARAM; 68 | } 69 | printf("(STUBBED) sceNpAuthPollAsync(%x, %llx)\n", unknown1, unknown2); 70 | return SCE_OK; 71 | } 72 | 73 | PSPCSDK_API SceResult sceNpAuthSetTimeout(int unknown1, int unknown2, int unknown3, int unknown4, int unknown5) { 74 | if ((unknown1 != 0 && unknown1 < 1000000) || 75 | (unknown2 != 0 && unknown2 < 10000000) || 76 | (unknown3 != 0 && unknown3 < 10000000) || 77 | (unknown4 != 0 && unknown4 < 10000000) || 78 | (unknown5 != 0 && unknown5 < 10000000)) { 79 | return SCE_ERROR_NP_INVALID_PARAM; 80 | } 81 | printf("(STUBBED) sceNpAuthSetTimeout(%d, %d, %d, %d, %d)\n", unknown1, unknown2, unknown3, unknown4, unknown5); 82 | return SCE_OK; 83 | } 84 | 85 | PSPCSDK_API SceResult sceNpAuthWaitAsync(int unknown1, uint64_t unknown2) { 86 | if (!unknown1 || !unknown2) { 87 | return SCE_ERROR_NP_INVALID_PARAM; 88 | } 89 | printf("(STUBBED) sceNpAuthWaitAsync(%x, %llx)\n", unknown1, unknown2); 90 | return SCE_OK; 91 | } 92 | 93 | PSPCSDK_API SceResult sceNpCreateAsyncRequest(uint64_t request) { 94 | if (request) { 95 | return SCE_ERROR_NP_INVALID_PARAM; 96 | } 97 | printf("(STUBBED) sceNpCreateAsyncRequest(%llx)\n", request); 98 | return SCE_OK; 99 | } 100 | 101 | PSPCSDK_API SceResult sceNpCreateRequest() { 102 | printf("(STUBBED) sceNpCreateRequest()\n"); 103 | return SCE_OK; 104 | } 105 | 106 | PSPCSDK_API SceResult sceNpDeleteRequest(int request) { 107 | if (request) { 108 | return SCE_ERROR_NP_INVALID_PARAM; 109 | } 110 | printf("(STUBBED) sceNpDeleteRequest(%d)\n", request); 111 | return SCE_OK; 112 | } 113 | 114 | PSPCSDK_API SceResult sceNpAbortRequest(uint64_t request) { 115 | if (!request) { 116 | return SCE_ERROR_NP_INVALID_PARAM; 117 | } 118 | printf("(STUBBED) sceNpAbortRequest(%llx)\n", request); 119 | return SCE_OK; 120 | } 121 | 122 | PSPCSDK_API SceResult sceNpPollAsync(int unknown1, void* unknown2) { 123 | if (unknown1 < 0 || !unknown2) { 124 | return SCE_ERROR_NP_INVALID_PARAM; 125 | } 126 | printf("(STUBBED) sceNpPollAsync(%d, %p)\n", unknown1, unknown2); 127 | return SCE_OK; 128 | } 129 | 130 | PSPCSDK_API SceResult sceNpSetTimeout(int unknown1, int unknown2, int unknown3, int unknown4, int unknown5) { 131 | if ((unknown1 != 0 && unknown1 < 1000000) || 132 | (unknown2 != 0 && unknown2 < 10000000) || 133 | (unknown3 != 0 && unknown3 < 10000000) || 134 | (unknown4 != 0 && unknown4 < 10000000) || 135 | (unknown5 != 0 && unknown5 < 10000000)) { 136 | return SCE_ERROR_NP_INVALID_PARAM; 137 | } 138 | printf("(STUBBED) sceNpSetTimeout(%d, %d, %d, %d, %d)\n", unknown1, unknown2, unknown3, unknown4, unknown5); 139 | return SCE_OK; 140 | } 141 | 142 | 143 | PSPCSDK_API SceResult sceNpWaitAsync(int handle, int* status) { 144 | if (!status || handle < 1) { 145 | return SCE_ERROR_NP_NULL_PARAMETER; 146 | } 147 | printf("(STUBBED) sceNpWaitAsync(%d, %p)\n", handle, status); 148 | return SCE_OK; 149 | } 150 | 151 | void np_auth_reset() { 152 | g_auth_requests.reset(); 153 | } 154 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/sceerror.h: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | typedef uint32_t SceResult; 13 | 14 | #define SCE_OK 0x0 15 | 16 | // PC 17 | #define SCE_ERROR_PC_INVALID_DATA_COLLECTION_MODE 0x8a800104 18 | 19 | // Dialog 20 | #define SCE_ERROR_COMMON_DIALOG_BUSY 0x80b80001 // might be wrong 21 | #define SCE_ERROR_COMMON_DIALOG_ALREADY_INITIALIZED 0x80b80002 22 | #define SCE_ERROR_COMMON_DIALOG_NOT_INITIALIZED 0x80b80003 23 | #define SCE_ERROR_COMMON_DIALOG_STILL_RUNNING 0x80b80005 24 | #define SCE_ERROR_COMMON_DIALOG_ALREADY_RUNNING 0x80b80006 25 | #define SCE_ERROR_COMMON_DIALOG_INVALID_PARAM 0x80b8000a 26 | #define SCE_ERROR_COMMON_DIALOG_NOT_RUNNING 0x80b8000b 27 | #define SCE_ERROR_COMMON_DIALOG_NULL_PARAMETER 0x80b8000d 28 | #define SCE_ERROR_COMMON_DIALOG_INITIALIZING 0x8a80000e 29 | 30 | // Signin Dialog 31 | #define SCE_ERROR_SIGNIN_DIALOG_ALREADY_INITIALIZED 0x80b80004 32 | 33 | // Np 34 | #define SCE_ERROR_NP_NOT_INITIALIZED 0x80550002 35 | #define SCE_ERROR_NP_NULL_PARAMETER 0x80550003 36 | #define SCE_ERROR_NP_INVALID_PARAM 0x80550301 37 | 38 | // Np Callback 39 | #define SCE_ERROR_NP_CALLBACK_ALREADY_REGISTERED 0x80550008 40 | #define SCE_ERROR_NP_CALLBACK_NOT_REGISTERED 0x80550009 41 | #define SCE_ERROR_NP_CALLBACK_NO_FREE_SLOT 0x8055001d 42 | 43 | // Np Auth 44 | 45 | // some trophy erros 46 | // 0x80553901, 0x80553904, 0x88553909, 0x805539d1 47 | 48 | // Np Universal Data System (THIS IS A GUESS) 49 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_ALREADY_INITIALIZED 0x80553118 50 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM 0x80553102 51 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_CONTEXT 0x80553104 52 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_HANDLE 0x80553106 53 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_EVENT_NAME 0x8055310d; 54 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM_UNK1 0x80553112 55 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY 0x80553114 56 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_BUFFER 0x80553115 57 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_EVENT 0x80553116 58 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED 0x80553017 59 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST 0x80553119 60 | #define SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST 0x8055311a 61 | 62 | // Np Web API 2 63 | #define SCE_ERROR_NP_WEB_API2_INVALID_USER 0x80553401 64 | #define SCE_ERROR_NP_WEB_API2_INVALID_PARAM 0x80553402 65 | #define SCE_ERROR_NP_WEB_API2_INVALID_CONTEXT 0x80553403 66 | #define SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED 0x80553404 67 | #define SCE_ERROR_NP_WEB_API2_INVALID_USER_CONTEXT 0x80553405 68 | #define SCE_ERROR_NP_WEB_API2_FULL_CONTEXT_POOL 0x80553418 69 | 70 | // Np Session 71 | #define SCE_ERROR_NP_SESSION_NOT_INITIALIZED 0x80553d01 72 | #define SCE_ERROR_NP_SESSION_NULL_PARAM 0x80553d03 73 | 74 | // System Service 75 | #define SCE_ERROR_SYSTEM_SERVICE_INVALID_PARAM 0x80a10003 76 | 77 | // User Service 78 | #define SCE_ERROR_USER_SERVICE_INVALID_PARAM 0x80960005 79 | 80 | // RUDP (errors are from the PS4. Might be different on the PC) 81 | #define SCE_ERROR_RUDP_NOT_INITIALIZED 0x80770001 82 | #define SCE_ERROR_RUDP_ALREADY_INITIALIZED 0x80770002 83 | #define SCE_ERROR_RUDP_INVALID_CONTEXT_ID 0x80770003 84 | #define SCE_ERROR_RUDP_INVALID_ARGUMENT 0x80770004 85 | #define SCE_ERROR_RUDP_INVALID_OPTION 0x80770005 86 | #define SCE_ERROR_RUDP_INVALID_MUXMODE 0x80770006 87 | #define SCE_ERROR_RUDP_MEMORY 0x80770007 88 | #define SCE_ERROR_RUDP_INTERNAL 0x80770008 89 | #define SCE_ERROR_RUDP_CONN_RESET 0x80770009 90 | #define SCE_ERROR_RUDP_CONN_REFUSED 0x8077000A 91 | #define SCE_ERROR_RUDP_CONN_TIMEOUT 0x8077000B 92 | #define SCE_ERROR_RUDP_CONN_VERSION_MISMATCH 0x8077000C 93 | #define SCE_ERROR_RUDP_CONN_TRANSPORT_TYPE_MISMATCH 0x8077000D 94 | #define SCE_ERROR_RUDP_CONN_QUALITY_LEVEL_MISMATCH 0x8077000E 95 | #define SCE_ERROR_RUDP_THREAD 0x8077000F 96 | #define SCE_ERROR_RUDP_THREAD_IN_USE 0x80770010 97 | #define SCE_ERROR_RUDP_NOT_ACCEPTABLE 0x80770011 98 | #define SCE_ERROR_RUDP_MSG_TOO_LARGE 0x80770012 99 | #define SCE_ERROR_RUDP_NOT_BOUND 0x80770013 100 | #define SCE_ERROR_RUDP_CANCELLED 0x80770014 101 | #define SCE_ERROR_RUDP_INVALID_VPORT 0x80770015 102 | #define SCE_ERROR_RUDP_WOULDBLOCK 0x80770016 103 | #define SCE_ERROR_RUDP_VPORT_IN_USE 0x8077001 104 | #define SCE_ERROR_RUDP_VPORT_EXHAUSTED 0x80770018 105 | #define SCE_ERROR_RUDP_INVALID_SOCKET 0x80770019 106 | #define SCE_ERROR_RUDP_BUFFER_TOO_SMALL 0x8077001A 107 | #define SCE_ERROR_RUDP_MSG_MALFORMED 0x8077001B 108 | #define SCE_ERROR_RUDP_ADDR_IN_USE 0x8077001C 109 | #define SCE_ERROR_RUDP_ALREADY_BOUND 0x8077001D 110 | #define SCE_ERROR_RUDP_ALREADY_EXISTS 0x8077001E 111 | #define SCE_ERROR_RUDP_INVALID_POLL_ID 0x8077001F 112 | #define SCE_ERROR_RUDP_TOO_MANY_CONTEXTS 0x80770020 113 | #define SCE_ERROR_RUDP_IN_PROGRESS 0x80770021 114 | #define SCE_ERROR_RUDP_NO_EVENT_HANDLER 0x80770022 115 | #define SCE_ERROR_RUDP_PAYLOAD_TOO_LARGE 0x80770023 116 | #define SCE_ERROR_RUDP_END_OF_DATA 0x80770024 117 | #define SCE_ERROR_RUDP_ALREADY_ESTABLISHED 0x80770025 118 | #define SCE_ERROR_RUDP_KEEP_ALIVE_FAILURE 0x80770026 119 | #define SCE_ERROR_RUDP_MEMLEAK 0x807700FF 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PsPcSdk Emulator 2 | This utility allows you to bypass the PlayStation Network account login requirement for various Sony-published games on PC. 3 | 4 | Now that Sony has made Playstation Network accounts optional on PC, you can use this utility to obtain the benefits of a PSN account without creating one. 5 | 6 | __NOTE__: This does not work for the online components of those games. Do not use it for that purpose. 7 | 8 | ## Tested Games 9 | The utility has been tested on the Steam versions of the following games: 10 | - God of War: Ragnarök 11 | - Horizon Zero Dawn: Remastered 12 | - Until Dawn 13 | - LEGO Horizon Adventures 14 | - Marvel's Spider-Man 2 15 | 16 | All these games work out of the box with PsPcSdk Emulator. 17 | 18 | ## How to Use 19 | Follow the instructions for your platform to install PsPcSdk Emulator. 20 | 21 | ### Windows 22 | 1. Go to the [releases page](https://github.com/LNDF/PsPcSdkEmulator/releases/latest). 23 | 1. Download the `version.dll` file from the latest version. 24 | 1. Place the file in the same folder as the executable of the game. See below on how to find the game executable. 25 | 1. Run the game. You will no longer see the PlayStation Login prompt. 26 | 27 | ### Linux 28 | 1. Go to the [releases page](https://github.com/LNDF/PsPcSdkEmulator/releases/latest). 29 | 1. Download the `version.dll` file from the latest version. 30 | 1. Place the file in the same folder as the executable of the game. See below on how to find the game executable. 31 | 1. Right-click the game on Steam and select Properties. 32 | 1. In the Launch Options box, enter: `WINEDLLOVERRIDES="version=n,b" %command%` 33 | 1. Run the game. You will no longer see the PlayStation Login prompt. 34 | 35 | ### How to Find the Game Executable 36 | 1. Right-click the game on Steam and select Properties. 37 | 1. Click on the LOCAL FILES tab. 38 | 1. Click Browse Local Files... 39 | 1. You will find a file with the game icon and the `.exe` extension. That is the executable file. 40 | 41 | __IMPORTANT__ note on Unreal Engine games (Until Dawn and LEGO Horizon Adventures): Unreal Engine games store the real game executable in a different location. You can identify Unreal Engine games because they usually have an `Engine` folder, another folder with the name of the project (`Glow` for LEGO Horizon Adventures and `Bates` for Until Dawn), and an executable file. In Unreal Engine games, the real executable is located under the folder with the project name, then `Binaries`, and then `Win64`. Place `version.dll` there. 42 | 43 | ### Custom DLL loader (advanced users) 44 | PsPcSdk Emulator supports being loaded by an external DLL loader. Just rename `version.dll` to something else an point the DLL loader to it. 45 | 46 | This can be useful when loading multiple mods that use the same DLL name (`version.dll` in this case). 47 | 48 | ## How it works 49 | All the source code is located under `PsPcSdkEmulator/src/` and the project is dividen in several parts. 50 | 51 | ### Loader 52 | Located in the `loader` folder, this part of PsPcSdk Emulator is responsable for making the game load this implementation of the Playstation SDK insteed of the one provided by Sony. To achive that, Microsoft Detours is used to hook some Win32 functions. 53 | 54 | ### SDK 55 | The `sdk` folder provides stubs and some implementations of the Playstation SDK functions. Once the loader makes the game load PsPcSdk Emulator as if it was the Playstation SDK, the game links against this implementations insteed of the original ones. 56 | 57 | ### Net (pss-cloud.net / PSNAccountLinking library) 58 | Playstation games on PC are built with a Playstation account linking library (`PSNAccountLinking`) which is responsable for linking Steam and PSN accounts. `PSNAccountLinking` relies on `pss-cloud.net` for account linking. Inside the `net` folder there is a local HTTP server that is started when the game calls the `scePsPcInitializeInternal()` SDK function. That HTTP server emulates `pss-cloud.net` telling the game that a PSN account is already linked to the Steam account and accepting any new link requqests. Additionaly, WinHttp functions are hooked so that requests to `pss-cloud.net` are redirected to the local HTTP server. 59 | 60 | ## Building 61 | 1. Clone this repository. 62 | 1. Open the solution in Visual Studio (built on 2022). 63 | 1. Build the project. It will automatically sign the built DLL with a fake certificate. 64 | 1. The DLL can be found on `x64/{Debug/Release}/PsPcSdkEmulator.dll` rename it to `version.dll` to use it. 65 | 66 | ### Recreating the Fake Certificate 67 | A fake certificate is required for PsPcSdk Emulator to load in place of the official PlayStation SDK. You can regenerate it by running the `RunMakeCert.bat` script inside the project folder. The new certificate will be saved to `/src/loader/cert.pfx` and will automatically be used to sign when building. 68 | 69 | ## Contributing 70 | Just submit a PR. There are some things to improove: 71 | * Write actual implementations of the currently stubbed functions. 72 | * Verify that the HTTP responses for Until Dawn are correct, since the game uses different endpoints. 73 | * Improve the structure and add features to the current code (custom Online id for the PSN account, track trophie completion...) 74 | 75 | ## License 76 | This project is licensed under the **Mozilla Public License 2.0**. 77 | You are free to use, modify, and distribute this project, as long as you comply with the terms of MPL-2.0. 78 | See the [LICENSE](./LICENSE) file for details. 79 | 80 | ### Third-Party Dependencies 81 | This project uses **Microsoft Detours**, which is licensed under the **MIT License**. 82 | You can see the license [here](./PsPcSdkEmulator/external/detours/LICENSE). 83 | 84 | ## Libraries Used 85 | PsPcSdk Emulator uses [Microsoft Detours](https://github.com/microsoft/Detours) for hooking Windows functions. 86 | 87 | ## Credits 88 | To the author of the nopcpssdk mod for God of War: Ragnarök. I took some ideas from that mod about the DLL loading process. Also, nopcpssdk was the reason I made this project, as it showed that it could be done. I'm not naming him here since he deleted the mod. 89 | 90 | Nixxes for leaving some logging enabled on Horizon Zero Dawn Remastered. It helped. 91 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/loader/hooks.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "hooks.h" 9 | 10 | #include "../utils.h" 11 | #include "dllmain.h" 12 | #include "procs.h" 13 | #include 14 | #include 15 | #include 16 | 17 | ///////////////////////////////////////// 18 | // Hooked functions 19 | ///////////////////////////////////////// 20 | 21 | static decltype(FindFirstFileExA)* OriginalFindFirstFileExA = nullptr; 22 | static decltype(FindNextFileA)* OriginalFindNextFileA = nullptr; 23 | static decltype(FindClose)* OriginalFindClose = nullptr; 24 | static decltype(PathFileExistsA)* OriginalPathFileExistsA = nullptr; 25 | static decltype(CreateFileA)* OriginalCreateFileA = nullptr; 26 | static decltype(GetFileVersionInfoSizeA)* OriginalGetFileVersionInfoSizeA = nullptr; 27 | static decltype(GetFileVersionInfoA)* OriginalGetFileVersionInfoA = nullptr; 28 | static decltype(WinVerifyTrust)* OriginalWinVerifyTrust = nullptr; 29 | static decltype(WTHelperProvDataFromStateData)* OriginalWTHelperProvDataFromStateData = nullptr; 30 | static decltype(WTHelperGetProvSignerFromChain)* OriginalWTHelperGetProvSignerFromChain = nullptr; 31 | static decltype(LoadLibraryExA)* OriginalLoadLibraryExA = nullptr; 32 | 33 | static HMODULE g_wintrust_dll = nullptr; 34 | 35 | #define FAKE_HANDLE_MAGIC 0x12345438 36 | static DWORD g_fake_handle = FAKE_HANDLE_MAGIC; 37 | 38 | static HANDLE WINAPI HookFindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags) { 39 | // We need to tell the game that the SDK is installed 40 | WIN32_FIND_DATAA& data = *reinterpret_cast(lpFindFileData); 41 | const char* sdk_path_start = "C:\\ProgramData\\Sony Interactive Entertainment Inc\\PSPC_SDK"; 42 | 43 | // Check both the start of the path and the wildcard (the "S22" part may change in the future) 44 | if (!lpFileName || strncmp(lpFileName, sdk_path_start, strlen(sdk_path_start)) != 0 || lpFileName[strlen(lpFileName) - 1] != '*') { 45 | return OriginalFindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); 46 | } 47 | 48 | // We need to return a handle to the SDK directory 49 | memset(&data, 0, sizeof(WIN32_FIND_DATAA)); 50 | data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; 51 | 52 | // We set the what would be the SDK directory 53 | strncpy_s(data.cFileName, sizeof(data.cFileName), lpFileName, _TRUNCATE); 54 | strncpy_s(data.cFileName + strlen(data.cFileName) - 1, sizeof(data.cFileName) - strlen(data.cFileName) + 1, "3.50.00.11", _TRUNCATE); 55 | GetShortPathNameA(data.cFileName, data.cAlternateFileName, sizeof(data.cAlternateFileName)); 56 | 57 | return reinterpret_cast(&g_fake_handle); 58 | } 59 | 60 | static BOOL WINAPI HookFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) { 61 | DWORD* info = reinterpret_cast(hFindFile); 62 | if (!info || info != &g_fake_handle || *info != FAKE_HANDLE_MAGIC) { 63 | return OriginalFindNextFileA(hFindFile, lpFindFileData); 64 | } 65 | 66 | // Only one file in the SDK directory 67 | SetLastError(ERROR_NO_MORE_FILES); 68 | return FALSE; 69 | } 70 | 71 | static BOOL WINAPI HookFindClose(HANDLE hFindFile) { 72 | DWORD* info = reinterpret_cast(hFindFile); 73 | if (!info || info != &g_fake_handle || *info != FAKE_HANDLE_MAGIC) { 74 | return OriginalFindClose(hFindFile); 75 | } 76 | 77 | return TRUE; 78 | } 79 | 80 | static BOOL WINAPI HookPathFileExistsA(LPCSTR pszPath) { 81 | if (strendswith(pszPath, "PsPcSdk.dll")) { 82 | return TRUE; 83 | } 84 | return OriginalPathFileExistsA(pszPath); 85 | } 86 | 87 | static DWORD APIENTRY HookGetFileVersionInfoSizeA(LPCSTR lptstrFilename, LPDWORD lpdwHandle) { 88 | if (strendswith(lptstrFilename, "PsPcSdk.dll")) { 89 | // We include the same version info as PsPcSdk.dll 90 | return GetFileVersionInfoSizeW(g_cuurent_dll_path, lpdwHandle); 91 | } 92 | return OriginalGetFileVersionInfoSizeA(lptstrFilename, lpdwHandle); 93 | } 94 | 95 | static BOOL APIENTRY HookGetFileVersionInfoA(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) { 96 | if (strendswith(lptstrFilename, "PsPcSdk.dll")) { 97 | // We include the same version info as PsPcSdk.dll 98 | #pragma warning(push) 99 | #pragma warning(disable: 6388) 100 | return GetFileVersionInfoW(g_cuurent_dll_path, dwHandle, dwLen, lpData); 101 | #pragma warning(pop) 102 | } 103 | return OriginalGetFileVersionInfoA(lptstrFilename, dwHandle, dwLen, lpData); 104 | } 105 | 106 | static HANDLE WINAPI HookCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { 107 | if (strendswith(lpFileName, "PsPcSdk.dll")) { 108 | // Used to obtain the cerificate from PsPcSdk.dll. We use a self signed certificate. 109 | return CreateFileW(g_cuurent_dll_path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 110 | } 111 | return OriginalCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 112 | } 113 | 114 | static LONG WINAPI HookWinVerifyTrust(HWND hwnd, GUID* pgActionID, LPVOID pWVTData) { 115 | const GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; 116 | if (pgActionID && memcmp(pgActionID, &generic_action_v2, sizeof(GUID)) == 0) { 117 | WINTRUST_DATA* data = reinterpret_cast(pWVTData); 118 | if (data->dwUnionChoice == WTD_CHOICE_FILE && wstrendswith(data->pFile->pcwszFilePath, L"PsPcSdk.dll")) { 119 | data->hWVTStateData = reinterpret_cast(&g_fake_handle); 120 | return ERROR_SUCCESS; 121 | } 122 | } 123 | return OriginalWinVerifyTrust(hwnd, pgActionID, pWVTData); 124 | } 125 | 126 | static CRYPT_PROVIDER_DATA* WINAPI HookWTHelperProvDataFromStateData(HANDLE hStateData) { 127 | DWORD* info = reinterpret_cast(hStateData); 128 | if (info && info == &g_fake_handle && *info == FAKE_HANDLE_MAGIC) { 129 | return reinterpret_cast(info); 130 | } 131 | return OriginalWTHelperProvDataFromStateData(hStateData); 132 | } 133 | 134 | static CRYPT_PROVIDER_SGNR* WINAPI HookWTHelperGetProvSignerFromChain(CRYPT_PROVIDER_DATA* pProvData, DWORD idxSigner, BOOL fCounterSigner, DWORD idxCounterSigner) { 135 | DWORD* info = reinterpret_cast(pProvData); 136 | if (info && info == &g_fake_handle && *info == FAKE_HANDLE_MAGIC) { 137 | return nullptr; 138 | } 139 | return OriginalWTHelperGetProvSignerFromChain(pProvData, idxSigner, fCounterSigner, idxCounterSigner); 140 | } 141 | 142 | static HMODULE WINAPI HookLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { 143 | if (strendswith(lpLibFileName, "PsPcSdk.dll")) { 144 | // The game may pass the handle to FreeLibrary 145 | pspcsdk_hooks_cleanup(); 146 | return LoadLibraryW(g_cuurent_dll_path); 147 | } 148 | return OriginalLoadLibraryExA(lpLibFileName, hFile, dwFlags); 149 | } 150 | 151 | ///////////////////////////////////////// 152 | // Initialization 153 | ///////////////////////////////////////// 154 | 155 | void pspcsdk_hooks_setup() { 156 | if (g_wintrust_dll) { 157 | return; 158 | } 159 | 160 | g_wintrust_dll = LoadLibraryA("wintrust.dll"); 161 | if (!g_wintrust_dll) { 162 | MessageBoxA(nullptr, "Failed to load wintrust.dll. PsPcSdkEmulator will not be initialized.", "PsPcSdkEmulator error", MB_ICONERROR); 163 | return; 164 | } 165 | 166 | OriginalFindFirstFileExA = &FindFirstFileExA; 167 | OriginalFindNextFileA = &FindNextFileA; 168 | OriginalFindClose = &FindClose; 169 | OriginalPathFileExistsA = &PathFileExistsA; 170 | 171 | // See procs.c 172 | OriginalGetFileVersionInfoSizeA = (decltype(OriginalGetFileVersionInfoSizeA)) g_version_dll_procs[4]; 173 | OriginalGetFileVersionInfoA = (decltype(OriginalGetFileVersionInfoA)) g_version_dll_procs[0]; 174 | 175 | OriginalCreateFileA = &CreateFileA; 176 | 177 | OriginalWinVerifyTrust = (decltype(OriginalWinVerifyTrust)) GetProcAddress(g_wintrust_dll, "WinVerifyTrust"); 178 | OriginalWTHelperProvDataFromStateData = (decltype(OriginalWTHelperProvDataFromStateData))GetProcAddress(g_wintrust_dll, "WTHelperProvDataFromStateData"); 179 | OriginalWTHelperGetProvSignerFromChain = (decltype(OriginalWTHelperGetProvSignerFromChain))GetProcAddress(g_wintrust_dll, "WTHelperGetProvSignerFromChain"); 180 | OriginalLoadLibraryExA = &LoadLibraryExA; 181 | 182 | HookFunction(&OriginalFindFirstFileExA, HookFindFirstFileExA); 183 | HookFunction(&OriginalFindNextFileA, HookFindNextFileA); 184 | HookFunction(&OriginalFindClose, HookFindClose); 185 | HookFunction(&OriginalPathFileExistsA, HookPathFileExistsA); 186 | HookFunction(&OriginalGetFileVersionInfoSizeA, HookGetFileVersionInfoSizeA); 187 | HookFunction(&OriginalGetFileVersionInfoA, HookGetFileVersionInfoA); 188 | HookFunction(&OriginalCreateFileA, HookCreateFileA); 189 | HookFunction(&OriginalWinVerifyTrust, HookWinVerifyTrust); 190 | HookFunction(&OriginalWTHelperProvDataFromStateData, HookWTHelperProvDataFromStateData); 191 | HookFunction(&OriginalWTHelperGetProvSignerFromChain, HookWTHelperGetProvSignerFromChain); 192 | HookFunction(&OriginalLoadLibraryExA, HookLoadLibraryExA); 193 | } 194 | 195 | void pspcsdk_hooks_cleanup() { 196 | if (!g_wintrust_dll) { 197 | return; 198 | } 199 | 200 | UnhookFunction(&OriginalFindFirstFileExA, HookFindFirstFileExA); 201 | UnhookFunction(&OriginalFindNextFileA, HookFindNextFileA); 202 | UnhookFunction(&OriginalFindClose, HookFindClose); 203 | UnhookFunction(&OriginalPathFileExistsA, HookPathFileExistsA); 204 | UnhookFunction(&OriginalGetFileVersionInfoSizeA, HookGetFileVersionInfoSizeA); 205 | UnhookFunction(&OriginalGetFileVersionInfoA, HookGetFileVersionInfoA); 206 | UnhookFunction(&OriginalCreateFileA, HookCreateFileA); 207 | UnhookFunction(&OriginalWinVerifyTrust, HookWinVerifyTrust); 208 | UnhookFunction(&OriginalWTHelperProvDataFromStateData, HookWTHelperProvDataFromStateData); 209 | UnhookFunction(&OriginalWTHelperGetProvSignerFromChain, HookWTHelperGetProvSignerFromChain); 210 | UnhookFunction(&OriginalLoadLibraryExA, HookLoadLibraryExA); 211 | 212 | FreeLibrary(g_wintrust_dll); 213 | g_wintrust_dll = nullptr; 214 | } 215 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/net/http.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "http.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | void HttpResponse::send_response(SOCKET client_socket) { 15 | std::ostringstream response_stream; 16 | response_stream << "HTTP/1.1 " << status << "\r\n"; 17 | for (const auto& [key, value] : headers) { 18 | if (key != "Content-Length") { 19 | response_stream << key << ": " << value << "\r\n"; 20 | } 21 | } 22 | response_stream << "Content-Length: " << body.size() << "\r\n\r\n" << body; 23 | std::string response = response_stream.str(); 24 | send(client_socket, response.c_str(), static_cast(response.size()), 0); 25 | } 26 | 27 | int HttpServer::server_count = 0; 28 | 29 | bool HttpServer::wsa_init() { 30 | if (server_count == 0) { 31 | WSADATA wsa_data; 32 | if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { 33 | return false; 34 | } 35 | } 36 | server_count++; 37 | return true; 38 | } 39 | 40 | void HttpServer::wsa_cleanup() { 41 | if (--server_count == 0) { 42 | WSACleanup(); 43 | } 44 | } 45 | 46 | std::unordered_map HttpServer::parse_headers(const std::string& request) { 47 | std::unordered_map headers; 48 | std::istringstream stream(request); 49 | std::string line; 50 | std::getline(stream, line); 51 | while (std::getline(stream, line) && line != "\r") { 52 | size_t colon_pos = line.find(':'); 53 | if (colon_pos != std::string::npos) { 54 | std::string_view key = std::string_view(line).substr(0, colon_pos); 55 | std::string_view value = std::string_view(line).substr(colon_pos + 1); 56 | auto trim = [](std::string_view str) { 57 | auto start = str.find_first_not_of(" \t\r\n"); 58 | auto end = str.find_last_not_of(" \t\r\n"); 59 | return start == std::string_view::npos ? "" : str.substr(start, end - start + 1); 60 | }; 61 | key = trim(key); 62 | value = trim(value); 63 | headers[std::string(key)] = std::string(value); 64 | } 65 | } 66 | return headers; 67 | } 68 | 69 | HttpServer::HttpParseResult HttpServer::parse_request(const std::string& request, std::string& method, std::string& uri, std::unordered_map& headers) { 70 | size_t method_end = request.find(' '); 71 | if (method_end == std::string::npos) return HttpParseResult::MALFORMED; 72 | method = request.substr(0, method_end); 73 | if (method != "GET" && method != "POST" && method != "PUT" && method != "DELETE") return HttpParseResult::METHOD_UNSUPPORTED; 74 | size_t uri_end = request.find(' ', method_end + 1); 75 | if (uri_end == std::string::npos) return HttpParseResult::MALFORMED; 76 | uri = request.substr(method_end + 1, uri_end - method_end - 1); 77 | if (uri.empty()) return HttpParseResult::MALFORMED; 78 | std::string_view version = std::string_view(request).substr(uri_end + 1, 8); 79 | if (version != "HTTP/1.1") return HttpParseResult::PROTO_UNSUPPORTED; 80 | size_t header_end = request.find("\r\n\r\n"); 81 | if (header_end == std::string::npos) return HttpParseResult::MALFORMED; 82 | headers = parse_headers(request); 83 | if (headers.find("Content-Length") != headers.end()) { 84 | try { 85 | int content_length = std::stoi(headers["Content-Length"]); 86 | if (content_length < 0) return HttpParseResult::MALFORMED; 87 | } 88 | catch (...) { 89 | return HttpParseResult::MALFORMED; 90 | } 91 | } 92 | return HttpParseResult::OK; 93 | } 94 | 95 | bool HttpServer::check_and_adjust_time(const std::chrono::time_point& start_time, SOCKET client_socket) { 96 | auto elapsed_time = std::chrono::steady_clock::now() - start_time; 97 | long long elapsed_time_ms = std::chrono::duration_cast(elapsed_time).count(); 98 | int remaining_time = static_cast(timeout - elapsed_time_ms); 99 | int socket_time = remaining_time < 1 ? 1 : remaining_time; 100 | setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&socket_time, sizeof(socket_time)); 101 | setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&socket_time, sizeof(socket_time)); 102 | return remaining_time > 0; 103 | } 104 | 105 | void HttpServer::send_400_response(SOCKET client_socket) { 106 | HttpResponse response; 107 | response.status = "400 Bad Request"; 108 | response.body = "Malformed request."; 109 | response.send_response(client_socket); 110 | } 111 | 112 | void HttpServer::send_404_response(SOCKET client_socket) { 113 | HttpResponse response; 114 | response.status = "404 Not Found"; 115 | response.body = "Resource not found."; 116 | response.send_response(client_socket); 117 | } 118 | 119 | void HttpServer::send_405_response(SOCKET client_socket) { 120 | HttpResponse response; 121 | response.status = "405 Method Not Allowed"; 122 | response.body = "Method not allowed."; 123 | response.send_response(client_socket); 124 | } 125 | 126 | void HttpServer::send_413_response(SOCKET client_socket) { 127 | HttpResponse response; 128 | response.status = "413 Payload Too Large"; 129 | response.body = "Request body is too large."; 130 | response.send_response(client_socket); 131 | } 132 | 133 | void HttpServer::send_503_response(SOCKET client_socket) { 134 | HttpResponse response; 135 | response.status = "503 Service Unavailable"; 136 | response.body = "Server is busy."; 137 | response.send_response(client_socket); 138 | } 139 | 140 | void HttpServer::send_505_response(SOCKET client_socket) { 141 | HttpResponse response; 142 | response.status = "505 HTTP Version Not Supported"; 143 | response.body = "This server only supports HTTP/1.1."; 144 | response.send_response(client_socket); 145 | } 146 | 147 | void HttpServer::client_handler(SOCKET client_socket) { 148 | char buffer[4096]; 149 | std::string request; 150 | std::string method; 151 | std::string uri; 152 | std::unordered_map headers; 153 | int content_length = 0; 154 | size_t remaining_bytes = 0; 155 | size_t bytes_received = 0; 156 | size_t bytes_to_read = 0; 157 | std::string body; 158 | auto start_time = std::chrono::steady_clock::now(); 159 | setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); 160 | setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout)); 161 | while (true) { 162 | bytes_received = recv(client_socket, buffer, sizeof(buffer), 0); 163 | if (bytes_received <= 0 || !check_and_adjust_time(start_time, client_socket)) { 164 | return; 165 | } 166 | if (request.size() + bytes_received > max_headers_size) { 167 | send_413_response(client_socket); 168 | return; 169 | } 170 | request.append(buffer, bytes_received); 171 | if (request.find("\r\n\r\n") != std::string::npos) { 172 | break; 173 | } 174 | 175 | } 176 | HttpParseResult parse_result = parse_request(request, method, uri, headers); 177 | switch (parse_result) { 178 | case HttpParseResult::MALFORMED: 179 | send_400_response(client_socket); 180 | return; 181 | case HttpParseResult::METHOD_UNSUPPORTED: 182 | send_405_response(client_socket); 183 | return; 184 | case HttpParseResult::PROTO_UNSUPPORTED: 185 | send_505_response(client_socket); 186 | return; 187 | default: 188 | break; 189 | } 190 | if (headers.find("Content-Length") != headers.end()) { 191 | content_length = std::stoi(headers["Content-Length"]); 192 | if (content_length > max_body_size) { 193 | send_413_response(client_socket); 194 | return; 195 | } 196 | size_t request_body_start = request.find("\r\n\r\n") + 4; 197 | bytes_to_read = request.size() - request_body_start; 198 | if (bytes_to_read > content_length) bytes_to_read = content_length; 199 | body.append(request, request_body_start, bytes_to_read); 200 | remaining_bytes = content_length - body.size(); 201 | while (remaining_bytes > 0) { 202 | bytes_to_read = remaining_bytes; 203 | if (bytes_to_read > sizeof(buffer)) bytes_to_read = sizeof(buffer); 204 | bytes_received = recv(client_socket, buffer, static_cast(bytes_to_read), 0); 205 | if (bytes_received <= 0 || !check_and_adjust_time(start_time, client_socket)) { 206 | return; 207 | } 208 | if (body.size() + bytes_received > max_body_size) { 209 | send_413_response(client_socket); 210 | return; 211 | } 212 | body.append(buffer, bytes_received); 213 | remaining_bytes -= bytes_received; 214 | } 215 | } 216 | if (request_handler) { 217 | HttpResponse response; 218 | (*request_handler)(method, uri, headers, body, response); 219 | response.send_response(client_socket); 220 | } else { 221 | send_404_response(client_socket); 222 | } 223 | } 224 | 225 | void HttpServer::client_thread(SOCKET client_socket) { 226 | client_handler(client_socket); 227 | closesocket(client_socket); 228 | { 229 | std::lock_guard lock(connection_mutex); 230 | active_connections--; 231 | connection_cv.notify_one(); 232 | } 233 | } 234 | 235 | void HttpServer::listener_thread() { 236 | while (server_running) { 237 | sockaddr_in client_addr{}; 238 | int client_addr_size = sizeof(client_addr); 239 | SOCKET client_socket = accept(server_socket, (sockaddr*)&client_addr, &client_addr_size); 240 | if (client_socket == INVALID_SOCKET) { 241 | continue; 242 | } 243 | { 244 | std::lock_guard lock(connection_mutex); 245 | if (active_connections >= max_connections) { 246 | send_503_response(client_socket); 247 | closesocket(client_socket); 248 | continue; 249 | } 250 | active_connections++; 251 | } 252 | std::thread client_thread(&HttpServer::client_thread, this, client_socket); 253 | client_thread.detach(); 254 | } 255 | } 256 | 257 | HttpServer::HttpServer(const std::string& address, uint16_t port) : server_socket{}, address(address), port(port) {} 258 | 259 | HttpServer::~HttpServer() { 260 | if (server_running) { 261 | stop(); 262 | } 263 | } 264 | 265 | void HttpServer::start() { 266 | if (server_running) return; 267 | if (!wsa_init()) return; 268 | server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 269 | if (server_socket == INVALID_SOCKET) { 270 | wsa_cleanup(); 271 | return; 272 | } 273 | sockaddr_in server_addr{}; 274 | server_addr.sin_family = AF_INET; 275 | if (inet_pton(AF_INET, address.c_str(), &server_addr.sin_addr) != 1) { 276 | closesocket(server_socket); 277 | wsa_cleanup(); 278 | return; 279 | } 280 | server_addr.sin_port = htons(port); 281 | if (bind(server_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) { 282 | closesocket(server_socket); 283 | wsa_cleanup(); 284 | return; 285 | } 286 | if (listen(server_socket, SOMAXCONN) == SOCKET_ERROR) { 287 | closesocket(server_socket); 288 | wsa_cleanup(); 289 | return; 290 | } 291 | server_running = true; 292 | listener = std::thread(&HttpServer::listener_thread, this); 293 | } 294 | 295 | void HttpServer::stop() { 296 | if (!server_running) return; 297 | server_running = false; 298 | closesocket(server_socket); 299 | if (listener.joinable()) { 300 | listener.join(); 301 | } 302 | std::unique_lock lock(connection_mutex); 303 | connection_cv.wait(lock, [this] { return active_connections == 0; }); 304 | wsa_cleanup(); 305 | } 306 | 307 | void HttpServer::set_request_handler(HttpReuestHandler handler) { 308 | request_handler = handler; 309 | } 310 | 311 | void HttpServer::remove_request_handler() { 312 | request_handler.reset(); 313 | } 314 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/external/detours/src/uimports.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Add DLLs to a module import table (uimports.cpp of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | // Note that this file is included into creatwth.cpp one or more times 10 | // (once for each supported module format). 11 | // 12 | 13 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH 14 | #error detours.h version mismatch 15 | #endif 16 | 17 | // UpdateImports32 aka UpdateImports64 18 | static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, 19 | HMODULE hModule, 20 | __in_ecount(nDlls) LPCSTR *plpDlls, 21 | DWORD nDlls) 22 | { 23 | BOOL fSucceeded = FALSE; 24 | DWORD cbNew = 0; 25 | 26 | BYTE * pbNew = NULL; 27 | DWORD i; 28 | SIZE_T cbRead; 29 | DWORD n; 30 | 31 | PBYTE pbModule = (PBYTE)hModule; 32 | 33 | IMAGE_DOS_HEADER idh; 34 | ZeroMemory(&idh, sizeof(idh)); 35 | if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead) 36 | || cbRead < sizeof(idh)) { 37 | 38 | DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", 39 | pbModule, pbModule + sizeof(idh), GetLastError())); 40 | 41 | finish: 42 | if (pbNew != NULL) { 43 | delete[] pbNew; 44 | pbNew = NULL; 45 | } 46 | return fSucceeded; 47 | } 48 | 49 | IMAGE_NT_HEADERS_XX inh; 50 | ZeroMemory(&inh, sizeof(inh)); 51 | 52 | if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead) 53 | || cbRead < sizeof(inh)) { 54 | DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", 55 | pbModule + idh.e_lfanew, 56 | pbModule + idh.e_lfanew + sizeof(inh), 57 | GetLastError())); 58 | goto finish; 59 | } 60 | 61 | if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) { 62 | DETOUR_TRACE(("Wrong size image (%04x != %04x).\n", 63 | inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX)); 64 | SetLastError(ERROR_INVALID_BLOCK); 65 | goto finish; 66 | } 67 | 68 | // Zero out the bound table so loader doesn't use it instead of our new table. 69 | inh.BOUND_DIRECTORY.VirtualAddress = 0; 70 | inh.BOUND_DIRECTORY.Size = 0; 71 | 72 | // Find the size of the mapped file. 73 | DWORD dwSec = idh.e_lfanew + 74 | FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) + 75 | inh.FileHeader.SizeOfOptionalHeader; 76 | 77 | for (i = 0; i < inh.FileHeader.NumberOfSections; i++) { 78 | IMAGE_SECTION_HEADER ish; 79 | ZeroMemory(&ish, sizeof(ish)); 80 | 81 | if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish, 82 | sizeof(ish), &cbRead) 83 | || cbRead < sizeof(ish)) { 84 | 85 | DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n", 86 | pbModule + dwSec + sizeof(ish) * i, 87 | pbModule + dwSec + sizeof(ish) * (i + 1), 88 | GetLastError())); 89 | goto finish; 90 | } 91 | 92 | DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData)); 93 | 94 | // If the linker didn't suggest an IAT in the data directories, the 95 | // loader will look for the section of the import directory to be used 96 | // for this instead. Since we put out new IMPORT_DIRECTORY outside any 97 | // section boundary, the loader will not find it. So we provide one 98 | // explicitly to avoid the search. 99 | // 100 | if (inh.IAT_DIRECTORY.VirtualAddress == 0 && 101 | inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress && 102 | inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) { 103 | 104 | inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress; 105 | inh.IAT_DIRECTORY.Size = ish.SizeOfRawData; 106 | } 107 | } 108 | 109 | if (inh.IMPORT_DIRECTORY.VirtualAddress != 0 && inh.IMPORT_DIRECTORY.Size == 0) { 110 | 111 | // Don't worry about changing the PE file, 112 | // because the load information of the original PE header has been saved and will be restored. 113 | // The change here is just for the following code to work normally 114 | 115 | PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + inh.IMPORT_DIRECTORY.VirtualAddress); 116 | 117 | do { 118 | IMAGE_IMPORT_DESCRIPTOR ImageImport; 119 | if (!ReadProcessMemory(hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) { 120 | DETOUR_TRACE(("ReadProcessMemory failed: %lu\n", GetLastError())); 121 | goto finish; 122 | } 123 | inh.IMPORT_DIRECTORY.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR); 124 | if (!ImageImport.Name) { 125 | break; 126 | } 127 | ++pImageImport; 128 | } while (TRUE); 129 | 130 | DWORD dwLastError = GetLastError(); 131 | OutputDebugString(TEXT("[This PE file has an import table, but the import table size is marked as 0. This is an error.") 132 | TEXT("If it is not repaired, the launched program will not work properly, Detours has automatically repaired its import table size for you! ! !]\r\n")); 133 | if (GetLastError() != dwLastError) { 134 | SetLastError(dwLastError); 135 | } 136 | } 137 | 138 | DETOUR_TRACE((" Imports: %p..%p\n", 139 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 140 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress + 141 | inh.IMPORT_DIRECTORY.Size)); 142 | 143 | // Calculate new import directory size. Note that since inh is from another 144 | // process, inh could have been corrupted. We need to protect against 145 | // integer overflow in allocation calculations. 146 | DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); 147 | DWORD obRem; 148 | if (DWordMult(sizeof(IMAGE_IMPORT_DESCRIPTOR), nDlls, &obRem) != S_OK) { 149 | DETOUR_TRACE(("too many new DLLs.\n")); 150 | goto finish; 151 | } 152 | DWORD obOld; 153 | if (DWordAdd(obRem, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls, &obOld) != S_OK) { 154 | DETOUR_TRACE(("DLL entries overflow.\n")); 155 | goto finish; 156 | } 157 | DWORD obTab = PadToDwordPtr(obOld); 158 | // Check for integer overflow. 159 | if (obTab < obOld) { 160 | DETOUR_TRACE(("DLL entries padding overflow.\n")); 161 | goto finish; 162 | } 163 | DWORD stSize; 164 | if (DWordMult(sizeof(DWORD_XX) * 4, nDlls, &stSize) != S_OK) { 165 | DETOUR_TRACE(("String table overflow.\n")); 166 | goto finish; 167 | } 168 | DWORD obDll; 169 | if (DWordAdd(obTab, stSize, &obDll) != S_OK) { 170 | DETOUR_TRACE(("Import table size overflow\n")); 171 | goto finish; 172 | } 173 | DWORD obStr = obDll; 174 | cbNew = obStr; 175 | for (n = 0; n < nDlls; n++) { 176 | if (DWordAdd(cbNew, PadToDword((DWORD)strlen(plpDlls[n]) + 1), &cbNew) != S_OK) { 177 | DETOUR_TRACE(("Overflow adding string table entry\n")); 178 | goto finish; 179 | } 180 | } 181 | pbNew = new BYTE [cbNew]; 182 | if (pbNew == NULL) { 183 | DETOUR_TRACE(("new BYTE [cbNew] failed.\n")); 184 | goto finish; 185 | } 186 | ZeroMemory(pbNew, cbNew); 187 | 188 | PBYTE pbBase = pbModule; 189 | PBYTE pbNext = pbBase 190 | + inh.OptionalHeader.BaseOfCode 191 | + inh.OptionalHeader.SizeOfCode 192 | + inh.OptionalHeader.SizeOfInitializedData 193 | + inh.OptionalHeader.SizeOfUninitializedData; 194 | if (pbBase < pbNext) { 195 | pbBase = pbNext; 196 | } 197 | DETOUR_TRACE(("pbBase = %p\n", pbBase)); 198 | 199 | PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbModule, pbBase, cbNew); 200 | if (pbNewIid == NULL) { 201 | DETOUR_TRACE(("FindAndAllocateNearBase failed.\n")); 202 | goto finish; 203 | } 204 | 205 | PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew; 206 | IMAGE_THUNK_DATAXX *pt = NULL; 207 | 208 | DWORD obBase = (DWORD)(pbNewIid - pbModule); 209 | DWORD dwProtect = 0; 210 | 211 | if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) { 212 | // Read the old import directory if it exists. 213 | DETOUR_TRACE(("IMPORT_DIRECTORY perms=%lx\n", dwProtect)); 214 | 215 | if (!ReadProcessMemory(hProcess, 216 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, 217 | &piid[nDlls], 218 | nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead) 219 | || cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) { 220 | 221 | DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError())); 222 | goto finish; 223 | } 224 | } 225 | 226 | for (n = 0; n < nDlls; n++) { 227 | HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]); 228 | if (FAILED(hrRet)) { 229 | DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet)); 230 | goto finish; 231 | } 232 | 233 | // After copying the string, we patch up the size "??" bits if any. 234 | hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr, 235 | cbNew - obStr, 236 | DETOURS_STRINGIFY(DETOURS_BITS_XX)); 237 | if (FAILED(hrRet)) { 238 | DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet)); 239 | goto finish; 240 | } 241 | 242 | DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n)); 243 | piid[n].OriginalFirstThunk = obBase + nOffset; 244 | 245 | // We need 2 thunks for the import table and 2 thunks for the IAT. 246 | // One for an ordinal import and one to mark the end of the list. 247 | pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset)); 248 | pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1; 249 | pt[1].u1.Ordinal = 0; 250 | 251 | nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * ((4 * n) + 2)); 252 | piid[n].FirstThunk = obBase + nOffset; 253 | pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset)); 254 | pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1; 255 | pt[1].u1.Ordinal = 0; 256 | piid[n].TimeDateStamp = 0; 257 | piid[n].ForwarderChain = 0; 258 | piid[n].Name = obBase + obStr; 259 | 260 | obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1); 261 | } 262 | _Analysis_assume_(obStr <= cbNew); 263 | 264 | #if 0 265 | for (i = 0; i < nDlls + nOldDlls; i++) { 266 | DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n", 267 | i, 268 | piid[i].OriginalFirstThunk, 269 | piid[i].TimeDateStamp, 270 | piid[i].ForwarderChain, 271 | piid[i].Name, 272 | piid[i].FirstThunk)); 273 | if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) { 274 | break; 275 | } 276 | } 277 | #endif 278 | 279 | if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) { 280 | DETOUR_TRACE(("WriteProcessMemory(iid) failed: %lu\n", GetLastError())); 281 | goto finish; 282 | } 283 | 284 | DETOUR_TRACE(("obBaseBef = %08lx..%08lx\n", 285 | inh.IMPORT_DIRECTORY.VirtualAddress, 286 | inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); 287 | DETOUR_TRACE(("obBaseAft = %08lx..%08lx\n", obBase, obBase + obStr)); 288 | 289 | // In this case the file didn't have an import directory in first place, 290 | // so we couldn't fix the missing IAT above. We still need to explicitly 291 | // provide an IAT to prevent to loader from looking for one. 292 | // 293 | if (inh.IAT_DIRECTORY.VirtualAddress == 0) { 294 | inh.IAT_DIRECTORY.VirtualAddress = obBase; 295 | inh.IAT_DIRECTORY.Size = cbNew; 296 | } 297 | 298 | inh.IMPORT_DIRECTORY.VirtualAddress = obBase; 299 | inh.IMPORT_DIRECTORY.Size = cbNew; 300 | 301 | /////////////////////// Update the NT header for the new import directory. 302 | // 303 | if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, 304 | PAGE_EXECUTE_READWRITE, &dwProtect)) { 305 | DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError())); 306 | goto finish; 307 | } 308 | 309 | inh.OptionalHeader.CheckSum = 0; 310 | 311 | if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { 312 | DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError())); 313 | goto finish; 314 | } 315 | DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh))); 316 | 317 | if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { 318 | DETOUR_TRACE(("WriteProcessMemory(inh) failed: %lu\n", GetLastError())); 319 | goto finish; 320 | } 321 | DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n", 322 | pbModule + idh.e_lfanew, 323 | pbModule + idh.e_lfanew + sizeof(inh))); 324 | 325 | if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, 326 | dwProtect, &dwProtect)) { 327 | DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError())); 328 | goto finish; 329 | } 330 | 331 | fSucceeded = TRUE; 332 | goto finish; 333 | } 334 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/PsPcSdkEmulator.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Document 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 17.0 94 | Win32Proj 95 | {8a87caf8-e44b-4759-89d6-bf45c9f1ed95} 96 | PsPcSdkEmulator 97 | 10.0 98 | 99 | 100 | 101 | DynamicLibrary 102 | true 103 | v143 104 | Unicode 105 | 106 | 107 | DynamicLibrary 108 | false 109 | v143 110 | true 111 | Unicode 112 | 113 | 114 | DynamicLibrary 115 | true 116 | v143 117 | Unicode 118 | 119 | 120 | DynamicLibrary 121 | false 122 | v143 123 | true 124 | Unicode 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | Level3 148 | true 149 | WIN32;_DEBUG;PSPCSDKEMULATOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 150 | true 151 | NotUsing 152 | pch.h 153 | stdcpp17 154 | $(ProjectDir)external\detours\include;$(ProjectDir)src;%(AdditionalIncludeDirectories) 155 | MultiThreadedDebug 156 | 157 | 158 | Windows 159 | true 160 | false 161 | $(ProjectDir)src\loader\proxy.def 162 | shlwapi.lib;Ws2_32.lib;%(AdditionalDependencies) 163 | 164 | 165 | signtool sign /f "$(ProjectDir)src\loader\cert.pfx" /p "PsPcSdk Emulator" /fd certHash /t http://timestamp.digicert.com /v "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" 166 | 167 | 168 | 169 | 170 | 171 | Level3 172 | true 173 | true 174 | true 175 | WIN32;NDEBUG;PSPCSDKEMULATOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 176 | true 177 | NotUsing 178 | pch.h 179 | stdcpp17 180 | $(ProjectDir)external\detours\include;$(ProjectDir)src;%(AdditionalIncludeDirectories) 181 | MultiThreaded 182 | Speed 183 | 184 | 185 | Windows 186 | true 187 | true 188 | false 189 | false 190 | $(ProjectDir)src\loader\proxy.def 191 | shlwapi.lib;Ws2_32.lib;%(AdditionalDependencies) 192 | UseLinkTimeCodeGeneration 193 | 194 | 195 | signtool sign /f "$(ProjectDir)src\loader\cert.pfx" /p "PsPcSdk Emulator" /fd certHash /t http://timestamp.digicert.com /v "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" 196 | 197 | 198 | 199 | 200 | 201 | Level3 202 | true 203 | _DEBUG;PSPCSDKEMULATOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 204 | true 205 | NotUsing 206 | pch.h 207 | stdcpp17 208 | $(ProjectDir)external\detours\include;$(ProjectDir)src;%(AdditionalIncludeDirectories) 209 | MultiThreadedDebug 210 | 211 | 212 | Windows 213 | true 214 | false 215 | $(ProjectDir)src\loader\proxy.def 216 | shlwapi.lib;Ws2_32.lib;%(AdditionalDependencies) 217 | 218 | 219 | signtool sign /f "$(ProjectDir)src\loader\cert.pfx" /p "PsPcSdk Emulator" /fd certHash /t http://timestamp.digicert.com /v "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" 220 | 221 | 222 | 223 | 224 | 225 | Level3 226 | true 227 | true 228 | true 229 | NDEBUG;PSPCSDKEMULATOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 230 | true 231 | NotUsing 232 | pch.h 233 | stdcpp17 234 | $(ProjectDir)external\detours\include;$(ProjectDir)src;%(AdditionalIncludeDirectories) 235 | MultiThreaded 236 | Speed 237 | 238 | 239 | Windows 240 | true 241 | true 242 | false 243 | false 244 | $(ProjectDir)src\loader\proxy.def 245 | shlwapi.lib;Ws2_32.lib;%(AdditionalDependencies) 246 | UseLinkTimeCodeGeneration 247 | 248 | 249 | signtool sign /f "$(ProjectDir)src\loader\cert.pfx" /p "PsPcSdk Emulator" /fd certHash /t http://timestamp.digicert.com /v "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll" 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/webapi2.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "webapi2.h" 9 | 10 | #include "../sce.h" 11 | #include 12 | 13 | static SceNpNpWebApi2ContextNode g_contexts; 14 | static int g_context_count = 0; 15 | 16 | static SceNpNpWebApi2ContextNode* find_context(int16_t context) { 17 | SceNpNpWebApi2ContextNode* node = &g_contexts; 18 | while (node->next != nullptr) { 19 | if (node->context == context) { 20 | return node; 21 | } 22 | node = node->next; 23 | } 24 | return nullptr; 25 | } 26 | 27 | PSPCSDK_API SceResult sceNpWebApi2Initialize(int16_t context) { 28 | if (g_context_count >= SCE_NP_WEB_API2_MAX_CONTEXTS) { 29 | return SCE_ERROR_NP_WEB_API2_FULL_CONTEXT_POOL; 30 | } 31 | SceNpNpWebApi2ContextNode* last_node = &g_contexts; 32 | while (last_node->next != nullptr) { 33 | last_node = last_node->next; 34 | } 35 | last_node->next = new SceNpNpWebApi2ContextNode(); 36 | last_node->context = context; 37 | g_context_count++; 38 | printf("(STUBBED) sceNpWebApi2Initialize(%hd)\n", context); 39 | return SCE_OK; 40 | } 41 | 42 | PSPCSDK_API SceResult sceNpWebApi2Terminate(int16_t context) { 43 | SceNpNpWebApi2ContextNode* node = find_context(context); 44 | if (node == nullptr) { 45 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 46 | } 47 | SceNpNpWebApi2ContextNode* next = node->next; 48 | node->next = next->next; 49 | node->context = next->context; 50 | delete next; 51 | g_context_count--; 52 | printf("(STUBBED) sceNpWebApi2Terminate(%hd)\n", context); 53 | return SCE_OK; 54 | } 55 | 56 | PSPCSDK_API SceResult sceNpWebApi2CreateUserContext(int16_t context, int user) { 57 | if (context == -1) { 58 | return SCE_ERROR_NP_WEB_API2_INVALID_CONTEXT; 59 | } 60 | if (user == -1) { 61 | return SCE_ERROR_NP_WEB_API2_INVALID_USER; 62 | } 63 | SceNpNpWebApi2ContextNode* node = find_context(context); 64 | if (node == nullptr) { 65 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 66 | } 67 | printf("(STUBBED) sceNpWebApi2CreateUserContext(%hd, %d)\n", context, user); 68 | return SCE_OK; 69 | } 70 | 71 | PSPCSDK_API SceResult sceNpWebApi2DeleteUserContext(int context_and_user) { 72 | int context = context_and_user >> 16; 73 | SceNpNpWebApi2ContextNode* node = find_context(context); 74 | if (node == nullptr) { 75 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 76 | } 77 | printf("(STUBBED) sceNpWebApi2DeleteUserContext(%d)\n", context_and_user); 78 | return SCE_OK; 79 | } 80 | 81 | PSPCSDK_API SceResult sceNpWebApi2CreateRequest(int data, void* unknown2, void* unknown3, void* unknown4, void* unknown5, void* unknown6) { 82 | if (!unknown2 || !unknown3 || !unknown4) { 83 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 84 | } 85 | int context = data >> 16; 86 | SceNpNpWebApi2ContextNode* node = find_context(context); 87 | if (node == nullptr) { 88 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 89 | } 90 | printf("(STUBBED) sceNpWebApi2CreateRequest(%d, %p, %p, %p, %p, %p)\n", data, unknown2, unknown3, unknown4, unknown5, unknown6); 91 | return SCE_OK; 92 | } 93 | 94 | PSPCSDK_API SceResult sceNpWebApi2DeleteRequest(uint64_t data) { 95 | int context = data >> 48; 96 | SceNpNpWebApi2ContextNode* node = find_context(context); 97 | if (node == nullptr) { 98 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 99 | } 100 | printf("(STUBBED) sceNpWebApi2DeleteRequest(%llx)\n", data); 101 | return SCE_OK; 102 | } 103 | 104 | PSPCSDK_API SceResult sceNpWebApi2DeleteContext(uint64_t data) { 105 | int context = data >> 48; 106 | SceNpNpWebApi2ContextNode* node = find_context(context); 107 | if (node == nullptr) { 108 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 109 | } 110 | printf("(STUBBED) sceNpWebApi2DeleteContext(%llx)\n", data); 111 | return SCE_OK; 112 | } 113 | 114 | PSPCSDK_API SceResult sceNpWebApi2AbortRequest(uint64_t data) { 115 | int context = data >> 48; 116 | SceNpNpWebApi2ContextNode* node = find_context(context); 117 | if (node == nullptr) { 118 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 119 | } 120 | printf("(STUBBED) sceNpWebApi2AbortRequest(%llx)\n", data); 121 | return SCE_OK; 122 | } 123 | 124 | PSPCSDK_API SceResult sceNpWebApi2CheckTimeout() { 125 | printf("(STUBBED) sceNpWebApi2CheckTimeout()\n"); 126 | return SCE_OK; 127 | } 128 | 129 | PSPCSDK_API SceResult sceNpWebApi2AddHttpRequestHeader(uint64_t data, const char* key, const char* value) { 130 | if (!key || !value) { 131 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 132 | } 133 | int context = data >> 48; 134 | SceNpNpWebApi2ContextNode* node = find_context(context); 135 | if (node == nullptr) { 136 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 137 | } 138 | printf("(STUBBED) sceNpWebApi2AddHttpRequestHeader(%llx, %s, %s)\n", data, key, value); 139 | return SCE_OK; 140 | } 141 | 142 | PSPCSDK_API SceResult sceNpWebApi2GetHttpResponseHeaderValue(uint64_t data, const char* key, char* value, uint64_t* value_size) { 143 | if (!key || !value || !value_size) { 144 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 145 | } 146 | int context = data >> 48; 147 | SceNpNpWebApi2ContextNode* node = find_context(context); 148 | if (node == nullptr) { 149 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 150 | } 151 | printf("(STUBBED) sceNpWebApi2GetHttpResponseHeaderValue(%llx, %s, %p, %p)\n", data, key, value, value_size); 152 | return SCE_OK; 153 | } 154 | 155 | PSPCSDK_API SceResult sceNpWebApi2GetHttpResponseHeaderValueLength(uint64_t data, char* key, uint64_t* length) { 156 | if (!key || !length) { 157 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 158 | } 159 | int context = data >> 48; 160 | SceNpNpWebApi2ContextNode* node = find_context(context); 161 | if (node == nullptr) { 162 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 163 | } 164 | printf("(STUBBED) sceNpWebApi2GetHttpResponseHeaderValueLength(%llx, %s, %p)\n", data, key, length); 165 | return SCE_OK; 166 | } 167 | 168 | PSPCSDK_API SceResult sceNpWebApi2SetRequestTimeout(uint64_t data, uint64_t timeout) { 169 | int context = data >> 48; 170 | SceNpNpWebApi2ContextNode* node = find_context(context); 171 | if (node == nullptr) { 172 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 173 | } 174 | printf("(STUBBED) sceNpWebApi2SetRequestTimeout(%llx, %llx)\n", data, timeout); 175 | return SCE_OK; 176 | } 177 | 178 | PSPCSDK_API SceResult sceNpWebApi2ReadData(uint64_t data, void* buffer, uint64_t* size) { 179 | if (!buffer || !size) { 180 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 181 | } 182 | int context = data >> 48; 183 | SceNpNpWebApi2ContextNode* node = find_context(context); 184 | if (node == nullptr) { 185 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 186 | } 187 | printf("(STUBBED) sceNpWebApi2ReadData(%llx, %p, %p)\n", data, buffer, size); 188 | return SCE_OK; 189 | } 190 | 191 | PSPCSDK_API SceResult sceNpWebApi2SendRequest(uint64_t data, void* unused, void* unknown3, void* unknown4, void* unknown5) { 192 | int context = data >> 48; 193 | SceNpNpWebApi2ContextNode* node = find_context(context); 194 | if (node == nullptr) { 195 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 196 | } 197 | printf("(STUBBED) sceNpWebApi2SendRequest(%llx, %p, %p, %p, %p)\n", data, unused, unknown3, unknown4, unknown5); 198 | return SCE_OK; 199 | } 200 | 201 | PSPCSDK_API SceResult sceNpWebApi2GetMemoryPoolStats(uint16_t context, void* out) { 202 | SceNpNpWebApi2ContextNode* node = find_context(context); 203 | if (node == nullptr) { 204 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 205 | } 206 | printf("(STUBBED) sceNpWebApi2GetMemoryPoolStats(%d, %p)\n", context, out); 207 | return SCE_OK; 208 | } 209 | 210 | PSPCSDK_API SceResult sceNpWebApi2GetPlatformError(uint64_t data, HRESULT* error, uint64_t four) { 211 | if (!error || four != 4) { 212 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 213 | } 214 | int context = 0; 215 | if ((data & 0xffffffffffff0000) == 0) { 216 | context = (int) (data >> 16); 217 | } else if ((data & 0xffffffff00000000) == 0 && (data & 0xffff0000) != 0) { 218 | context = (int) (data >> 32); 219 | } else { 220 | context = (int) (data >> 48); 221 | } 222 | SceNpNpWebApi2ContextNode* node = find_context(context); 223 | if (node == nullptr) { 224 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 225 | } 226 | printf("(STUBBED) sceNpWebApi2GetPlatformError(%llx, %p, %llx)\n", data, error, four); 227 | *error = 0; 228 | return SCE_OK; 229 | } 230 | 231 | PSPCSDK_API SceResult sceNpWebApi2PushEventCreatePushContext(int data, void* push_context) { 232 | if (!push_context) { 233 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 234 | } 235 | int context = data >> 16; 236 | SceNpNpWebApi2ContextNode* node = find_context(context); 237 | if (node == nullptr) { 238 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 239 | } 240 | printf("(STUBBED) sceNpWebApi2PushEventCreatePushContext(%d, %p)\n", data, push_context); 241 | return SCE_OK; 242 | } 243 | 244 | PSPCSDK_API SceResult sceNpWebApi2PushEventDeletePushContext(int data, void* push_context) { 245 | if (!push_context) { 246 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 247 | } 248 | int context = data >> 16; 249 | SceNpNpWebApi2ContextNode* node = find_context(context); 250 | if (node == nullptr) { 251 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 252 | } 253 | printf("(STUBBED) sceNpWebApi2PushEventDeletePushContext(%d, %p)\n", data, push_context); 254 | return SCE_OK; 255 | } 256 | 257 | PSPCSDK_API SceResult sceNpWebApi2PushEventCreateHandle(uint16_t context) { 258 | SceNpNpWebApi2ContextNode* node = find_context(context); 259 | if (node == nullptr) { 260 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 261 | } 262 | printf("(STUBBED) sceNpWebApi2PushEventCreateHandle(%d)\n", context); 263 | return SCE_OK; 264 | } 265 | 266 | PSPCSDK_API SceResult sceNpWebApi2PushEventDeleteHandle(uint16_t context, int handle) { 267 | SceNpNpWebApi2ContextNode* node = find_context(context); 268 | if (node == nullptr) { 269 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 270 | } 271 | printf("(STUBBED) sceNpWebApi2PushEventDeleteHandle(%d, %d)\n", context, handle); 272 | return SCE_OK; 273 | } 274 | 275 | PSPCSDK_API SceResult sceNpWebApi2PushEventAbortHandle(uint16_t context, int handle) { 276 | SceNpNpWebApi2ContextNode* node = find_context(context); 277 | if (node == nullptr) { 278 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 279 | } 280 | printf("(STUBBED) sceNpWebApi2PushEventAbortHandle(%d, %d)\n", context, handle); 281 | return SCE_OK; 282 | } 283 | 284 | PSPCSDK_API SceResult sceNpWebApi2PushEventSetHandleTimeout(uint16_t context, int handle, uint64_t timeout) { 285 | SceNpNpWebApi2ContextNode* node = find_context(context); 286 | if (node == nullptr) { 287 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 288 | } 289 | printf("(STUBBED) sceNpWebApi2PushEventSetHandleTimeout(%d, %d, %llx)\n", context, handle, timeout); 290 | return SCE_OK; 291 | } 292 | 293 | PSPCSDK_API SceResult sceNpWebApi2PushEventCreateFilter(uint16_t context, void* unknown2, uint64_t unknown3, int64_t unknown4, void* unknown5, void* unknown6) { 294 | if ((unknown3 && unknown4 != -1) || !unknown5 || !unknown6) { 295 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 296 | } 297 | SceNpNpWebApi2ContextNode* node = find_context(context); 298 | if (node == nullptr) { 299 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 300 | } 301 | printf("(STUBBED) sceNpWebApi2PushEventCreateFilter(%d, %p, %llx, %llx, %p, %p)\n", context, unknown2, unknown3, unknown4, unknown5, unknown6); 302 | return SCE_OK; 303 | } 304 | 305 | PSPCSDK_API SceResult sceNpWebApi2PushEventDeleteFilter(uint16_t context, int filter) { 306 | SceNpNpWebApi2ContextNode* node = find_context(context); 307 | if (node == nullptr) { 308 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 309 | } 310 | printf("(STUBBED) sceNpWebApi2PushEventDeleteFilter(%d, %d)\n", context, filter); 311 | return SCE_OK; 312 | } 313 | 314 | PSPCSDK_API SceResult sceNpWebApi2PushEventGetPlatformError(uint16_t context, int handle, HRESULT* error, uint64_t four) { 315 | if (!error || four != 4) { 316 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 317 | } 318 | SceNpNpWebApi2ContextNode* node = find_context(context); 319 | if (node == nullptr) { 320 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 321 | } 322 | printf("(STUBBED) sceNpWebApi2PushEventGetPlatformError(%d, %d, %p, %llx)\n", context, handle, error, four); 323 | *error = 0; 324 | return SCE_OK; 325 | } 326 | 327 | PSPCSDK_API SceResult sceNpWebApi2PushEventRegisterCallback(int data, int handle, void* callback, void* userdata) { 328 | if (!callback) { 329 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 330 | } 331 | int context = data >> 16; 332 | SceNpNpWebApi2ContextNode* node = find_context(context); 333 | if (node == nullptr) { 334 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 335 | } 336 | printf("(STUBBED) sceNpWebApi2PushEventRegisterCallback(%d, %d, %p, %p)\n", data, handle, callback, userdata); 337 | return SCE_OK; 338 | } 339 | 340 | PSPCSDK_API SceResult sceNpWebApi2PushEventUnregisterCallback(int data, int handle) { 341 | int context = data >> 16; 342 | SceNpNpWebApi2ContextNode* node = find_context(context); 343 | if (node == nullptr) { 344 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 345 | } 346 | printf("(STUBBED) sceNpWebApi2PushEventUnregisterCallback(%d, %d)\n", data, handle); 347 | return SCE_OK; 348 | } 349 | 350 | PSPCSDK_API SceResult sceNpWebApi2PushEventRegisterPushContextCallback(int data, int push_context, void* callback, void* userdata) { 351 | if (!callback) { 352 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 353 | } 354 | int context = data >> 16; 355 | SceNpNpWebApi2ContextNode* node = find_context(context); 356 | if (node == nullptr) { 357 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 358 | } 359 | printf("(STUBBED) sceNpWebApi2PushEventRegisterPushContextCallback(%d, %d, %p, %p)\n", data, push_context, callback, userdata); 360 | return SCE_OK; 361 | } 362 | 363 | PSPCSDK_API SceResult sceNpWebApi2PushEventUnregisterPushContextCallback(int data, int push_context) { 364 | int context = data >> 16; 365 | SceNpNpWebApi2ContextNode* node = find_context(context); 366 | if (node == nullptr) { 367 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 368 | } 369 | printf("(STUBBED) sceNpWebApi2PushEventUnregisterPushContextCallback(%d, %d)\n", data, push_context); 370 | return SCE_OK; 371 | } 372 | 373 | PSPCSDK_API SceResult sceNpWebApi2PushEventStartPushContextCallback(int data, void* unknown2) { 374 | if (!unknown2) { 375 | return SCE_ERROR_NP_WEB_API2_INVALID_PARAM; 376 | } 377 | int context = data >> 16; 378 | SceNpNpWebApi2ContextNode* node = find_context(context); 379 | if (node == nullptr) { 380 | return SCE_ERROR_NP_WEB_API2_CONTEXT_NOT_INITIALIZED; 381 | } 382 | printf("(STUBBED) sceNpWebApi2PushEventStartPushContextCallback(%d, %p)\n", data, unknown2); 383 | return SCE_OK; 384 | } 385 | 386 | void np_web_api2_reset() { 387 | SceNpNpWebApi2ContextNode* node = g_contexts.next; 388 | while (node != nullptr) { 389 | SceNpNpWebApi2ContextNode* next = node->next; 390 | delete node; 391 | node = next; 392 | } 393 | g_contexts.next = nullptr; 394 | g_context_count = 0; 395 | } 396 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /PsPcSdkEmulator/src/sdk/np/uds.cpp: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. 2 | * If a copy of the MPL was not distributed with this file, you can obtain one at 3 | * https://mozilla.org/MPL/2.0/. 4 | * 5 | * Copyright (c) 2025 Lander Gallastegi (LNDF) 6 | */ 7 | 8 | #include "uds.h" 9 | 10 | #include "../sce.h" 11 | #include 12 | #include 13 | 14 | bool g_udsInitialized = false; 15 | 16 | PSPCSDK_API SceResult sceNpUniversalDataSystemInitialize(SceNpUniversalDataSystemInitParams* params) { 17 | if (g_udsInitialized) { 18 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_ALREADY_INITIALIZED; 19 | } 20 | if (!params) { 21 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 22 | } 23 | if (params->size != 0x118) { 24 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM_UNK1; 25 | } 26 | if (!params->unknown2) { 27 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 28 | } 29 | size_t path_len = strnlen(params->path, 0x105); 30 | if (path_len <= 0 || path_len >= 0x105) { 31 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 32 | } 33 | printf("(STUBBED) sceUniversalDataSystemInitialize(%p)\n", params); 34 | g_udsInitialized = true; 35 | return SCE_OK; 36 | } 37 | 38 | PSPCSDK_API SceResult sceNpUniversalDataSystemTerminate() { 39 | if (!g_udsInitialized) { 40 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 41 | } 42 | g_udsInitialized = false; 43 | return SCE_OK; 44 | } 45 | 46 | PSPCSDK_API SceResult sceNpUniversalDataSystemCreateContext(int* unknown1, int unknown2, int unknown3, void* unused) { 47 | if (!unknown1 || unknown3 >= 100 || unused) { 48 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 49 | } 50 | printf("(STUBBED) sceUniversalDataSystemCreateContext(%p, %d, %d, %p)\n", unknown1, unknown2, unknown3, unused); 51 | *unknown1 = 0x12345678; 52 | return SCE_OK; 53 | } 54 | 55 | PSPCSDK_API SceResult sceNpUniversalDataSystemDestroyContext(int context) { 56 | if (context == -1) { 57 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_CONTEXT; 58 | } 59 | printf("(STUBBED) sceUniversalDataSystemDestroyContext(%d)\n", context); 60 | return SCE_OK; 61 | } 62 | 63 | PSPCSDK_API SceResult sceNpUniversalDataSystemCreateEvent(char* name, uint64_t unknown2, void* unknown3, void* unknown4) { 64 | if (!g_udsInitialized) { 65 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 66 | } 67 | if (!name) { 68 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_EVENT_NAME; 69 | } 70 | printf("(STUBBED) sceUniversalDataSystemCreateEvent(%s, %llx, %p, %p)\n", name, unknown2, unknown3, unknown4); 71 | return SCE_OK; 72 | } 73 | 74 | PSPCSDK_API SceResult sceNpUniversalDataSystemDestroyEvent(void* context) { 75 | if (!g_udsInitialized) { 76 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 77 | } 78 | printf("(STUBBED) sceUniversalDataSystemDestroyEvent(%p)\n", context); 79 | return SCE_OK; 80 | } 81 | 82 | PSPCSDK_API SceResult sceNpUniversalDataSystemCreateEventPropertyArray(void* param) { 83 | if (!g_udsInitialized) { 84 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 85 | } 86 | if (!param) { 87 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 88 | } 89 | printf("(STUBBED) sceUniversalDataSystemCreateEventPropertyArray(%p)\n", param); 90 | return SCE_OK; 91 | } 92 | 93 | PSPCSDK_API SceResult sceNpUniversalDataSystemDestroyEventPropertyArray(void* param) { 94 | printf("(STUBBED) sceUniversalDataSystemDestroyEventPropertyArray(%p)\n", param); 95 | return SCE_OK; 96 | } 97 | 98 | PSPCSDK_API SceResult sceNpUniversalDataSystemCreateEventPropertyObject(void* param) { 99 | if (!g_udsInitialized) { 100 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 101 | } 102 | if (!param) { 103 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 104 | } 105 | printf("(STUBBED) sceUniversalDataSystemCreateEventPropertyObject(%p)\n", param); 106 | return SCE_OK; 107 | } 108 | 109 | PSPCSDK_API SceResult sceNpUniversalDataSystemDestroyEventPropertyObject(void* param) { 110 | printf("(STUBBED) sceUniversalDataSystemDestroyEventPropertyObject(%p)\n", param); 111 | return SCE_OK; 112 | } 113 | 114 | PSPCSDK_API SceResult sceNpUniversalDataSystemCreateHandle(int* handle) { 115 | if (!handle) { 116 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 117 | } 118 | printf("(STUBBED) sceUniversalDataSystemCreateHandle(%p)\n", handle); 119 | return SCE_OK; 120 | } 121 | 122 | PSPCSDK_API SceResult sceNpUniversalDataSystemDestroyHandle(int param) { 123 | if (param == -1) { 124 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_HANDLE; 125 | } 126 | printf("(STUBBED) sceUniversalDataSystemDestroyHandle(%d)\n", param); 127 | return SCE_OK; 128 | } 129 | 130 | PSPCSDK_API SceResult sceNpUniversalDataSystemAbortHandle(int param) { 131 | if (param == -1) { 132 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_HANDLE; 133 | } 134 | printf("(STUBBED) sceUniversalDataSystemAbortHandle(%d)\n", param); 135 | return SCE_OK; 136 | } 137 | 138 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventEstimateSize(int* param, int* size) { 139 | if (!g_udsInitialized) { 140 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 141 | } 142 | if (!param) { 143 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_EVENT; 144 | } 145 | if (!size) { 146 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 147 | } 148 | printf("(STUBBED) sceUniversalDataSystemEventEstimateSize(%p, %p)\n", param, size); 149 | *size = 0x100; 150 | return SCE_OK; 151 | } 152 | 153 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetArray(void* dest, void* src, uint64_t* copied) { 154 | if (!g_udsInitialized) { 155 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 156 | } 157 | if (!dest) { 158 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 159 | } 160 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetArray(%p, %p, %p)\n", dest, src, copied); 161 | return SCE_OK; 162 | } 163 | 164 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetBinary(void* dest, void* data, uint64_t size) { 165 | if (!g_udsInitialized) { 166 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 167 | } 168 | if (!dest) { 169 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 170 | } 171 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetBinary(%p, %p, %llx)\n", dest, data, size); 172 | return SCE_OK; 173 | } 174 | 175 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetFloat32(void* dest, float value) { 176 | if (!g_udsInitialized) { 177 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 178 | } 179 | if (!dest) { 180 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 181 | } 182 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetFloat32(%p, %f)\n", dest, value); 183 | return SCE_OK; 184 | } 185 | 186 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetFloat64(void* dest, double value) { 187 | if (!g_udsInitialized) { 188 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 189 | } 190 | if (!dest) { 191 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 192 | } 193 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetFloat64(%p, %f)\n", dest, value); 194 | return SCE_OK; 195 | } 196 | 197 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetInt32(void* dest, int32_t value) { 198 | if (!g_udsInitialized) { 199 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 200 | } 201 | if (!dest) { 202 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 203 | } 204 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetInt32(%p, %d)\n", dest, value); 205 | return SCE_OK; 206 | } 207 | 208 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetInt64(void* dest, int64_t value) { 209 | if (!g_udsInitialized) { 210 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 211 | } 212 | if (!dest) { 213 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 214 | } 215 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetInt64(%p, %lld)\n", dest, value); 216 | return SCE_OK; 217 | } 218 | 219 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetString(void* dest, const char* value) { 220 | if (!g_udsInitialized) { 221 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 222 | } 223 | if (!dest) { 224 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 225 | } 226 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetString(%p, %s)\n", dest, value); 227 | return SCE_OK; 228 | } 229 | 230 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetUInt32(void* dest, uint32_t value) { 231 | if (!g_udsInitialized) { 232 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 233 | } 234 | if (!dest) { 235 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 236 | } 237 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetUInt32(%p, %u)\n", dest, value); 238 | return SCE_OK; 239 | } 240 | 241 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetUInt64(void* dest, uint64_t value) { 242 | if (!g_udsInitialized) { 243 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 244 | } 245 | if (!dest) { 246 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 247 | } 248 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetUInt64(%p, %llu)\n", dest, value); 249 | return SCE_OK; 250 | } 251 | 252 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetBool(void* dest, bool value) { 253 | if (!g_udsInitialized) { 254 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 255 | } 256 | if (!dest) { 257 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_ARRAY_DST; 258 | } 259 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetBool(%p, %d)\n", dest, value); 260 | return SCE_OK; 261 | } 262 | 263 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyArraySetObject(void* dest, void* src, uint64_t* copied) { 264 | if (!g_udsInitialized) { 265 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 266 | } 267 | if (!dest) { 268 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 269 | } 270 | printf("(STUBBED) sceUniversalDataSystemEventPropertyArraySetObject(%p, %p, %p)\n", dest, src, copied); 271 | return SCE_OK; 272 | } 273 | 274 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetArray(void* dst, void* key, void* src, uint64_t* copied) { 275 | if (!g_udsInitialized) { 276 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 277 | } 278 | if (!dst) { 279 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 280 | } 281 | if (!key) { 282 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 283 | } 284 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetArray(%p, %p, %p, %p)\n", dst, key, src, copied); 285 | return SCE_OK; 286 | } 287 | 288 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetBinary(void* dst, void* key, void* data, uint64_t size) { 289 | if (!g_udsInitialized) { 290 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 291 | } 292 | if (!dst) { 293 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 294 | } 295 | if (!key) { 296 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 297 | } 298 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetBinary(%p, %p, %p, %llx)\n", dst, key, data, size); 299 | return SCE_OK; 300 | } 301 | 302 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetFloat32(void* dst, void* key, float value) { 303 | if (!g_udsInitialized) { 304 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 305 | } 306 | if (!dst) { 307 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 308 | } 309 | if (!key) { 310 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 311 | } 312 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetFloat32(%p, %p, %f)\n", dst, key, value); 313 | return SCE_OK; 314 | } 315 | 316 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetFloat64(void* dst, void* key, double value) { 317 | if (!g_udsInitialized) { 318 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 319 | } 320 | if (!dst) { 321 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 322 | } 323 | if (!key) { 324 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 325 | } 326 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetFloat64(%p, %p, %f)\n", dst, key, value); 327 | return SCE_OK; 328 | } 329 | 330 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetInt32(void* dst, void* key, int32_t value) { 331 | if (!g_udsInitialized) { 332 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 333 | } 334 | if (!dst) { 335 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 336 | } 337 | if (!key) { 338 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 339 | } 340 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetInt32(%p, %p, %d)\n", dst, key, value); 341 | return SCE_OK; 342 | } 343 | 344 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetInt64(void* dst, void* key, int64_t value) { 345 | if (!g_udsInitialized) { 346 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 347 | } 348 | if (!dst) { 349 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 350 | } 351 | if (!key) { 352 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 353 | } 354 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetInt64(%p, %p, %lld)\n", dst, key, value); 355 | return SCE_OK; 356 | } 357 | 358 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetString(void* dst, void* key, const char* value) { 359 | if (!g_udsInitialized) { 360 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 361 | } 362 | if (!dst) { 363 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 364 | } 365 | if (!key) { 366 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 367 | } 368 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetString(%p, %p, %s)\n", dst, key, value); 369 | return SCE_OK; 370 | } 371 | 372 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetUInt32(void* dst, void* key, uint32_t value) { 373 | if (!g_udsInitialized) { 374 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 375 | } 376 | if (!dst) { 377 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 378 | } 379 | if (!key) { 380 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 381 | } 382 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetUInt32(%p, %p, %u)\n", dst, key, value); 383 | return SCE_OK; 384 | } 385 | 386 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetUInt64(void* dst, void* key, uint64_t value) { 387 | if (!g_udsInitialized) { 388 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 389 | } 390 | if (!dst) { 391 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 392 | } 393 | if (!key) { 394 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 395 | } 396 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetUInt64(%p, %p, %llu)\n", dst, key, value); 397 | return SCE_OK; 398 | } 399 | 400 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetBool(void* dst, void* key, bool value) { 401 | if (!g_udsInitialized) { 402 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 403 | } 404 | if (!dst) { 405 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 406 | } 407 | if (!key) { 408 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 409 | } 410 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetBool(%p, %p, %d)\n", dst, key, value); 411 | return SCE_OK; 412 | } 413 | 414 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventPropertyObjectSetObject(void* dst, void* key, void* src, uint64_t* copied) { 415 | if (!g_udsInitialized) { 416 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 417 | } 418 | if (!dst) { 419 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_OBJECT_DST; 420 | } 421 | if (!key) { 422 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_KEY; 423 | } 424 | printf("(STUBBED) sceUniversalDataSystemEventPropertyObjectSetObject(%p, %p, %p, %p)\n", dst, key, src, copied); 425 | return SCE_OK; 426 | } 427 | 428 | PSPCSDK_API SceResult sceNpUniversalDataSystemEventToString(void* event, char* buffer, uint64_t size, uint64_t* written) { 429 | if (!g_udsInitialized) { 430 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 431 | } 432 | if (!event) { 433 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_EVENT; 434 | } 435 | if (!buffer && !written) { 436 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 437 | } 438 | printf("(STUBBED) sceUniversalDataSystemEventToString(%p, %p, %llx, %p)\n", event, buffer, size, written); 439 | return SCE_OK; 440 | } 441 | 442 | PSPCSDK_API SceResult sceNpUniversalDataSystemGetMemoryStat(void* out) { 443 | if (!g_udsInitialized) { 444 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 445 | } 446 | if (!out) { 447 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 448 | } 449 | printf("(STUBBED) sceUniversalDataSystemGetMemoryStat(%p)\n", out); 450 | return SCE_OK; 451 | } 452 | 453 | PSPCSDK_API SceResult sceNpUniversalDataSystemGetPlatformError(HRESULT* error, int64_t four) { 454 | if (!g_udsInitialized) { 455 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 456 | } 457 | if (!error || four != 4) { 458 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 459 | } 460 | printf("(STUBBED) sceUniversalDataSystemGetPlatformError(%p, %lld)\n", error, four); 461 | *error = 0; 462 | return SCE_OK; 463 | } 464 | 465 | PSPCSDK_API SceResult sceNpUniversalDataSystemGetStorageStat(int context, void* out) { 466 | if (!g_udsInitialized) { 467 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 468 | } 469 | if (context == -1) { 470 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_CONTEXT; 471 | } 472 | if (!out) { 473 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 474 | } 475 | printf("(STUBBED) sceUniversalDataSystemGetStorageStat(%d, %p)\n", context, out); 476 | return SCE_OK; 477 | } 478 | 479 | PSPCSDK_API SceResult sceNpUniversalDataSystemPostEvent(int context, int handle, void* event, int* unknown4) { 480 | if (!g_udsInitialized) { 481 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_NOT_INITIALIZED; 482 | } 483 | if (context == -1) { 484 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_CONTEXT; 485 | } 486 | if (handle == -1) { 487 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_HANDLE; 488 | } 489 | if (!event) { 490 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_EVENT; 491 | } 492 | printf("(STUBBED) sceUniversalDataSystemPostEvent(%d, %d, %p, %p)\n", context, handle, event, unknown4); 493 | *unknown4 = 0x12345678; 494 | return SCE_OK; 495 | } 496 | 497 | PSPCSDK_API SceResult sceNpUniversalDataSystemRegisterContext(int context, int handle, int zero) { 498 | if (context == -1) { 499 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_CONTEXT; 500 | } 501 | if (zero != 0) { 502 | return SCE_ERROR_NP_UNIVERSAL_DATA_SYSTEM_INVALID_PARAM; 503 | } 504 | printf("(STUBBED) sceUniversalDataSystemRegisterContext(%d, %d, %d)\n", context, handle, zero); 505 | return SCE_OK; 506 | } 507 | 508 | void np_uds_reset() { 509 | g_udsInitialized = false; 510 | } 511 | --------------------------------------------------------------------------------