diff --git a/CMakeLists.txt b/CMakeLists.txt
index 185205221..13204f479 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,28 +113,39 @@ git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
+message("start git things")
# Try to get the upstream remote and branch
+message("check for remote and branch")
execute_process(
COMMAND git rev-parse --abbrev-ref --symbolic-full-name @{u}
OUTPUT_VARIABLE GIT_REMOTE_NAME
- RESULT_VARIABLE GIT_BRANCH_RESULT
+ RESULT_VARIABLE GIT_REMOTE_RESULT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
-
# If there's no upstream set or the command failed, check remote.pushDefault
-if (GIT_BRANCH_RESULT OR GIT_REMOTE_NAME STREQUAL "")
+if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
+ message("check default push")
execute_process(
COMMAND git config --get remote.pushDefault
OUTPUT_VARIABLE GIT_REMOTE_NAME
- RESULT_VARIABLE GIT_PUSH_DEFAULT_RESULT
+ RESULT_VARIABLE GIT_REMOTE_RESULT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
-
- # If remote.pushDefault is not set or fails, default to origin
- if (GIT_PUSH_DEFAULT_RESULT OR GIT_REMOTE_NAME STREQUAL "")
- set(GIT_REMOTE_NAME "origin")
+endif()
+# If running in GitHub Actions and the above fails
+if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
+ message("check github")
+ set(GIT_REMOTE_NAME "origin")
+
+ if (DEFINED ENV{GITHUB_HEAD_REF}) # PR branch name
+ set(GIT_BRANCH "pr-$ENV{GITHUB_HEAD_REF}")
+ elseif (DEFINED ENV{GITHUB_REF}) # Normal branch name
+ string(REGEX REPLACE "^refs/[^/]*/" "" GIT_BRANCH "$ENV{GITHUB_REF}")
+ else()
+ message("couldn't find branch")
+ set(GIT_BRANCH "detached-head")
endif()
else()
# Extract remote name if the output contains a remote/branch format
@@ -148,6 +159,7 @@ else()
endif()
# Get remote link
+message("getting remote link")
execute_process(
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
OUTPUT_VARIABLE GIT_REMOTE_URL
@@ -156,6 +168,8 @@ execute_process(
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
+message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
+
find_package(Boost 1.84.0 CONFIG)
find_package(FFmpeg 5.1.2 MODULE)
find_package(fmt 10.2.0 CONFIG)
@@ -378,6 +392,24 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
src/core/libraries/ngs2/ngs2_error.h
src/core/libraries/ngs2/ngs2_impl.cpp
src/core/libraries/ngs2/ngs2_impl.h
+ src/core/libraries/ngs2/ngs2_custom.cpp
+ src/core/libraries/ngs2/ngs2_custom.h
+ src/core/libraries/ngs2/ngs2_reverb.cpp
+ src/core/libraries/ngs2/ngs2_reverb.h
+ src/core/libraries/ngs2/ngs2_geom.cpp
+ src/core/libraries/ngs2/ngs2_geom.h
+ src/core/libraries/ngs2/ngs2_pan.cpp
+ src/core/libraries/ngs2/ngs2_pan.h
+ src/core/libraries/ngs2/ngs2_report.cpp
+ src/core/libraries/ngs2/ngs2_report.h
+ src/core/libraries/ngs2/ngs2_eq.cpp
+ src/core/libraries/ngs2/ngs2_eq.h
+ src/core/libraries/ngs2/ngs2_mastering.cpp
+ src/core/libraries/ngs2/ngs2_mastering.h
+ src/core/libraries/ngs2/ngs2_sampler.cpp
+ src/core/libraries/ngs2/ngs2_sampler.h
+ src/core/libraries/ngs2/ngs2_submixer.cpp
+ src/core/libraries/ngs2/ngs2_submixer.h
src/core/libraries/ajm/ajm_error.h
src/core/libraries/audio3d/audio3d.cpp
src/core/libraries/audio3d/audio3d.h
@@ -621,9 +653,6 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/aerolib/aerolib.h
src/core/address_space.cpp
src/core/address_space.h
- src/core/crypto/crypto.cpp
- src/core/crypto/crypto.h
- src/core/crypto/keys.h
src/core/devices/base_device.cpp
src/core/devices/base_device.h
src/core/devices/ioccom.h
@@ -641,10 +670,6 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/devices/srandom_device.cpp
src/core/devices/srandom_device.h
src/core/file_format/pfs.h
- src/core/file_format/pkg.cpp
- src/core/file_format/pkg.h
- src/core/file_format/pkg_type.cpp
- src/core/file_format/pkg_type.h
src/core/file_format/psf.cpp
src/core/file_format/psf.h
src/core/file_format/playgo_chunk.cpp
@@ -653,8 +678,6 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/file_format/trp.h
src/core/file_sys/fs.cpp
src/core/file_sys/fs.h
- src/core/loader.cpp
- src/core/loader.h
src/core/loader/dwarf.cpp
src/core/loader/dwarf.h
src/core/loader/elf.cpp
@@ -944,10 +967,6 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
src/qt_gui/game_grid_frame.h
src/qt_gui/game_install_dialog.cpp
src/qt_gui/game_install_dialog.h
- src/qt_gui/install_dir_select.cpp
- src/qt_gui/install_dir_select.h
- src/qt_gui/pkg_viewer.cpp
- src/qt_gui/pkg_viewer.h
src/qt_gui/trophy_viewer.cpp
src/qt_gui/trophy_viewer.h
src/qt_gui/elf_viewer.cpp
diff --git a/REUSE.toml b/REUSE.toml
index 793990bd8..ad2bc3678 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -49,8 +49,10 @@ path = [
"src/images/pause_icon.png",
"src/images/play_icon.png",
"src/images/ps4_controller.png",
- "src/images/refresh_icon.png",
+ "src/images/restart_game_icon.png",
+ "src/images/refreshlist_icon.png",
"src/images/settings_icon.png",
+ "src/images/fullscreen_icon.png",
"src/images/stop_icon.png",
"src/images/utils_icon.png",
"src/images/shadPS4.icns",
diff --git a/documents/Quickstart/2.png b/documents/Quickstart/2.png
deleted file mode 100644
index 7e5bdfb15..000000000
Binary files a/documents/Quickstart/2.png and /dev/null differ
diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md
index 2f2751887..9c6bc5a6f 100644
--- a/documents/Quickstart/Quickstart.md
+++ b/documents/Quickstart/Quickstart.md
@@ -13,7 +13,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
- [**RAM**](#ram)
- [**OS**](#os)
- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4)
-- [**Install PKG files (Games and Updates)**](#install-pkg-files)
- [**Configure the emulator**](#configure-the-emulator)
## Minimum PC requirements
@@ -48,13 +47,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder.
-3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that shadPS4 can use to install your PKG files to.
-
-## Install PKG files
-
-To install PKG files (game and updates), you will need the Qt application (with UI). You will have to go to "File" then to "Install Packages (PKG)", a window will open then you will have to select the files. You can install multiple PKG files at once. Once finished, the game should appear in the application.
-
-
+3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that contains your dumped games.
## Configure the emulator
diff --git a/documents/building-linux.md b/documents/building-linux.md
index 18ddab0c6..cdc8ba12f 100644
--- a/documents/building-linux.md
+++ b/documents/building-linux.md
@@ -108,7 +108,7 @@ Now run the emulator. If Qt was enabled at configure time:
./build/shadps4
```
-Otherwise, specify the path to your PKG's boot file:
+Otherwise, specify the path to your game's boot file:
```bash
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
diff --git a/src/common/config.cpp b/src/common/config.cpp
index e0a348fbe..d1bb89897 100644
--- a/src/common/config.cpp
+++ b/src/common/config.cpp
@@ -32,6 +32,7 @@ std::filesystem::path find_fs_path_or(const basic_value& v, const K& ky,
namespace Config {
static bool isNeo = false;
+static bool isDevKit = false;
static bool playBGM = false;
static bool isTrophyPopupDisabled = false;
static int BGMvolume = 50;
@@ -40,7 +41,7 @@ static u32 screenWidth = 1280;
static u32 screenHeight = 720;
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
static std::string logFilter;
-static std::string logType = "async";
+static std::string logType = "sync";
static std::string userName = "shadPS4";
static std::string updateChannel;
static std::string chooseHomeTab;
@@ -97,7 +98,6 @@ u32 m_slider_pos_grid = 0;
u32 m_table_mode = 0;
u32 m_window_size_W = 1280;
u32 m_window_size_H = 720;
-std::vector m_pkg_viewer;
std::vector m_elf_viewer;
std::vector m_recent_files;
std::string emulator_language = "en_US";
@@ -106,6 +106,7 @@ static bool showBackgroundImage = true;
static bool isFullscreen = false;
static std::string fullscreenMode = "Windowed";
static bool isHDRAllowed = false;
+static bool showLabelsUnderIcons = true;
// Language
u32 m_language = 1; // english
@@ -167,10 +168,22 @@ bool isNeoModeConsole() {
return isNeo;
}
+bool isDevKitConsole() {
+ return isDevKit;
+}
+
bool getIsFullscreen() {
return isFullscreen;
}
+bool getShowLabelsUnderIcons() {
+ return showLabelsUnderIcons;
+}
+
+bool setShowLabelsUnderIcons() {
+ return false;
+}
+
std::string getFullscreenMode() {
return fullscreenMode;
}
@@ -422,6 +435,9 @@ void setVblankDiv(u32 value) {
void setIsFullscreen(bool enable) {
isFullscreen = enable;
}
+static void setShowLabelsUnderIcons(bool enable) {
+ showLabelsUnderIcons = enable;
+}
void setFullscreenMode(std::string mode) {
fullscreenMode = mode;
@@ -584,11 +600,6 @@ void setMainWindowHeight(u32 height) {
m_window_size_H = height;
}
-void setPkgViewer(const std::vector& pkgList) {
- m_pkg_viewer.resize(pkgList.size());
- m_pkg_viewer = pkgList;
-}
-
void setElfViewer(const std::vector& elfList) {
m_elf_viewer.resize(elfList.size());
m_elf_viewer = elfList;
@@ -692,10 +703,6 @@ u32 getMainWindowHeight() {
return m_window_size_H;
}
-std::vector getPkgViewer() {
- return m_pkg_viewer;
-}
-
std::vector getElfViewer() {
return m_elf_viewer;
}
@@ -755,6 +762,7 @@ void load(const std::filesystem::path& path) {
const toml::value& general = data.at("General");
isNeo = toml::find_or(general, "isPS4Pro", false);
+ isDevKit = toml::find_or(general, "isDevKit", false);
playBGM = toml::find_or(general, "playBGM", false);
isTrophyPopupDisabled = toml::find_or(general, "isTrophyPopupDisabled", false);
trophyNotificationDuration =
@@ -842,7 +850,7 @@ void load(const std::filesystem::path& path) {
m_window_size_H = toml::find_or(gui, "mw_height", 0);
const auto install_dir_array =
- toml::find_or>(gui, "installDirs", {});
+ toml::find_or>(gui, "installDirs", {});
try {
install_dirs_enabled = toml::find>(gui, "installDirsEnabled");
@@ -868,7 +876,6 @@ void load(const std::filesystem::path& path) {
main_window_geometry_y = toml::find_or(gui, "geometry_y", 0);
main_window_geometry_w = toml::find_or(gui, "geometry_w", 0);
main_window_geometry_h = toml::find_or(gui, "geometry_h", 0);
- m_pkg_viewer = toml::find_or>(gui, "pkgDirs", {});
m_elf_viewer = toml::find_or>(gui, "elfDirs", {});
m_recent_files = toml::find_or>(gui, "recentFiles", {});
m_table_mode = toml::find_or(gui, "gameTableMode", 0);
@@ -955,6 +962,7 @@ void save(const std::filesystem::path& path) {
}
data["General"]["isPS4Pro"] = isNeo;
+ data["General"]["isDevKit"] = isDevKit;
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
data["General"]["playBGM"] = playBGM;
@@ -1086,7 +1094,6 @@ void saveMainWindow(const std::filesystem::path& path) {
data["GUI"]["geometry_y"] = main_window_geometry_y;
data["GUI"]["geometry_w"] = main_window_geometry_w;
data["GUI"]["geometry_h"] = main_window_geometry_h;
- data["GUI"]["pkgDirs"] = m_pkg_viewer;
data["GUI"]["elfDirs"] = m_elf_viewer;
data["GUI"]["recentFiles"] = m_recent_files;
@@ -1101,6 +1108,7 @@ void saveMainWindow(const std::filesystem::path& path) {
void setDefaultValues() {
isHDRAllowed = false;
isNeo = false;
+ isDevKit = false;
isFullscreen = false;
isTrophyPopupDisabled = false;
playBGM = false;
@@ -1109,7 +1117,7 @@ void setDefaultValues() {
screenWidth = 1280;
screenHeight = 720;
logFilter = "";
- logType = "async";
+ logType = "sync";
userName = "shadPS4";
if (Common::isRelease) {
updateChannel = "Release";
diff --git a/src/common/config.h b/src/common/config.h
index 4202da88a..d040aa337 100644
--- a/src/common/config.h
+++ b/src/common/config.h
@@ -26,8 +26,11 @@ bool GetLoadGameSizeEnabled();
std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen();
+bool getShowLabelsUnderIcons();
+bool setShowLabelsUnderIcons();
std::string getFullscreenMode();
bool isNeoModeConsole();
+bool isDevKitConsole();
bool getPlayBGM();
int getBGMvolume();
bool getisTrophyPopupDisabled();
@@ -151,7 +154,6 @@ void setSliderPositionGrid(u32 pos);
void setTableMode(u32 mode);
void setMainWindowWidth(u32 width);
void setMainWindowHeight(u32 height);
-void setPkgViewer(const std::vector& pkgList);
void setElfViewer(const std::vector& elfList);
void setRecentFiles(const std::vector& recentFiles);
void setEmulatorLanguage(std::string language);
@@ -171,7 +173,6 @@ u32 getSliderPositionGrid();
u32 getTableMode();
u32 getMainWindowWidth();
u32 getMainWindowHeight();
-std::vector getPkgViewer();
std::vector getElfViewer();
std::vector getRecentFiles();
std::string getEmulatorLanguage();
diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp
index 067010a26..3efadc6ea 100644
--- a/src/common/io_file.cpp
+++ b/src/common/io_file.cpp
@@ -125,12 +125,15 @@ namespace {
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
switch (origin) {
case SeekOrigin::SetOrigin:
- default:
return SEEK_SET;
case SeekOrigin::CurrentPosition:
return SEEK_CUR;
case SeekOrigin::End:
return SEEK_END;
+ default:
+ LOG_ERROR(Common_Filesystem, "Unsupported origin {}, defaulting to SEEK_SET",
+ static_cast(origin));
+ return SEEK_SET;
}
}
@@ -377,20 +380,6 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
return false;
}
- if (False(file_access_mode & (FileAccessMode::Write | FileAccessMode::Append))) {
- u64 size = GetSize();
- if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
- LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
- return false;
- } else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
- LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
- return false;
- } else if (origin == SeekOrigin::End && offset > 0) {
- LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
- return false;
- }
- }
-
errno = 0;
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
diff --git a/src/common/io_file.h b/src/common/io_file.h
index 45787a092..fb20a2bc5 100644
--- a/src/common/io_file.h
+++ b/src/common/io_file.h
@@ -61,6 +61,8 @@ enum class SeekOrigin : u32 {
SetOrigin, // Seeks from the start of the file.
CurrentPosition, // Seeks from the current file pointer position.
End, // Seeks from the end of the file.
+ SeekHole, // Seeks from the start of the next hole in the file.
+ SeekData, // Seeks from the start of the next non-hole region in the file.
};
class IOFile final {
diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp
deleted file mode 100644
index 4020edfd8..000000000
--- a/src/core/crypto/crypto.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-
-#include "crypto.h"
-
-CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
- CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80));
- params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80));
-
- params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4));
- params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100));
-
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80));
-
- params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80));
-
- CryptoPP::RSA::PrivateKey privateKey(params);
-
- return privateKey;
-}
-
-CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() {
- CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80));
- params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80));
-
- params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4));
- params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100));
-
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80));
-
- params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(FakeKeyset::Coefficient, 0x80));
-
- CryptoPP::RSA::PrivateKey privateKey(params);
-
- return privateKey;
-}
-
-CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() {
- CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1)));
- params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2)));
-
- params.SetPublicExponent(
- CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent)));
- params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent,
- sizeof(DebugRifKeyset::PrivateExponent)));
-
- params.SetModPrime1PrivateExponent(
- CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1)));
- params.SetModPrime2PrivateExponent(
- CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2)));
-
- params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus)));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient)));
-
- CryptoPP::RSA::PrivateKey privateKey(params);
-
- return privateKey;
-}
-
-void Crypto::RSA2048Decrypt(std::span dec_key,
- std::span ciphertext,
- bool is_dk3) { // RSAES_PKCS1v15_
- // Create an RSA decryptor
- CryptoPP::RSA::PrivateKey privateKey;
- if (is_dk3) {
- privateKey = key_pkg_derived_key3_keyset_init();
- } else {
- privateKey = FakeKeyset_keyset_init();
- }
-
- CryptoPP::RSAES_PKCS1v15_Decryptor rsaDecryptor(privateKey);
-
- // Allocate memory for the decrypted data
- std::array decrypted;
-
- // Perform the decryption
- CryptoPP::AutoSeededRandomPool rng;
- CryptoPP::DecodingResult result =
- rsaDecryptor.Decrypt(rng, ciphertext.data(), decrypted.size(), decrypted.data());
- std::copy(decrypted.begin(), decrypted.begin() + dec_key.size(), dec_key.begin());
-}
-
-void Crypto::ivKeyHASH256(std::span cipher_input,
- std::span ivkey_result) {
- CryptoPP::SHA256 sha256;
- std::array hashResult;
- auto array_sink = new CryptoPP::ArraySink(hashResult.data(), CryptoPP::SHA256::DIGESTSIZE);
- auto filter = new CryptoPP::HashFilter(sha256, array_sink);
- CryptoPP::ArraySource r(cipher_input.data(), cipher_input.size(), true, filter);
- std::copy(hashResult.begin(), hashResult.begin() + ivkey_result.size(), ivkey_result.begin());
-}
-
-void Crypto::aesCbcCfb128Decrypt(std::span ivkey,
- std::span ciphertext,
- std::span decrypted) {
- std::array key;
- std::array iv;
-
- std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
- std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
-
- CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
- CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
-
- for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
- cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
- CryptoPP::AES::BLOCKSIZE);
- }
-}
-
-void Crypto::aesCbcCfb128DecryptEntry(std::span ivkey,
- std::span ciphertext,
- std::span decrypted) {
- std::array key;
- std::array iv;
-
- std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
- std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
-
- CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
- CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
-
- for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
- cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
- CryptoPP::AES::BLOCKSIZE);
- }
-}
-
-void Crypto::decryptEFSM(std::span trophyKey,
- std::span NPcommID,
- std::span efsmIv, std::span ciphertext,
- std::span decrypted) {
-
- // step 1: Encrypt NPcommID
- CryptoPP::CBC_Mode::Encryption encrypt;
-
- std::vector trophyIv(16, 0);
- std::vector trpKey(16);
-
- encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data());
- encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
-
- // step 2: decrypt efsm.
- CryptoPP::CBC_Mode::Decryption decrypt;
- decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
-
- for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
- decrypt.ProcessData(decrypted.data() + i, ciphertext.data() + i, CryptoPP::AES::BLOCKSIZE);
- }
-}
-
-void Crypto::PfsGenCryptoKey(std::span ekpfs,
- std::span seed,
- std::span dataKey,
- std::span tweakKey) {
- CryptoPP::HMAC hmac(ekpfs.data(), ekpfs.size());
-
- CryptoPP::SecByteBlock d(20); // Use Crypto++ SecByteBlock for better memory management
-
- // Copy the bytes of 'index' to the 'd' array
- uint32_t index = 1;
- std::memcpy(d, &index, sizeof(uint32_t));
-
- // Copy the bytes of 'seed' to the 'd' array starting from index 4
- std::memcpy(d + sizeof(uint32_t), seed.data(), seed.size());
-
- // Allocate memory for 'u64' using new
- std::vector data_tweak_key(hmac.DigestSize());
-
- // Calculate the HMAC
- hmac.CalculateDigest(data_tweak_key.data(), d, d.size());
- std::copy(data_tweak_key.begin(), data_tweak_key.begin() + dataKey.size(), tweakKey.begin());
- std::copy(data_tweak_key.begin() + tweakKey.size(),
- data_tweak_key.begin() + tweakKey.size() + dataKey.size(), dataKey.begin());
-}
-
-void Crypto::decryptPFS(std::span dataKey,
- std::span tweakKey, std::span src_image,
- std::span dst_image, u64 sector) {
- // Start at 0x10000 to keep the header when decrypting the whole pfs_image.
- for (int i = 0; i < src_image.size(); i += 0x1000) {
- const u64 current_sector = sector + (i / 0x1000);
- CryptoPP::ECB_Mode::Encryption encrypt(tweakKey.data(), tweakKey.size());
- CryptoPP::ECB_Mode::Decryption decrypt(dataKey.data(), dataKey.size());
-
- std::array tweak{};
- std::array encryptedTweak;
- std::array xorBuffer;
- std::memcpy(tweak.data(), ¤t_sector, sizeof(u64));
-
- // Encrypt the tweak for each sector.
- encrypt.ProcessData(encryptedTweak.data(), tweak.data(), 16);
-
- for (int plaintextOffset = 0; plaintextOffset < 0x1000; plaintextOffset += 16) {
- xtsXorBlock(xorBuffer.data(), src_image.data() + i + plaintextOffset,
- encryptedTweak.data()); // x, c, t
- decrypt.ProcessData(xorBuffer.data(), xorBuffer.data(), 16); // x, x
- xtsXorBlock(dst_image.data() + i + plaintextOffset, xorBuffer.data(),
- encryptedTweak.data()); //(p) c, x , t
- xtsMult(encryptedTweak);
- }
- }
-}
diff --git a/src/core/crypto/crypto.h b/src/core/crypto/crypto.h
deleted file mode 100644
index b5d8104b5..000000000
--- a/src/core/crypto/crypto.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "common/types.h"
-#include "keys.h"
-
-class Crypto {
-public:
- CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init();
- CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init();
- CryptoPP::RSA::PrivateKey DebugRifKeyset_init();
-
- void RSA2048Decrypt(std::span dk3,
- std::span ciphertext,
- bool is_dk3); // RSAES_PKCS1v15_
- void ivKeyHASH256(std::span cipher_input,
- std::span ivkey_result);
- void aesCbcCfb128Decrypt(std::span ivkey,
- std::span ciphertext,
- std::span decrypted);
- void aesCbcCfb128DecryptEntry(std::span ivkey,
- std::span ciphertext,
- std::span decrypted);
- void decryptEFSM(std::span trophyKey,
- std::span NPcommID, std::span efsmIv,
- std::span ciphertext, std::span decrypted);
- void PfsGenCryptoKey(std::span ekpfs,
- std::span seed,
- std::span dataKey,
- std::span tweakKey);
- void decryptPFS(std::span dataKey,
- std::span tweakKey, std::span src_image,
- std::span dst_image, u64 sector);
-
- void xtsXorBlock(CryptoPP::byte* x, const CryptoPP::byte* a, const CryptoPP::byte* b) {
- for (int i = 0; i < 16; i++) {
- x[i] = a[i] ^ b[i];
- }
- }
-
- void xtsMult(std::span encryptedTweak) {
- int feedback = 0;
- for (int k = 0; k < encryptedTweak.size(); k++) {
- const auto tmp = (encryptedTweak[k] >> 7) & 1;
- encryptedTweak[k] = ((encryptedTweak[k] << 1) + feedback) & 0xFF;
- feedback = tmp;
- }
- if (feedback != 0) {
- encryptedTweak[0] ^= 0x87;
- }
- }
-};
diff --git a/src/core/crypto/keys.h b/src/core/crypto/keys.h
deleted file mode 100644
index 441082481..000000000
--- a/src/core/crypto/keys.h
+++ /dev/null
@@ -1,305 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-#include
-
-class FakeKeyset {
-public:
- // Constructor
- static constexpr CryptoPP::byte Exponent1[] = {
- 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7,
- 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9,
- 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6,
- 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6,
- 0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC,
- 0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF,
- 0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8,
- 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E,
- 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25};
- // exponent2 = d mod (q - 1)
- static constexpr CryptoPP::byte Exponent2[] = {
- 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60,
- 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8,
- 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75,
- 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18,
- 0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16,
- 0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C,
- 0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD,
- 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA,
- 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D};
- // e
- static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
- // (InverseQ)(q) = 1 mod p
- static constexpr CryptoPP::byte Coefficient[] = {
- 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD,
- 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D,
- 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B,
- 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69,
- 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15,
- 0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8,
- 0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6,
- 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67,
- 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5};
- // n = p * q
- static constexpr CryptoPP::byte Modulus[] = {
- 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E,
- 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D,
- 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B,
- 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7,
- 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C,
- 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33,
- 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01,
- 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A,
- 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96,
- 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80,
- 0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F,
- 0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53,
- 0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22,
- 0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F,
- 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40,
- 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9,
- 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E,
- 0x27};
- // p
- static constexpr CryptoPP::byte Prime1[] = {
- 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35,
- 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24,
- 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9,
- 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F,
- 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C,
- 0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A,
- 0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40,
- 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89,
- 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D};
- // q
- static constexpr CryptoPP::byte Prime2[] = {
- 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97,
- 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0,
- 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D,
- 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47,
- 0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92,
- 0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A,
- 0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79,
- 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51,
- 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23};
- static constexpr CryptoPP::byte PrivateExponent[] = {
- 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA,
- 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD,
- 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C,
- 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F,
- 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09,
- 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14,
- 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77,
- 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90,
- 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22,
- 0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0,
- 0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93,
- 0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5,
- 0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5,
- 0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1,
- 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85,
- 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39,
- 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6,
- 0xB1};
-};
-
-class DebugRifKeyset {
-public:
- // std::uint8_t* PrivateExponent;
- static constexpr CryptoPP::byte Exponent1[] = {
- 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56,
- 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C,
- 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F,
- 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87,
- 0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F,
- 0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6,
- 0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69,
- 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6,
- 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9};
- // exponent2 = d mod (q - 1)
- static constexpr CryptoPP::byte Exponent2[] = {
- 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44,
- 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B,
- 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91,
- 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88,
- 0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B,
- 0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7,
- 0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF,
- 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F,
- 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05};
- // e
- static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01};
- // (InverseQ)(q) = 1 mod p
- static constexpr CryptoPP::byte Coefficient[] = {
- 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C,
- 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4,
- 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4,
- 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD,
- 0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A,
- 0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7,
- 0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75,
- 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A,
- 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB};
- // n = p * q
- static constexpr CryptoPP::byte Modulus[] = {
- 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A,
- 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB,
- 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B,
- 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD,
- 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53,
- 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F,
- 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30,
- 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A,
- 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4,
- 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B,
- 0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E,
- 0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87,
- 0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19,
- 0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A,
- 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C,
- 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58,
- 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64,
- 0xC1};
- // p
- static constexpr CryptoPP::byte Prime1[] = {
- 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6,
- 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34,
- 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8,
- 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5,
- 0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5,
- 0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8,
- 0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39,
- 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F,
- 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05};
- // q
- static constexpr CryptoPP::byte Prime2[] = {
- 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C,
- 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38,
- 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D,
- 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2,
- 0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31,
- 0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE,
- 0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81,
- 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B,
- 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D};
- static constexpr CryptoPP::byte PrivateExponent[] = {
- 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01,
- 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC,
- 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73,
- 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61,
- 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9,
- 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28,
- 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36,
- 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E,
- 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14,
- 0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97,
- 0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F,
- 0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C,
- 0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61,
- 0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49,
- 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3,
- 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E,
- 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14,
- 0xA5};
-};
-
-class PkgDerivedKey3Keyset {
-public:
- // std::uint8_t* PrivateExponent;
- static constexpr CryptoPP::byte Exponent1[] = {
- 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1,
- 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7,
- 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36,
- 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43,
- 0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0,
- 0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E,
- 0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D,
- 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC,
- 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13};
- // exponent2 = d mod (q - 1)
- static constexpr CryptoPP::byte Exponent2[] = {
- 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5,
- 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71,
- 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51,
- 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D,
- 0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00,
- 0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98,
- 0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1,
- 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57,
- 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37};
- // e
- static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
- // (InverseQ)(q) = 1 mod p
- static constexpr CryptoPP::byte Coefficient[] = {
- 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42,
- 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3,
- 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE,
- 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C,
- 0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF,
- 0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D,
- 0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17,
- 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6,
- 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3};
- // n = p * q
- static constexpr CryptoPP::byte Modulus[] = {
- 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27,
- 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb,
- 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb,
- 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef,
- 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a,
- 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99,
- 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d,
- 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44,
- 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c,
- 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65,
- 0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6,
- 0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65,
- 0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f,
- 0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01,
- 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09,
- 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95,
- 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3,
- 0xc1};
- // p
- static constexpr CryptoPP::byte Prime1[] = {
- 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D,
- 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42,
- 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE,
- 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52,
- 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D,
- 0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23,
- 0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80,
- 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE,
- 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB};
- // q
- static constexpr CryptoPP::byte Prime2[] = {
- 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40,
- 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F,
- 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89,
- 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9,
- 0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E,
- 0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C,
- 0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53,
- 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10,
- 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73};
- static constexpr CryptoPP::byte PrivateExponent[] = {
- 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3,
- 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1,
- 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE,
- 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41,
- 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D,
- 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F,
- 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3,
- 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB,
- 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD,
- 0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB,
- 0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F,
- 0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80,
- 0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65,
- 0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64,
- 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A,
- 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08,
- 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC,
- 0x0D};
-};
\ No newline at end of file
diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp
index 87fd9ffb3..94b39e801 100644
--- a/src/core/devtools/layer.cpp
+++ b/src/core/devtools/layer.cpp
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "SDL3/SDL_log.h"
#include "layer.h"
#include
@@ -117,22 +118,6 @@ void L::DrawMenuBar() {
EndMainMenuBar();
}
-
- if (IsKeyPressed(ImGuiKey_F9, false)) {
- if (io.KeyCtrl && io.KeyAlt) {
- if (!DebugState.ShouldPauseInSubmit()) {
- DebugState.RequestFrameDump(dump_frame_count);
- }
- }
- if (!io.KeyCtrl && !io.KeyAlt) {
- if (isSystemPaused) {
- DebugState.ResumeGuestThreads();
- } else {
- DebugState.PauseGuestThreads();
- }
- }
- }
-
if (open_popup_options) {
OpenPopup("GPU Tools Options");
just_opened_options = true;
@@ -381,6 +366,32 @@ void L::Draw() {
visibility_toggled = true;
}
+ if (IsKeyPressed(ImGuiKey_F9, false)) {
+ if (io.KeyCtrl && io.KeyAlt) {
+ if (!DebugState.ShouldPauseInSubmit()) {
+ DebugState.RequestFrameDump(dump_frame_count);
+ }
+ } else {
+ if (DebugState.IsGuestThreadsPaused()) {
+ DebugState.ResumeGuestThreads();
+ SDL_Log("Game resumed from Keyboard");
+ show_pause_status = false;
+ } else {
+ DebugState.PauseGuestThreads();
+ SDL_Log("Game paused from Keyboard");
+ show_pause_status = true;
+ }
+ visibility_toggled = true;
+ }
+ }
+
+ if (show_pause_status) {
+ ImVec2 pos = ImVec2(10, 10);
+ ImU32 color = IM_COL32(255, 255, 255, 255);
+
+ ImGui::GetForegroundDrawList()->AddText(pos, color, "Game Paused Press F9 to Resume");
+ }
+
if (show_simple_fps) {
if (Begin("Video Info", nullptr,
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
diff --git a/src/core/devtools/layer.h b/src/core/devtools/layer.h
index 5bb53fbdb..9e949c8e9 100644
--- a/src/core/devtools/layer.h
+++ b/src/core/devtools/layer.h
@@ -19,6 +19,7 @@ public:
static void SetupSettings();
void Draw() override;
+ bool show_pause_status = false;
};
} // namespace Core::Devtools
diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp
deleted file mode 100644
index ecc5f10a4..000000000
--- a/src/core/file_format/pkg.cpp
+++ /dev/null
@@ -1,473 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include "common/io_file.h"
-#include "common/logging/formatter.h"
-#include "core/file_format/pkg.h"
-#include "core/file_format/pkg_type.h"
-
-static void DecompressPFSC(std::span compressed_data, std::span decompressed_data) {
- z_stream decompressStream;
- decompressStream.zalloc = Z_NULL;
- decompressStream.zfree = Z_NULL;
- decompressStream.opaque = Z_NULL;
-
- if (inflateInit(&decompressStream) != Z_OK) {
- // std::cerr << "Error initializing zlib for deflation." << std::endl;
- }
-
- decompressStream.avail_in = compressed_data.size();
- decompressStream.next_in = reinterpret_cast(compressed_data.data());
- decompressStream.avail_out = decompressed_data.size();
- decompressStream.next_out = reinterpret_cast(decompressed_data.data());
-
- if (inflate(&decompressStream, Z_FINISH)) {
- }
- if (inflateEnd(&decompressStream) != Z_OK) {
- // std::cerr << "Error ending zlib inflate" << std::endl;
- }
-}
-
-u32 GetPFSCOffset(std::span pfs_image) {
- static constexpr u32 PfscMagic = 0x43534650;
- u32 value;
- for (u32 i = 0x20000; i < pfs_image.size(); i += 0x10000) {
- std::memcpy(&value, &pfs_image[i], sizeof(u32));
- if (value == PfscMagic)
- return i;
- }
- return -1;
-}
-
-PKG::PKG() = default;
-
-PKG::~PKG() = default;
-
-bool PKG::Open(const std::filesystem::path& filepath, std::string& failreason) {
- Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
- if (!file.IsOpen()) {
- return false;
- }
- pkgSize = file.GetSize();
-
- file.Read(pkgheader);
- if (pkgheader.magic != 0x7F434E54)
- return false;
-
- for (const auto& flag : flagNames) {
- if (isFlagSet(pkgheader.pkg_content_flags, flag.first)) {
- if (!pkgFlags.empty())
- pkgFlags += (", ");
- pkgFlags += (flag.second);
- }
- }
-
- // Find title id it is part of pkg_content_id starting at offset 0x40
- file.Seek(0x47); // skip first 7 characters of content_id
- file.Read(pkgTitleID);
-
- u32 offset = pkgheader.pkg_table_entry_offset;
- u32 n_files = pkgheader.pkg_table_entry_count;
-
- if (!file.Seek(offset)) {
- failreason = "Failed to seek to PKG table entry offset";
- return false;
- }
-
- for (int i = 0; i < n_files; i++) {
- PKGEntry entry{};
- file.Read(entry.id);
- file.Read(entry.filename_offset);
- file.Read(entry.flags1);
- file.Read(entry.flags2);
- file.Read(entry.offset);
- file.Read(entry.size);
- file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
-
- // Try to figure out the name
- const auto name = GetEntryNameByType(entry.id);
- if (name == "param.sfo") {
- sfo.clear();
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to param.sfo offset";
- return false;
- }
- sfo.resize(entry.size);
- file.ReadRaw(sfo.data(), entry.size);
- }
- }
- file.Close();
-
- return true;
-}
-
-bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
- std::string& failreason) {
- extract_path = extract;
- pkgpath = filepath;
- Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
- if (!file.IsOpen()) {
- return false;
- }
- pkgSize = file.GetSize();
- file.ReadRaw(&pkgheader, sizeof(PKGHeader));
-
- if (pkgheader.magic != 0x7F434E54)
- return false;
-
- if (pkgheader.pkg_size > pkgSize) {
- failreason = "PKG file size is different";
- return false;
- }
- if ((pkgheader.pkg_content_size + pkgheader.pkg_content_offset) > pkgheader.pkg_size) {
- failreason = "Content size is bigger than pkg size";
- return false;
- }
-
- u32 offset = pkgheader.pkg_table_entry_offset;
- u32 n_files = pkgheader.pkg_table_entry_count;
-
- std::array concatenated_ivkey_dk3;
- std::array seed_digest;
- std::array, 7> digest1;
- std::array, 7> key1;
- std::array imgkeydata;
-
- if (!file.Seek(offset)) {
- failreason = "Failed to seek to PKG table entry offset";
- return false;
- }
-
- for (int i = 0; i < n_files; i++) {
- PKGEntry entry{};
- file.Read(entry.id);
- file.Read(entry.filename_offset);
- file.Read(entry.flags1);
- file.Read(entry.flags2);
- file.Read(entry.offset);
- file.Read(entry.size);
- file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
-
- auto currentPos = file.Tell();
-
- // Try to figure out the name
- const auto name = GetEntryNameByType(entry.id);
- const auto filepath = extract_path / "sce_sys" / name;
- std::filesystem::create_directories(filepath.parent_path());
-
- if (name.empty()) {
- // Just print with id
- Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id),
- Common::FS::FileAccessMode::Write);
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to PKG entry offset";
- return false;
- }
-
- std::vector data;
- data.resize(entry.size);
- file.ReadRaw(data.data(), entry.size);
- out.WriteRaw(data.data(), entry.size);
- out.Close();
-
- file.Seek(currentPos);
- continue;
- }
-
- if (entry.id == 0x1) { // DIGESTS, seek;
- // file.Seek(entry.offset, fsSeekSet);
- } else if (entry.id == 0x10) { // ENTRY_KEYS, seek;
- file.Seek(entry.offset);
- file.Read(seed_digest);
-
- for (int i = 0; i < 7; i++) {
- file.Read(digest1[i]);
- }
-
- for (int i = 0; i < 7; i++) {
- file.Read(key1[i]);
- }
-
- PKG::crypto.RSA2048Decrypt(dk3_, key1[3], true); // decrypt DK3
- } else if (entry.id == 0x20) { // IMAGE_KEY, seek; IV_KEY
- file.Seek(entry.offset);
- file.Read(imgkeydata);
-
- // The Concatenated iv + dk3 imagekey for HASH256
- std::memcpy(concatenated_ivkey_dk3.data(), &entry, sizeof(entry));
- std::memcpy(concatenated_ivkey_dk3.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
-
- PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3, ivKey); // ivkey_
- // imgkey_ to use for last step to get ekpfs
- PKG::crypto.aesCbcCfb128Decrypt(ivKey, imgkeydata, imgKey);
- // ekpfs key to get data and tweak keys.
- PKG::crypto.RSA2048Decrypt(ekpfsKey, imgKey, false);
- } else if (entry.id == 0x80) {
- // GENERAL_DIGESTS, seek;
- // file.Seek(entry.offset, fsSeekSet);
- }
-
- Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write);
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to PKG entry offset";
- return false;
- }
-
- std::vector data;
- data.resize(entry.size);
- file.ReadRaw(data.data(), entry.size);
- out.WriteRaw(data.data(), entry.size);
- out.Close();
-
- // Decrypt Np stuff and overwrite.
- if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 ||
- entry.id == 0x403) { // somehow 0x401 is not decrypting
- decNp.resize(entry.size);
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to PKG entry offset";
- return false;
- }
-
- std::vector data;
- data.resize(entry.size);
- file.ReadRaw(data.data(), entry.size);
-
- std::span cipherNp(data.data(), entry.size);
- std::array concatenated_ivkey_dk3_;
- std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry));
- std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
- PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3_, ivKey);
- PKG::crypto.aesCbcCfb128DecryptEntry(ivKey, cipherNp, decNp);
-
- Common::FS::IOFile out(extract_path / "sce_sys" / name,
- Common::FS::FileAccessMode::Write);
- out.Write(decNp);
- out.Close();
- }
-
- file.Seek(currentPos);
- }
-
- // Read the seed
- std::array seed;
- if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) {
- failreason = "Failed to seek to PFS image offset";
- return false;
- }
- file.Read(seed);
-
- // Get data and tweak keys.
- PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey);
- const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok.
-
- int num_blocks = 0;
- std::vector pfsc(length);
- if (length != 0) {
- // Read encrypted pfs_image
- std::vector pfs_encrypted(length);
- file.Seek(pkgheader.pfs_image_offset);
- file.Read(pfs_encrypted);
- file.Close();
- // Decrypt the pfs_image.
- std::vector pfs_decrypted(length);
- PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
-
- // Retrieve PFSC from decrypted pfs_image.
- pfsc_offset = GetPFSCOffset(pfs_decrypted);
- std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset);
-
- PFSCHdr pfsChdr;
- std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr));
-
- num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2);
- sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset.
-
- for (int i = 0; i < num_blocks + 1; i++) {
- std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8);
- }
- }
-
- u32 ent_size = 0;
- u32 ndinode = 0;
- int ndinode_counter = 0;
- bool dinode_reached = false;
- bool uroot_reached = false;
- std::vector compressedData;
- std::vector decompressedData(0x10000);
-
- // Get iNdoes and Dirents.
- for (int i = 0; i < num_blocks; i++) {
- const u64 sectorOffset = sectorMap[i];
- const u64 sectorSize = sectorMap[i + 1] - sectorOffset;
-
- compressedData.resize(sectorSize);
- std::memcpy(compressedData.data(), pfsc.data() + sectorOffset, sectorSize);
-
- if (sectorSize == 0x10000) // Uncompressed data
- std::memcpy(decompressedData.data(), compressedData.data(), 0x10000);
- else if (sectorSize < 0x10000) // Compressed data
- DecompressPFSC(compressedData, decompressedData);
-
- if (i == 0) {
- std::memcpy(&ndinode, decompressedData.data() + 0x30, 4); // number of folders and files
- }
-
- int occupied_blocks =
- (ndinode * 0xA8) / 0x10000; // how many blocks(0x10000) are taken by iNodes.
- if (((ndinode * 0xA8) % 0x10000) != 0)
- occupied_blocks += 1;
-
- if (i >= 1 && i <= occupied_blocks) { // Get all iNodes, gives type, file size and location.
- for (int p = 0; p < 0x10000; p += 0xA8) {
- Inode node;
- std::memcpy(&node, &decompressedData[p], sizeof(node));
- if (node.Mode == 0) {
- break;
- }
- iNodeBuf.push_back(node);
- }
- }
-
- // let's deal with the root/uroot entries here.
- // Sometimes it's more than 2 entries (Tomb Raider Remastered)
- const std::string_view flat_path_table(&decompressedData[0x10], 15);
- if (flat_path_table == "flat_path_table") {
- uroot_reached = true;
- }
-
- if (uroot_reached) {
- for (int i = 0; i < 0x10000; i += ent_size) {
- Dirent dirent;
- std::memcpy(&dirent, &decompressedData[i], sizeof(dirent));
- ent_size = dirent.entsize;
- if (dirent.ino != 0) {
- ndinode_counter++;
- } else {
- // Set the the folder according to the current inode.
- // Can be 2 or more (rarely)
- auto parent_path = extract_path.parent_path();
- auto title_id = GetTitleID();
-
- if (parent_path.filename() != title_id &&
- !fmt::UTF(extract_path.u8string()).data.ends_with("-patch")) {
- extractPaths[ndinode_counter] = parent_path / title_id;
- } else {
- // DLCs path has different structure
- extractPaths[ndinode_counter] = extract_path;
- }
- uroot_reached = false;
- break;
- }
- }
- }
-
- const char dot = decompressedData[0x10];
- const std::string_view dotdot(&decompressedData[0x28], 2);
- if (dot == '.' && dotdot == "..") {
- dinode_reached = true;
- }
-
- // Get folder and file names.
- bool end_reached = false;
- if (dinode_reached) {
- for (int j = 0; j < 0x10000; j += ent_size) { // Skip the first parent and child.
- Dirent dirent;
- std::memcpy(&dirent, &decompressedData[j], sizeof(dirent));
-
- // Stop here and continue the main loop
- if (dirent.ino == 0) {
- break;
- }
-
- ent_size = dirent.entsize;
- auto& table = fsTable.emplace_back();
- table.name = std::string(dirent.name, dirent.namelen);
- table.inode = dirent.ino;
- table.type = dirent.type;
-
- if (table.type == PFS_CURRENT_DIR) {
- current_dir = extractPaths[table.inode];
- }
- extractPaths[table.inode] = current_dir / std::filesystem::path(table.name);
-
- if (table.type == PFS_FILE || table.type == PFS_DIR) {
- if (table.type == PFS_DIR) { // Create dirs.
- std::filesystem::create_directory(extractPaths[table.inode]);
- }
- ndinode_counter++;
- if ((ndinode_counter + 1) == ndinode) // 1 for the image itself (root).
- end_reached = true;
- }
- }
- if (end_reached) {
- break;
- }
- }
- }
- return true;
-}
-
-void PKG::ExtractFiles(const int index) {
- int inode_number = fsTable[index].inode;
- int inode_type = fsTable[index].type;
- std::string inode_name = fsTable[index].name;
-
- if (inode_type == PFS_FILE) {
- int sector_loc = iNodeBuf[inode_number].loc;
- int nblocks = iNodeBuf[inode_number].Blocks;
- int bsize = iNodeBuf[inode_number].Size;
-
- Common::FS::IOFile inflated;
- inflated.Open(extractPaths[inode_number], Common::FS::FileAccessMode::Write);
-
- Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict.
- pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read);
-
- int size_decompressed = 0;
- std::vector compressedData;
- std::vector decompressedData(0x10000);
-
- u64 pfsc_buf_size = 0x11000; // extra 0x1000
- std::vector pfsc(pfsc_buf_size);
- std::vector pfs_decrypted(pfsc_buf_size);
-
- for (int j = 0; j < nblocks; j++) {
- u64 sectorOffset =
- sectorMap[sector_loc + j]; // offset into PFSC_image and not pfs_image.
- u64 sectorSize = sectorMap[sector_loc + j + 1] -
- sectorOffset; // indicates if data is compressed or not.
- u64 fileOffset = (pkgheader.pfs_image_offset + pfsc_offset + sectorOffset);
- u64 currentSector1 =
- (pfsc_offset + sectorOffset) / 0x1000; // block size is 0x1000 for xts decryption.
-
- int sectorOffsetMask = (sectorOffset + pfsc_offset) & 0xFFFFF000;
- int previousData = (sectorOffset + pfsc_offset) - sectorOffsetMask;
-
- pkgFile.Seek(fileOffset - previousData);
- pkgFile.Read(pfsc);
-
- PKG::crypto.decryptPFS(dataKey, tweakKey, pfsc, pfs_decrypted, currentSector1);
-
- compressedData.resize(sectorSize);
- std::memcpy(compressedData.data(), pfs_decrypted.data() + previousData, sectorSize);
-
- if (sectorSize == 0x10000) // Uncompressed data
- std::memcpy(decompressedData.data(), compressedData.data(), 0x10000);
- else if (sectorSize < 0x10000) // Compressed data
- DecompressPFSC(compressedData, decompressedData);
-
- size_decompressed += 0x10000;
-
- if (j < nblocks - 1) {
- inflated.WriteRaw(decompressedData.data(), decompressedData.size());
- } else {
- // This is to remove the zeros at the end of the file.
- const u32 write_size = decompressedData.size() - (size_decompressed - bsize);
- inflated.WriteRaw(decompressedData.data(), write_size);
- }
- }
- pkgFile.Close();
- inflated.Close();
- }
-}
diff --git a/src/core/file_format/pkg.h b/src/core/file_format/pkg.h
deleted file mode 100644
index a488a2df8..000000000
--- a/src/core/file_format/pkg.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include "common/endian.h"
-#include "core/crypto/crypto.h"
-#include "pfs.h"
-#include "trp.h"
-
-struct PKGHeader {
- u32_be magic; // Magic
- u32_be pkg_type;
- u32_be pkg_0x8; // unknown field
- u32_be pkg_file_count;
- u32_be pkg_table_entry_count;
- u16_be pkg_sc_entry_count;
- u16_be pkg_table_entry_count_2; // same as pkg_entry_count
- u32_be pkg_table_entry_offset; // file table offset
- u32_be pkg_sc_entry_data_size;
- u64_be pkg_body_offset; // offset of PKG entries
- u64_be pkg_body_size; // length of all PKG entries
- u64_be pkg_content_offset;
- u64_be pkg_content_size;
- u8 pkg_content_id[0x24]; // packages' content ID as a 36-byte string
- u8 pkg_padding[0xC]; // padding
- u32_be pkg_drm_type; // DRM type
- u32_be pkg_content_type; // Content type
- u32_be pkg_content_flags; // Content flags
- u32_be pkg_promote_size;
- u32_be pkg_version_date;
- u32_be pkg_version_hash;
- u32_be pkg_0x088;
- u32_be pkg_0x08C;
- u32_be pkg_0x090;
- u32_be pkg_0x094;
- u32_be pkg_iro_tag;
- u32_be pkg_drm_type_version;
-
- u8 pkg_zeroes_1[0x60];
-
- /* Digest table */
- u8 digest_entries1[0x20]; // sha256 digest for main entry 1
- u8 digest_entries2[0x20]; // sha256 digest for main entry 2
- u8 digest_table_digest[0x20]; // sha256 digest for digest table
- u8 digest_body_digest[0x20]; // sha256 digest for main table
-
- u8 pkg_zeroes_2[0x280];
-
- u32_be pkg_0x400;
-
- u32_be pfs_image_count; // count of PFS images
- u64_be pfs_image_flags; // PFS flags
- u64_be pfs_image_offset; // offset to start of external PFS image
- u64_be pfs_image_size; // size of external PFS image
- u64_be mount_image_offset;
- u64_be mount_image_size;
- u64_be pkg_size;
- u32_be pfs_signed_size;
- u32_be pfs_cache_size;
- u8 pfs_image_digest[0x20];
- u8 pfs_signed_digest[0x20];
- u64_be pfs_split_size_nth_0;
- u64_be pfs_split_size_nth_1;
-
- u8 pkg_zeroes_3[0xB50];
-
- u8 pkg_digest[0x20];
-};
-
-enum class PKGContentFlag {
- FIRST_PATCH = 0x100000,
- PATCHGO = 0x200000,
- REMASTER = 0x400000,
- PS_CLOUD = 0x800000,
- GD_AC = 0x2000000,
- NON_GAME = 0x4000000,
- UNKNOWN_0x8000000 = 0x8000000,
- SUBSEQUENT_PATCH = 0x40000000,
- DELTA_PATCH = 0x41000000,
- CUMULATIVE_PATCH = 0x60000000
-};
-
-struct PKGEntry {
- u32_be id; // File ID, useful for files without a filename entry
- u32_be filename_offset; // Offset into the filenames table (ID 0x200) where this file's name is
- // located
- u32_be flags1; // Flags including encrypted flag, etc
- u32_be flags2; // Flags including encryption key index, etc
- u32_be offset; // Offset into PKG to find the file
- u32_be size; // Size of the file
- u64_be padding; // blank padding
-};
-static_assert(sizeof(PKGEntry) == 32);
-
-class PKG {
-public:
- PKG();
- ~PKG();
-
- bool Open(const std::filesystem::path& filepath, std::string& failreason);
- void ExtractFiles(const int index);
- bool Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
- std::string& failreason);
-
- std::vector sfo;
-
- u32 GetNumberOfFiles() {
- return fsTable.size();
- }
-
- u64 GetPkgSize() {
- return pkgSize;
- }
-
- std::string GetPkgFlags() {
- return pkgFlags;
- }
-
- std::string_view GetTitleID() {
- return std::string_view(pkgTitleID, 9);
- }
-
- PKGHeader GetPkgHeader() {
- return pkgheader;
- }
-
- static bool isFlagSet(u32_be variable, PKGContentFlag flag) {
- return (variable) & static_cast(flag);
- }
-
- static constexpr std::array, 10> flagNames = {
- {{PKGContentFlag::FIRST_PATCH, "FIRST_PATCH"},
- {PKGContentFlag::PATCHGO, "PATCHGO"},
- {PKGContentFlag::REMASTER, "REMASTER"},
- {PKGContentFlag::PS_CLOUD, "PS_CLOUD"},
- {PKGContentFlag::GD_AC, "GD_AC"},
- {PKGContentFlag::NON_GAME, "NON_GAME"},
- {PKGContentFlag::UNKNOWN_0x8000000, "UNKNOWN_0x8000000"},
- {PKGContentFlag::SUBSEQUENT_PATCH, "SUBSEQUENT_PATCH"},
- {PKGContentFlag::DELTA_PATCH, "DELTA_PATCH"},
- {PKGContentFlag::CUMULATIVE_PATCH, "CUMULATIVE_PATCH"}}};
-
-private:
- Crypto crypto;
- TRP trp;
- u64 pkgSize = 0;
- char pkgTitleID[9];
- PKGHeader pkgheader;
- std::string pkgFlags;
-
- std::unordered_map extractPaths;
- std::vector fsTable;
- std::vector iNodeBuf;
- std::vector sectorMap;
- u64 pfsc_offset;
-
- std::array dk3_;
- std::array ivKey;
- std::array imgKey;
- std::array ekpfsKey;
- std::array dataKey;
- std::array tweakKey;
- std::vector decNp;
-
- std::filesystem::path pkgpath;
- std::filesystem::path current_dir;
- std::filesystem::path extract_path;
-};
diff --git a/src/core/file_format/pkg_type.cpp b/src/core/file_format/pkg_type.cpp
deleted file mode 100644
index 464f0b993..000000000
--- a/src/core/file_format/pkg_type.cpp
+++ /dev/null
@@ -1,638 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include
-#include "pkg_type.h"
-
-struct PkgEntryValue {
- u32 type;
- std::string_view name;
-
- operator u32() const noexcept {
- return type;
- }
-};
-
-constexpr static std::array PkgEntries = {{
- {0x0001, "digests"},
- {0x0010, "entry_keys"},
- {0x0020, "image_key"},
- {0x0080, "general_digests"},
- {0x0100, "metas"},
- {0x0200, "entry_names"},
- {0x0400, "license.dat"},
- {0x0401, "license.info"},
- {0x0402, "nptitle.dat"},
- {0x0403, "npbind.dat"},
- {0x0404, "selfinfo.dat"},
- {0x0406, "imageinfo.dat"},
- {0x0407, "target-deltainfo.dat"},
- {0x0408, "origin-deltainfo.dat"},
- {0x0409, "psreserved.dat"},
- {0x1000, "param.sfo"},
- {0x1001, "playgo-chunk.dat"},
- {0x1002, "playgo-chunk.sha"},
- {0x1003, "playgo-manifest.xml"},
- {0x1004, "pronunciation.xml"},
- {0x1005, "pronunciation.sig"},
- {0x1006, "pic1.png"},
- {0x1007, "pubtoolinfo.dat"},
- {0x1008, "app/playgo-chunk.dat"},
- {0x1009, "app/playgo-chunk.sha"},
- {0x100A, "app/playgo-manifest.xml"},
- {0x100B, "shareparam.json"},
- {0x100C, "shareoverlayimage.png"},
- {0x100D, "save_data.png"},
- {0x100E, "shareprivacyguardimage.png"},
- {0x1200, "icon0.png"},
- {0x1201, "icon0_00.png"},
- {0x1202, "icon0_01.png"},
- {0x1203, "icon0_02.png"},
- {0x1204, "icon0_03.png"},
- {0x1205, "icon0_04.png"},
- {0x1206, "icon0_05.png"},
- {0x1207, "icon0_06.png"},
- {0x1208, "icon0_07.png"},
- {0x1209, "icon0_08.png"},
- {0x120A, "icon0_09.png"},
- {0x120B, "icon0_10.png"},
- {0x120C, "icon0_11.png"},
- {0x120D, "icon0_12.png"},
- {0x120E, "icon0_13.png"},
- {0x120F, "icon0_14.png"},
- {0x1210, "icon0_15.png"},
- {0x1211, "icon0_16.png"},
- {0x1212, "icon0_17.png"},
- {0x1213, "icon0_18.png"},
- {0x1214, "icon0_19.png"},
- {0x1215, "icon0_20.png"},
- {0x1216, "icon0_21.png"},
- {0x1217, "icon0_22.png"},
- {0x1218, "icon0_23.png"},
- {0x1219, "icon0_24.png"},
- {0x121A, "icon0_25.png"},
- {0x121B, "icon0_26.png"},
- {0x121C, "icon0_27.png"},
- {0x121D, "icon0_28.png"},
- {0x121E, "icon0_29.png"},
- {0x121F, "icon0_30.png"},
- {0x1220, "pic0.png"},
- {0x1240, "snd0.at9"},
- {0x1241, "pic1_00.png"},
- {0x1242, "pic1_01.png"},
- {0x1243, "pic1_02.png"},
- {0x1244, "pic1_03.png"},
- {0x1245, "pic1_04.png"},
- {0x1246, "pic1_05.png"},
- {0x1247, "pic1_06.png"},
- {0x1248, "pic1_07.png"},
- {0x1249, "pic1_08.png"},
- {0x124A, "pic1_09.png"},
- {0x124B, "pic1_10.png"},
- {0x124C, "pic1_11.png"},
- {0x124D, "pic1_12.png"},
- {0x124E, "pic1_13.png"},
- {0x124F, "pic1_14.png"},
- {0x1250, "pic1_15.png"},
- {0x1251, "pic1_16.png"},
- {0x1252, "pic1_17.png"},
- {0x1253, "pic1_18.png"},
- {0x1254, "pic1_19.png"},
- {0x1255, "pic1_20.png"},
- {0x1256, "pic1_21.png"},
- {0x1257, "pic1_22.png"},
- {0x1258, "pic1_23.png"},
- {0x1259, "pic1_24.png"},
- {0x125A, "pic1_25.png"},
- {0x125B, "pic1_26.png"},
- {0x125C, "pic1_27.png"},
- {0x125D, "pic1_28.png"},
- {0x125E, "pic1_29.png"},
- {0x125F, "pic1_30.png"},
- {0x1260, "changeinfo/changeinfo.xml"},
- {0x1261, "changeinfo/changeinfo_00.xml"},
- {0x1262, "changeinfo/changeinfo_01.xml"},
- {0x1263, "changeinfo/changeinfo_02.xml"},
- {0x1264, "changeinfo/changeinfo_03.xml"},
- {0x1265, "changeinfo/changeinfo_04.xml"},
- {0x1266, "changeinfo/changeinfo_05.xml"},
- {0x1267, "changeinfo/changeinfo_06.xml"},
- {0x1268, "changeinfo/changeinfo_07.xml"},
- {0x1269, "changeinfo/changeinfo_08.xml"},
- {0x126A, "changeinfo/changeinfo_09.xml"},
- {0x126B, "changeinfo/changeinfo_10.xml"},
- {0x126C, "changeinfo/changeinfo_11.xml"},
- {0x126D, "changeinfo/changeinfo_12.xml"},
- {0x126E, "changeinfo/changeinfo_13.xml"},
- {0x126F, "changeinfo/changeinfo_14.xml"},
- {0x1270, "changeinfo/changeinfo_15.xml"},
- {0x1271, "changeinfo/changeinfo_16.xml"},
- {0x1272, "changeinfo/changeinfo_17.xml"},
- {0x1273, "changeinfo/changeinfo_18.xml"},
- {0x1274, "changeinfo/changeinfo_19.xml"},
- {0x1275, "changeinfo/changeinfo_20.xml"},
- {0x1276, "changeinfo/changeinfo_21.xml"},
- {0x1277, "changeinfo/changeinfo_22.xml"},
- {0x1278, "changeinfo/changeinfo_23.xml"},
- {0x1279, "changeinfo/changeinfo_24.xml"},
- {0x127A, "changeinfo/changeinfo_25.xml"},
- {0x127B, "changeinfo/changeinfo_26.xml"},
- {0x127C, "changeinfo/changeinfo_27.xml"},
- {0x127D, "changeinfo/changeinfo_28.xml"},
- {0x127E, "changeinfo/changeinfo_29.xml"},
- {0x127F, "changeinfo/changeinfo_30.xml"},
- {0x1280, "icon0.dds"},
- {0x1281, "icon0_00.dds"},
- {0x1282, "icon0_01.dds"},
- {0x1283, "icon0_02.dds"},
- {0x1284, "icon0_03.dds"},
- {0x1285, "icon0_04.dds"},
- {0x1286, "icon0_05.dds"},
- {0x1287, "icon0_06.dds"},
- {0x1288, "icon0_07.dds"},
- {0x1289, "icon0_08.dds"},
- {0x128A, "icon0_09.dds"},
- {0x128B, "icon0_10.dds"},
- {0x128C, "icon0_11.dds"},
- {0x128D, "icon0_12.dds"},
- {0x128E, "icon0_13.dds"},
- {0x128F, "icon0_14.dds"},
- {0x1290, "icon0_15.dds"},
- {0x1291, "icon0_16.dds"},
- {0x1292, "icon0_17.dds"},
- {0x1293, "icon0_18.dds"},
- {0x1294, "icon0_19.dds"},
- {0x1295, "icon0_20.dds"},
- {0x1296, "icon0_21.dds"},
- {0x1297, "icon0_22.dds"},
- {0x1298, "icon0_23.dds"},
- {0x1299, "icon0_24.dds"},
- {0x129A, "icon0_25.dds"},
- {0x129B, "icon0_26.dds"},
- {0x129C, "icon0_27.dds"},
- {0x129D, "icon0_28.dds"},
- {0x129E, "icon0_29.dds"},
- {0x129F, "icon0_30.dds"},
- {0x12A0, "pic0.dds"},
- {0x12C0, "pic1.dds"},
- {0x12C1, "pic1_00.dds"},
- {0x12C2, "pic1_01.dds"},
- {0x12C3, "pic1_02.dds"},
- {0x12C4, "pic1_03.dds"},
- {0x12C5, "pic1_04.dds"},
- {0x12C6, "pic1_05.dds"},
- {0x12C7, "pic1_06.dds"},
- {0x12C8, "pic1_07.dds"},
- {0x12C9, "pic1_08.dds"},
- {0x12CA, "pic1_09.dds"},
- {0x12CB, "pic1_10.dds"},
- {0x12CC, "pic1_11.dds"},
- {0x12CD, "pic1_12.dds"},
- {0x12CE, "pic1_13.dds"},
- {0x12CF, "pic1_14.dds"},
- {0x12D0, "pic1_15.dds"},
- {0x12D1, "pic1_16.dds"},
- {0x12D2, "pic1_17.dds"},
- {0x12D3, "pic1_18.dds"},
- {0x12D4, "pic1_19.dds"},
- {0x12D5, "pic1_20.dds"},
- {0x12D6, "pic1_21.dds"},
- {0x12D7, "pic1_22.dds"},
- {0x12D8, "pic1_23.dds"},
- {0x12D9, "pic1_24.dds"},
- {0x12DA, "pic1_25.dds"},
- {0x12DB, "pic1_26.dds"},
- {0x12DC, "pic1_27.dds"},
- {0x12DD, "pic1_28.dds"},
- {0x12DE, "pic1_29.dds"},
- {0x12DF, "pic1_30.dds"},
- {0x1400, "trophy/trophy00.trp"},
- {0x1401, "trophy/trophy01.trp"},
- {0x1402, "trophy/trophy02.trp"},
- {0x1403, "trophy/trophy03.trp"},
- {0x1404, "trophy/trophy04.trp"},
- {0x1405, "trophy/trophy05.trp"},
- {0x1406, "trophy/trophy06.trp"},
- {0x1407, "trophy/trophy07.trp"},
- {0x1408, "trophy/trophy08.trp"},
- {0x1409, "trophy/trophy09.trp"},
- {0x140A, "trophy/trophy10.trp"},
- {0x140B, "trophy/trophy11.trp"},
- {0x140C, "trophy/trophy12.trp"},
- {0x140D, "trophy/trophy13.trp"},
- {0x140E, "trophy/trophy14.trp"},
- {0x140F, "trophy/trophy15.trp"},
- {0x1410, "trophy/trophy16.trp"},
- {0x1411, "trophy/trophy17.trp"},
- {0x1412, "trophy/trophy18.trp"},
- {0x1413, "trophy/trophy19.trp"},
- {0x1414, "trophy/trophy20.trp"},
- {0x1415, "trophy/trophy21.trp"},
- {0x1416, "trophy/trophy22.trp"},
- {0x1417, "trophy/trophy23.trp"},
- {0x1418, "trophy/trophy24.trp"},
- {0x1419, "trophy/trophy25.trp"},
- {0x141A, "trophy/trophy26.trp"},
- {0x141B, "trophy/trophy27.trp"},
- {0x141C, "trophy/trophy28.trp"},
- {0x141D, "trophy/trophy29.trp"},
- {0x141E, "trophy/trophy30.trp"},
- {0x141F, "trophy/trophy31.trp"},
- {0x1420, "trophy/trophy32.trp"},
- {0x1421, "trophy/trophy33.trp"},
- {0x1422, "trophy/trophy34.trp"},
- {0x1423, "trophy/trophy35.trp"},
- {0x1424, "trophy/trophy36.trp"},
- {0x1425, "trophy/trophy37.trp"},
- {0x1426, "trophy/trophy38.trp"},
- {0x1427, "trophy/trophy39.trp"},
- {0x1428, "trophy/trophy40.trp"},
- {0x1429, "trophy/trophy41.trp"},
- {0x142A, "trophy/trophy42.trp"},
- {0x142B, "trophy/trophy43.trp"},
- {0x142C, "trophy/trophy44.trp"},
- {0x142D, "trophy/trophy45.trp"},
- {0x142E, "trophy/trophy46.trp"},
- {0x142F, "trophy/trophy47.trp"},
- {0x1430, "trophy/trophy48.trp"},
- {0x1431, "trophy/trophy49.trp"},
- {0x1432, "trophy/trophy50.trp"},
- {0x1433, "trophy/trophy51.trp"},
- {0x1434, "trophy/trophy52.trp"},
- {0x1435, "trophy/trophy53.trp"},
- {0x1436, "trophy/trophy54.trp"},
- {0x1437, "trophy/trophy55.trp"},
- {0x1438, "trophy/trophy56.trp"},
- {0x1439, "trophy/trophy57.trp"},
- {0x143A, "trophy/trophy58.trp"},
- {0x143B, "trophy/trophy59.trp"},
- {0x143C, "trophy/trophy60.trp"},
- {0x143D, "trophy/trophy61.trp"},
- {0x143E, "trophy/trophy62.trp"},
- {0x143F, "trophy/trophy63.trp"},
- {0x1440, "trophy/trophy64.trp"},
- {0x1441, "trophy/trophy65.trp"},
- {0x1442, "trophy/trophy66.trp"},
- {0x1443, "trophy/trophy67.trp"},
- {0x1444, "trophy/trophy68.trp"},
- {0x1445, "trophy/trophy69.trp"},
- {0x1446, "trophy/trophy70.trp"},
- {0x1447, "trophy/trophy71.trp"},
- {0x1448, "trophy/trophy72.trp"},
- {0x1449, "trophy/trophy73.trp"},
- {0x144A, "trophy/trophy74.trp"},
- {0x144B, "trophy/trophy75.trp"},
- {0x144C, "trophy/trophy76.trp"},
- {0x144D, "trophy/trophy77.trp"},
- {0x144E, "trophy/trophy78.trp"},
- {0x144F, "trophy/trophy79.trp"},
- {0x1450, "trophy/trophy80.trp"},
- {0x1451, "trophy/trophy81.trp"},
- {0x1452, "trophy/trophy82.trp"},
- {0x1453, "trophy/trophy83.trp"},
- {0x1454, "trophy/trophy84.trp"},
- {0x1455, "trophy/trophy85.trp"},
- {0x1456, "trophy/trophy86.trp"},
- {0x1457, "trophy/trophy87.trp"},
- {0x1458, "trophy/trophy88.trp"},
- {0x1459, "trophy/trophy89.trp"},
- {0x145A, "trophy/trophy90.trp"},
- {0x145B, "trophy/trophy91.trp"},
- {0x145C, "trophy/trophy92.trp"},
- {0x145D, "trophy/trophy93.trp"},
- {0x145E, "trophy/trophy94.trp"},
- {0x145F, "trophy/trophy95.trp"},
- {0x1460, "trophy/trophy96.trp"},
- {0x1461, "trophy/trophy97.trp"},
- {0x1462, "trophy/trophy98.trp"},
- {0x1463, "trophy/trophy99.trp"},
- {0x1600, "keymap_rp/001.png"},
- {0x1601, "keymap_rp/002.png"},
- {0x1602, "keymap_rp/003.png"},
- {0x1603, "keymap_rp/004.png"},
- {0x1604, "keymap_rp/005.png"},
- {0x1605, "keymap_rp/006.png"},
- {0x1606, "keymap_rp/007.png"},
- {0x1607, "keymap_rp/008.png"},
- {0x1608, "keymap_rp/009.png"},
- {0x1609, "keymap_rp/010.png"},
- {0x1610, "keymap_rp/00/001.png"},
- {0x1611, "keymap_rp/00/002.png"},
- {0x1612, "keymap_rp/00/003.png"},
- {0x1613, "keymap_rp/00/004.png"},
- {0x1614, "keymap_rp/00/005.png"},
- {0x1615, "keymap_rp/00/006.png"},
- {0x1616, "keymap_rp/00/007.png"},
- {0x1617, "keymap_rp/00/008.png"},
- {0x1618, "keymap_rp/00/009.png"},
- {0x1619, "keymap_rp/00/010.png"},
- {0x1620, "keymap_rp/01/001.png"},
- {0x1621, "keymap_rp/01/002.png"},
- {0x1622, "keymap_rp/01/003.png"},
- {0x1623, "keymap_rp/01/004.png"},
- {0x1624, "keymap_rp/01/005.png"},
- {0x1625, "keymap_rp/01/006.png"},
- {0x1626, "keymap_rp/01/007.png"},
- {0x1627, "keymap_rp/01/008.png"},
- {0x1628, "keymap_rp/01/009.png"},
- {0x1629, "keymap_rp/01/010.png"},
- {0x1630, "keymap_rp/02/001.png"},
- {0x1631, "keymap_rp/02/002.png"},
- {0x1632, "keymap_rp/02/003.png"},
- {0x1633, "keymap_rp/02/004.png"},
- {0x1634, "keymap_rp/02/005.png"},
- {0x1635, "keymap_rp/02/006.png"},
- {0x1636, "keymap_rp/02/007.png"},
- {0x1637, "keymap_rp/02/008.png"},
- {0x1638, "keymap_rp/02/009.png"},
- {0x1639, "keymap_rp/02/010.png"},
- {0x1640, "keymap_rp/03/001.png"},
- {0x1641, "keymap_rp/03/002.png"},
- {0x1642, "keymap_rp/03/003.png"},
- {0x1643, "keymap_rp/03/004.png"},
- {0x1644, "keymap_rp/03/005.png"},
- {0x1645, "keymap_rp/03/006.png"},
- {0x1646, "keymap_rp/03/007.png"},
- {0x1647, "keymap_rp/03/008.png"},
- {0x1648, "keymap_rp/03/0010.png"},
- {0x1650, "keymap_rp/04/001.png"},
- {0x1651, "keymap_rp/04/002.png"},
- {0x1652, "keymap_rp/04/003.png"},
- {0x1653, "keymap_rp/04/004.png"},
- {0x1654, "keymap_rp/04/005.png"},
- {0x1655, "keymap_rp/04/006.png"},
- {0x1656, "keymap_rp/04/007.png"},
- {0x1657, "keymap_rp/04/008.png"},
- {0x1658, "keymap_rp/04/009.png"},
- {0x1659, "keymap_rp/04/010.png"},
- {0x1660, "keymap_rp/05/001.png"},
- {0x1661, "keymap_rp/05/002.png"},
- {0x1662, "keymap_rp/05/003.png"},
- {0x1663, "keymap_rp/05/004.png"},
- {0x1664, "keymap_rp/05/005.png"},
- {0x1665, "keymap_rp/05/006.png"},
- {0x1666, "keymap_rp/05/007.png"},
- {0x1667, "keymap_rp/05/008.png"},
- {0x1668, "keymap_rp/05/009.png"},
- {0x1669, "keymap_rp/05/010.png"},
- {0x1670, "keymap_rp/06/001.png"},
- {0x1671, "keymap_rp/06/002.png"},
- {0x1672, "keymap_rp/06/003.png"},
- {0x1673, "keymap_rp/06/004.png"},
- {0x1674, "keymap_rp/06/005.png"},
- {0x1675, "keymap_rp/06/006.png"},
- {0x1676, "keymap_rp/06/007.png"},
- {0x1677, "keymap_rp/06/008.png"},
- {0x1678, "keymap_rp/06/009.png"},
- {0x1679, "keymap_rp/06/010.png"},
- {0x1680, "keymap_rp/07/001.png"},
- {0x1681, "keymap_rp/07/002.png"},
- {0x1682, "keymap_rp/07/003.png"},
- {0x1683, "keymap_rp/07/004.png"},
- {0x1684, "keymap_rp/07/005.png"},
- {0x1685, "keymap_rp/07/006.png"},
- {0x1686, "keymap_rp/07/007.png"},
- {0x1687, "keymap_rp/07/008.png"},
- {0x1688, "keymap_rp/07/009.png"},
- {0x1689, "keymap_rp/07/010.png"},
- {0x1690, "keymap_rp/08/001.png"},
- {0x1691, "keymap_rp/08/002.png"},
- {0x1692, "keymap_rp/08/003.png"},
- {0x1693, "keymap_rp/08/004.png"},
- {0x1694, "keymap_rp/08/005.png"},
- {0x1695, "keymap_rp/08/006.png"},
- {0x1696, "keymap_rp/08/007.png"},
- {0x1697, "keymap_rp/08/008.png"},
- {0x1698, "keymap_rp/08/009.png"},
- {0x1699, "keymap_rp/08/010.png"},
- {0x16A0, "keymap_rp/09/001.png"},
- {0x16A1, "keymap_rp/09/002.png"},
- {0x16A2, "keymap_rp/09/003.png"},
- {0x16A3, "keymap_rp/09/004.png"},
- {0x16A4, "keymap_rp/09/005.png"},
- {0x16A5, "keymap_rp/09/006.png"},
- {0x16A6, "keymap_rp/09/007.png"},
- {0x16A7, "keymap_rp/09/008.png"},
- {0x16A8, "keymap_rp/09/009.png"},
- {0x16A9, "keymap_rp/09/010.png"},
- {0x16B0, "keymap_rp/10/001.png"},
- {0x16B1, "keymap_rp/10/002.png"},
- {0x16B2, "keymap_rp/10/003.png"},
- {0x16B3, "keymap_rp/10/004.png"},
- {0x16B4, "keymap_rp/10/005.png"},
- {0x16B5, "keymap_rp/10/006.png"},
- {0x16B6, "keymap_rp/10/007.png"},
- {0x16B7, "keymap_rp/10/008.png"},
- {0x16B8, "keymap_rp/10/009.png"},
- {0x16B9, "keymap_rp/10/010.png"},
- {0x16C0, "keymap_rp/11/001.png"},
- {0x16C1, "keymap_rp/11/002.png"},
- {0x16C2, "keymap_rp/11/003.png"},
- {0x16C3, "keymap_rp/11/004.png"},
- {0x16C4, "keymap_rp/11/005.png"},
- {0x16C5, "keymap_rp/11/006.png"},
- {0x16C6, "keymap_rp/11/007.png"},
- {0x16C7, "keymap_rp/11/008.png"},
- {0x16C8, "keymap_rp/11/009.png"},
- {0x16C9, "keymap_rp/11/010.png"},
- {0x16D0, "keymap_rp/12/001.png"},
- {0x16D1, "keymap_rp/12/002.png"},
- {0x16D2, "keymap_rp/12/003.png"},
- {0x16D3, "keymap_rp/12/004.png"},
- {0x16D4, "keymap_rp/12/005.png"},
- {0x16D5, "keymap_rp/12/006.png"},
- {0x16D6, "keymap_rp/12/007.png"},
- {0x16D7, "keymap_rp/12/008.png"},
- {0x16D8, "keymap_rp/12/009.png"},
- {0x16D9, "keymap_rp/12/010.png"},
- {0x16E0, "keymap_rp/13/001.png"},
- {0x16E1, "keymap_rp/13/002.png"},
- {0x16E2, "keymap_rp/13/003.png"},
- {0x16E3, "keymap_rp/13/004.png"},
- {0x16E4, "keymap_rp/13/005.png"},
- {0x16E5, "keymap_rp/13/006.png"},
- {0x16E6, "keymap_rp/13/007.png"},
- {0x16E7, "keymap_rp/13/008.png"},
- {0x16E8, "keymap_rp/13/009.png"},
- {0x16E9, "keymap_rp/13/010.png"},
- {0x16F0, "keymap_rp/14/001.png"},
- {0x16F1, "keymap_rp/14/002.png"},
- {0x16F2, "keymap_rp/14/003.png"},
- {0x16F3, "keymap_rp/14/004.png"},
- {0x16F4, "keymap_rp/14/005.png"},
- {0x16F5, "keymap_rp/14/006.png"},
- {0x16F6, "keymap_rp/14/007.png"},
- {0x16F7, "keymap_rp/14/008.png"},
- {0x16F8, "keymap_rp/14/009.png"},
- {0x16F9, "keymap_rp/14/010.png"},
- {0x1700, "keymap_rp/15/001.png"},
- {0x1701, "keymap_rp/15/002.png"},
- {0x1702, "keymap_rp/15/003.png"},
- {0x1703, "keymap_rp/15/004.png"},
- {0x1704, "keymap_rp/15/005.png"},
- {0x1705, "keymap_rp/15/006.png"},
- {0x1706, "keymap_rp/15/007.png"},
- {0x1707, "keymap_rp/15/008.png"},
- {0x1708, "keymap_rp/15/009.png"},
- {0x1709, "keymap_rp/15/010.png"},
- {0x1710, "keymap_rp/16/001.png"},
- {0x1711, "keymap_rp/16/002.png"},
- {0x1712, "keymap_rp/16/003.png"},
- {0x1713, "keymap_rp/16/004.png"},
- {0x1714, "keymap_rp/16/005.png"},
- {0x1715, "keymap_rp/16/006.png"},
- {0x1716, "keymap_rp/16/007.png"},
- {0x1717, "keymap_rp/16/008.png"},
- {0x1718, "keymap_rp/16/009.png"},
- {0x1719, "keymap_rp/16/010.png"},
- {0x1720, "keymap_rp/17/001.png"},
- {0x1721, "keymap_rp/17/002.png"},
- {0x1722, "keymap_rp/17/003.png"},
- {0x1723, "keymap_rp/17/004.png"},
- {0x1724, "keymap_rp/17/005.png"},
- {0x1725, "keymap_rp/17/006.png"},
- {0x1726, "keymap_rp/17/007.png"},
- {0x1727, "keymap_rp/17/008.png"},
- {0x1728, "keymap_rp/17/009.png"},
- {0x1729, "keymap_rp/17/010.png"},
- {0x1730, "keymap_rp/18/001.png"},
- {0x1731, "keymap_rp/18/002.png"},
- {0x1732, "keymap_rp/18/003.png"},
- {0x1733, "keymap_rp/18/004.png"},
- {0x1734, "keymap_rp/18/005.png"},
- {0x1735, "keymap_rp/18/006.png"},
- {0x1736, "keymap_rp/18/007.png"},
- {0x1737, "keymap_rp/18/008.png"},
- {0x1738, "keymap_rp/18/009.png"},
- {0x1739, "keymap_rp/18/010.png"},
- {0x1740, "keymap_rp/19/001.png"},
- {0x1741, "keymap_rp/19/002.png"},
- {0x1742, "keymap_rp/19/003.png"},
- {0x1743, "keymap_rp/19/004.png"},
- {0x1744, "keymap_rp/19/005.png"},
- {0x1745, "keymap_rp/19/006.png"},
- {0x1746, "keymap_rp/19/007.png"},
- {0x1747, "keymap_rp/19/008.png"},
- {0x1748, "keymap_rp/19/009.png"},
- {0x1749, "keymap_rp/19/010.png"},
- {0x1750, "keymap_rp/20/001.png"},
- {0x1751, "keymap_rp/20/002.png"},
- {0x1752, "keymap_rp/20/003.png"},
- {0x1753, "keymap_rp/20/004.png"},
- {0x1754, "keymap_rp/20/005.png"},
- {0x1755, "keymap_rp/20/006.png"},
- {0x1756, "keymap_rp/20/007.png"},
- {0x1757, "keymap_rp/20/008.png"},
- {0x1758, "keymap_rp/20/009.png"},
- {0x1759, "keymap_rp/20/010.png"},
- {0x1760, "keymap_rp/21/001.png"},
- {0x1761, "keymap_rp/21/002.png"},
- {0x1762, "keymap_rp/21/003.png"},
- {0x1763, "keymap_rp/21/004.png"},
- {0x1764, "keymap_rp/21/005.png"},
- {0x1765, "keymap_rp/21/006.png"},
- {0x1766, "keymap_rp/21/007.png"},
- {0x1767, "keymap_rp/21/008.png"},
- {0x1768, "keymap_rp/21/009.png"},
- {0x1769, "keymap_rp/21/010.png"},
- {0x1770, "keymap_rp/22/001.png"},
- {0x1771, "keymap_rp/22/002.png"},
- {0x1772, "keymap_rp/22/003.png"},
- {0x1773, "keymap_rp/22/004.png"},
- {0x1774, "keymap_rp/22/005.png"},
- {0x1775, "keymap_rp/22/006.png"},
- {0x1776, "keymap_rp/22/007.png"},
- {0x1777, "keymap_rp/22/008.png"},
- {0x1778, "keymap_rp/22/009.png"},
- {0x1779, "keymap_rp/22/010.png"},
- {0x1780, "keymap_rp/23/001.png"},
- {0x1781, "keymap_rp/23/002.png"},
- {0x1782, "keymap_rp/23/003.png"},
- {0x1783, "keymap_rp/23/004.png"},
- {0x1784, "keymap_rp/23/005.png"},
- {0x1785, "keymap_rp/23/006.png"},
- {0x1786, "keymap_rp/23/007.png"},
- {0x1787, "keymap_rp/23/008.png"},
- {0x1788, "keymap_rp/23/009.png"},
- {0x1789, "keymap_rp/23/010.png"},
- {0x1790, "keymap_rp/24/001.png"},
- {0x1791, "keymap_rp/24/002.png"},
- {0x1792, "keymap_rp/24/003.png"},
- {0x1793, "keymap_rp/24/004.png"},
- {0x1794, "keymap_rp/24/005.png"},
- {0x1795, "keymap_rp/24/006.png"},
- {0x1796, "keymap_rp/24/007.png"},
- {0x1797, "keymap_rp/24/008.png"},
- {0x1798, "keymap_rp/24/009.png"},
- {0x1799, "keymap_rp/24/010.png"},
- {0x17A0, "keymap_rp/25/001.png"},
- {0x17A1, "keymap_rp/25/002.png"},
- {0x17A2, "keymap_rp/25/003.png"},
- {0x17A3, "keymap_rp/25/004.png"},
- {0x17A4, "keymap_rp/25/005.png"},
- {0x17A5, "keymap_rp/25/006.png"},
- {0x17A6, "keymap_rp/25/007.png"},
- {0x17A7, "keymap_rp/25/008.png"},
- {0x17A8, "keymap_rp/25/009.png"},
- {0x17A9, "keymap_rp/25/010.png"},
- {0x17B0, "keymap_rp/26/001.png"},
- {0x17B1, "keymap_rp/26/002.png"},
- {0x17B2, "keymap_rp/26/003.png"},
- {0x17B3, "keymap_rp/26/004.png"},
- {0x17B4, "keymap_rp/26/005.png"},
- {0x17B5, "keymap_rp/26/006.png"},
- {0x17B6, "keymap_rp/26/007.png"},
- {0x17B7, "keymap_rp/26/008.png"},
- {0x17B8, "keymap_rp/26/009.png"},
- {0x17B9, "keymap_rp/26/010.png"},
- {0x17C0, "keymap_rp/27/001.png"},
- {0x17C1, "keymap_rp/27/002.png"},
- {0x17C2, "keymap_rp/27/003.png"},
- {0x17C3, "keymap_rp/27/004.png"},
- {0x17C4, "keymap_rp/27/005.png"},
- {0x17C5, "keymap_rp/27/006.png"},
- {0x17C6, "keymap_rp/27/007.png"},
- {0x17C7, "keymap_rp/27/008.png"},
- {0x17C8, "keymap_rp/27/009.png"},
- {0x17C9, "keymap_rp/27/010.png"},
- {0x17D0, "keymap_rp/28/001.png"},
- {0x17D1, "keymap_rp/28/002.png"},
- {0x17D2, "keymap_rp/28/003.png"},
- {0x17D3, "keymap_rp/28/004.png"},
- {0x17D4, "keymap_rp/28/005.png"},
- {0x17D5, "keymap_rp/28/006.png"},
- {0x17D6, "keymap_rp/28/007.png"},
- {0x17D7, "keymap_rp/28/008.png"},
- {0x17D8, "keymap_rp/28/009.png"},
- {0x17D9, "keymap_rp/28/010.png"},
- {0x17E0, "keymap_rp/29/001.png"},
- {0x17E1, "keymap_rp/29/002.png"},
- {0x17E2, "keymap_rp/29/003.png"},
- {0x17E3, "keymap_rp/29/004.png"},
- {0x17E4, "keymap_rp/29/005.png"},
- {0x17E5, "keymap_rp/29/006.png"},
- {0x17E6, "keymap_rp/29/007.png"},
- {0x17E7, "keymap_rp/29/008.png"},
- {0x17E8, "keymap_rp/29/009.png"},
- {0x17E9, "keymap_rp/29/010.png"},
- {0x17F0, "keymap_rp/30/001.png"},
- {0x17F1, "keymap_rp/30/002.png"},
- {0x17F2, "keymap_rp/30/003.png"},
- {0x17F3, "keymap_rp/30/004.png"},
- {0x17F4, "keymap_rp/30/005.png"},
- {0x17F5, "keymap_rp/30/006.png"},
- {0x17F6, "keymap_rp/30/007.png"},
- {0x17F7, "keymap_rp/30/008.png"},
- {0x17F8, "keymap_rp/30/009.png"},
- {0x17F9, "keymap_rp/30/010.png"},
-}};
-
-std::string_view GetEntryNameByType(u32 type) {
- const auto key = PkgEntryValue{type};
- const auto it = std::ranges::lower_bound(PkgEntries, key);
- if (it != PkgEntries.end() && it->type == type) {
- return it->name;
- }
- return "";
-}
diff --git a/src/core/file_format/pkg_type.h b/src/core/file_format/pkg_type.h
deleted file mode 100644
index 6b010e3a3..000000000
--- a/src/core/file_format/pkg_type.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include "common/types.h"
-
-/// Retrieves the PKG entry name from its type identifier.
-std::string_view GetEntryNameByType(u32 type);
diff --git a/src/core/file_format/trp.cpp b/src/core/file_format/trp.cpp
index d25c93c3f..311bd0b9d 100644
--- a/src/core/file_format/trp.cpp
+++ b/src/core/file_format/trp.cpp
@@ -1,10 +1,36 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include
+#include
+
#include "common/config.h"
#include "common/logging/log.h"
#include "common/path_util.h"
-#include "trp.h"
+#include "core/file_format/trp.h"
+
+static void DecryptEFSM(std::span trophyKey,
+ std::span NPcommID,
+ std::span efsmIv, std::span ciphertext,
+ std::span decrypted) {
+
+ // step 1: Encrypt NPcommID
+ CryptoPP::CBC_Mode::Encryption encrypt;
+
+ std::vector trophyIv(16, 0);
+ std::vector trpKey(16);
+
+ encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data());
+ encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
+
+ // step 2: decrypt efsm.
+ CryptoPP::CBC_Mode::Decryption decrypt;
+ decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
+
+ for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
+ decrypt.ProcessData(decrypted.data() + i, ciphertext.data() + i, CryptoPP::AES::BLOCKSIZE);
+ }
+}
TRP::TRP() = default;
TRP::~TRP() = default;
@@ -115,7 +141,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
return false;
}
file.Read(ESFM);
- crypto.decryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt
+ DecryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt
removePadding(XML);
std::string xml_name = entry.entry_name;
size_t pos = xml_name.find("ESFM");
diff --git a/src/core/file_format/trp.h b/src/core/file_format/trp.h
index aec129f0e..01207475b 100644
--- a/src/core/file_format/trp.h
+++ b/src/core/file_format/trp.h
@@ -7,7 +7,6 @@
#include "common/endian.h"
#include "common/io_file.h"
#include "common/types.h"
-#include "core/crypto/crypto.h"
struct TrpHeader {
u32_be magic; // (0xDCA24D00)
@@ -37,10 +36,9 @@ public:
void GetNPcommID(const std::filesystem::path& trophyPath, int index);
private:
- Crypto crypto;
std::vector NPcommID = std::vector(12);
std::array np_comm_id{};
std::array esfmIv{};
std::filesystem::path trpFilesPath;
static constexpr int iv_len = 16;
-};
\ No newline at end of file
+};
diff --git a/src/core/libraries/disc_map/disc_map.cpp b/src/core/libraries/disc_map/disc_map.cpp
index bb566a149..e8b40e624 100644
--- a/src/core/libraries/disc_map/disc_map.cpp
+++ b/src/core/libraries/disc_map/disc_map.cpp
@@ -9,29 +9,29 @@
namespace Libraries::DiscMap {
-int PS4_SYSV_ABI sceDiscMapGetPackageSize() {
- LOG_WARNING(Lib_DiscMap, "(DUMMY) called");
+int PS4_SYSV_ABI sceDiscMapGetPackageSize(s64 fflags, int* ret1, int* ret2) {
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
}
-int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD() {
- LOG_WARNING(Lib_DiscMap, "(DUMMY) called");
+int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD(char* path, s64 offset, s64 nbytes, int* ret) {
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
}
-int PS4_SYSV_ABI Func_7C980FFB0AA27E7A() {
- LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
+int PS4_SYSV_ABI Func_7C980FFB0AA27E7A(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
+ int* ret2) {
+ *flags = 0;
+ *ret1 = 0;
+ *ret2 = 0;
return ORBIS_OK;
}
-int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9() {
- LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
- return ORBIS_OK;
+int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
+ int* ret2) {
+ return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
}
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8() {
- LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
- return ORBIS_OK;
+ return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
}
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym) {
diff --git a/src/core/libraries/disc_map/disc_map.h b/src/core/libraries/disc_map/disc_map.h
index 08abee632..dc8b875ac 100644
--- a/src/core/libraries/disc_map/disc_map.h
+++ b/src/core/libraries/disc_map/disc_map.h
@@ -10,10 +10,12 @@ class SymbolsResolver;
}
namespace Libraries::DiscMap {
-int PS4_SYSV_ABI sceDiscMapGetPackageSize();
-int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD();
-int PS4_SYSV_ABI Func_7C980FFB0AA27E7A();
-int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9();
+int PS4_SYSV_ABI sceDiscMapGetPackageSize(s64 fflags, int* ret1, int* ret2);
+int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD(char* path, s64 offset, s64 nbytes, int* ret);
+int PS4_SYSV_ABI Func_7C980FFB0AA27E7A(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
+ int* ret2);
+int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
+ int* ret2);
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8();
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym);
diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp
index 0150c11f5..3321559ed 100644
--- a/src/core/libraries/kernel/file_system.cpp
+++ b/src/core/libraries/kernel/file_system.cpp
@@ -18,6 +18,7 @@
#include "core/file_sys/fs.h"
#include "core/libraries/kernel/file_system.h"
#include "core/libraries/kernel/orbis_error.h"
+#include "core/libraries/kernel/posix_error.h"
#include "core/libraries/libs.h"
#include "core/memory.h"
#include "kernel.h"
@@ -57,7 +58,7 @@ static std::map available_device = {
namespace Libraries::Kernel {
-int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) {
+s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", raw_path, flags, mode);
auto* h = Common::Singleton::Instance();
auto* mnt = Common::Singleton::Instance();
@@ -99,7 +100,8 @@ int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) {
file->m_host_name = mnt->GetHostPath(file->m_guest_name);
if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist
h->DeleteHandle(handle);
- return ORBIS_KERNEL_ERROR_ENOTDIR;
+ *__Error() = POSIX_ENOENT;
+ return -1;
} else {
if (create) {
return handle; // dir already exists
@@ -116,61 +118,87 @@ int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) {
} else {
file->m_guest_name = path;
file->m_host_name = mnt->GetHostPath(file->m_guest_name);
+ bool exists = std::filesystem::exists(file->m_host_name);
int e = 0;
- if (read) {
- e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
- } else if (write && (create || truncate)) {
- e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
- } else if (write && create && append) { // CUSA04729 (appends app0/shaderlist.txt)
- e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
- } else if (rdwr) {
- if (create) { // Create an empty file first.
- Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write);
+
+ if (create) {
+ if (excl && exists) {
+ // Error if file exists
+ h->DeleteHandle(handle);
+ *__Error() = POSIX_EEXIST;
+ return -1;
}
- // RW, then scekernelWrite is called and savedata is written just fine now.
- e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
- } else if (write) {
- e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
- } else {
- UNREACHABLE();
- }
- if (e != 0) {
+ // Create file if it doesn't exist
+ Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write);
+ } else if (!exists) {
+ // File to open doesn't exist, return ENOENT
h->DeleteHandle(handle);
- return ErrnoToSceKernelError(e);
+ *__Error() = POSIX_ENOENT;
+ return -1;
+ }
+
+ if (read) {
+ // Read only
+ e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
+ } else if (write) {
+ // Write only
+ if (append) {
+ e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
+ } else {
+ e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
+ }
+ } else if (rdwr) {
+ // Read and write
+ if (append) {
+ e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
+ } else {
+ e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
+ }
+ } else {
+ // Invalid flags
+ *__Error() = POSIX_EINVAL;
+ return -1;
+ }
+
+ if (truncate && e == 0) {
+ // If the file was opened successfully and truncate was enabled, reduce size to 0
+ file->f.SetSize(0);
+ }
+
+ if (e != 0) {
+ // Open failed in platform-specific code, errno needs to be converted.
+ h->DeleteHandle(handle);
+ SetPosixErrno(e);
+ return -1;
}
}
file->is_opened = true;
return handle;
}
-int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) {
- LOG_INFO(Kernel_Fs, "posix open redirect to sceKernelOpen");
- int result = sceKernelOpen(path, flags, mode);
- // Posix calls different only for their return values
+s32 PS4_SYSV_ABI posix_open(const char* filename, s32 flags, u16 mode) {
+ return open(filename, flags, mode);
+}
+
+s32 PS4_SYSV_ABI sceKernelOpen(const char* path, s32 flags, /* SceKernelMode*/ u16 mode) {
+ s32 result = open(path, flags, mode);
if (result < 0) {
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-int PS4_SYSV_ABI open(const char* filename, const char* mode) {
- LOG_INFO(Kernel_Fs, "open redirect to sceKernelOpen");
- int result = sceKernelOpen(filename, ORBIS_KERNEL_O_RDWR, 0);
- if (result < 0) {
- return -1;
- }
- return result;
-}
-
-int PS4_SYSV_ABI sceKernelClose(int d) {
- if (d < 3) { // d probably hold an error code
- return ORBIS_KERNEL_ERROR_EPERM;
+s32 PS4_SYSV_ABI close(s32 fd) {
+ if (fd < 3) {
+ // This is technically possible, but it's usually caused by some stubbed function instead.
+ LOG_WARNING(Kernel_Fs, "called on an std handle, fd = {}", fd);
}
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
if (file->type == Core::FileSys::FileType::Regular) {
file->f.Close();
@@ -178,63 +206,54 @@ int PS4_SYSV_ABI sceKernelClose(int d) {
file->is_opened = false;
LOG_INFO(Kernel_Fs, "Closing {}", file->m_guest_name);
// FIXME: Lock file mutex before deleting it?
- h->DeleteHandle(d);
+ h->DeleteHandle(fd);
return ORBIS_OK;
}
-int PS4_SYSV_ABI posix_close(int d) {
- int result = sceKernelClose(d);
+s32 PS4_SYSV_ABI posix_close(s32 fd) {
+ return close(fd);
+}
+
+s32 PS4_SYSV_ABI sceKernelClose(s32 fd) {
+ s32 result = close(fd);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_close: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-s64 PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes) {
+s64 PS4_SYSV_ABI write(s32 fd, const void* buf, size_t nbytes) {
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->write(buf, nbytes);
+ s64 result = file->device->write(buf, nbytes);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
return file->f.WriteRaw(buf, nbytes);
}
-int PS4_SYSV_ABI sceKernelUnlink(const char* path) {
- if (path == nullptr) {
- return ORBIS_KERNEL_ERROR_EINVAL;
+s64 PS4_SYSV_ABI posix_write(s32 fd, const void* buf, size_t nbytes) {
+ return write(fd, buf, nbytes);
+}
+
+s64 PS4_SYSV_ABI sceKernelWrite(s32 fd, const void* buf, size_t nbytes) {
+ s64 result = write(fd, buf, nbytes);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
-
- auto* h = Common::Singleton::Instance();
- auto* mnt = Common::Singleton::Instance();
-
- bool ro = false;
- const auto host_path = mnt->GetHostPath(path, &ro);
- if (host_path.empty()) {
- return ORBIS_KERNEL_ERROR_EACCES;
- }
-
- if (ro) {
- return ORBIS_KERNEL_ERROR_EROFS;
- }
-
- if (std::filesystem::is_directory(host_path)) {
- return ORBIS_KERNEL_ERROR_EPERM;
- }
-
- auto* file = h->GetFile(host_path);
- if (file != nullptr) {
- file->f.Unlink();
- }
-
- LOG_INFO(Kernel_Fs, "Unlinked {}", path);
- return ORBIS_OK;
+ return result;
}
size_t ReadFile(Common::FS::IOFile& file, void* buf, size_t nbytes) {
@@ -246,58 +265,97 @@ size_t ReadFile(Common::FS::IOFile& file, void* buf, size_t nbytes) {
return file.ReadRaw(buf, nbytes);
}
-size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
+size_t PS4_SYSV_ABI readv(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- int r = file->device->readv(iov, iovcnt);
- if (r < 0) {
- ErrSceToPosix(r);
+ size_t result = file->device->readv(iov, iovcnt);
+ if (result < 0) {
+ ErrSceToPosix(result);
return -1;
}
- return r;
+ return result;
}
size_t total_read = 0;
- for (int i = 0; i < iovcnt; i++) {
+ for (s32 i = 0; i < iovcnt; i++) {
total_read += ReadFile(file->f, iov[i].iov_base, iov[i].iov_len);
}
return total_read;
}
-size_t PS4_SYSV_ABI _writev(int fd, const SceKernelIovec* iov, int iovcn) {
+size_t PS4_SYSV_ABI posix_readv(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
+ return readv(fd, iov, iovcnt);
+}
+
+size_t PS4_SYSV_ABI sceKernelReadv(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
+ size_t result = readv(fd, iov, iovcnt);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+size_t PS4_SYSV_ABI writev(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
auto* h = Common::Singleton::Instance();
auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->writev(iov, iovcn);
+ size_t result = file->device->writev(iov, iovcnt);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
size_t total_written = 0;
- for (int i = 0; i < iovcn; i++) {
+ for (s32 i = 0; i < iovcnt; i++) {
total_written += file->f.WriteRaw(iov[i].iov_base, iov[i].iov_len);
}
return total_written;
}
-s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
+size_t PS4_SYSV_ABI posix_writev(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
+ return writev(fd, iov, iovcnt);
+}
+
+size_t PS4_SYSV_ABI sceKernelWritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
+ size_t result = writev(fd, iov, iovcnt);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s64 PS4_SYSV_ABI posix_lseek(s32 fd, s64 offset, s32 whence) {
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->lseek(offset, whence);
+ s64 result = file->device->lseek(offset, whence);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
Common::FS::SeekOrigin origin{};
@@ -307,53 +365,82 @@ s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
origin = Common::FS::SeekOrigin::CurrentPosition;
} else if (whence == 2) {
origin = Common::FS::SeekOrigin::End;
+ } else if (whence == 3) {
+ origin = Common::FS::SeekOrigin::SeekHole;
+ } else if (whence == 4) {
+ origin = Common::FS::SeekOrigin::SeekData;
+ } else {
+ // whence parameter is invalid
+ *__Error() = POSIX_EINVAL;
+ return -1;
}
if (!file->f.Seek(offset, origin)) {
- LOG_CRITICAL(Kernel_Fs, "sceKernelLseek: failed to seek");
- return ORBIS_KERNEL_ERROR_EINVAL;
+ if (errno != 0) {
+ // Seek failed in platform-specific code, errno needs to be converted.
+ SetPosixErrno(errno);
+ return -1;
+ }
+ // Shouldn't be possible, but just in case.
+ return -1;
}
- return file->f.Tell();
-}
-s64 PS4_SYSV_ABI posix_lseek(int d, s64 offset, int whence) {
- s64 result = sceKernelLseek(d, offset, whence);
+ s64 result = file->f.Tell();
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_lseek: error = {}", result);
- ErrSceToPosix(result);
+ // Tell failed in platform-specific code, errno needs to be converted.
+ SetPosixErrno(errno);
return -1;
}
return result;
}
-s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
+s64 PS4_SYSV_ABI sceKernelLseek(s32 fd, s64 offset, s32 whence) {
+ s64 result = posix_lseek(fd, offset, whence);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s64 PS4_SYSV_ABI read(s32 fd, void* buf, size_t nbytes) {
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->read(buf, nbytes);
+ s64 result = file->device->read(buf, nbytes);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
return ReadFile(file->f, buf, nbytes);
}
-int PS4_SYSV_ABI posix_read(int d, void* buf, size_t nbytes) {
- int result = sceKernelRead(d, buf, nbytes);
+s64 PS4_SYSV_ABI posix_read(s32 fd, void* buf, size_t nbytes) {
+ return read(fd, buf, nbytes);
+}
+
+s64 PS4_SYSV_ABI sceKernelRead(s32 fd, void* buf, size_t nbytes) {
+ s64 result = read(fd, buf, nbytes);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_read: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) {
+s32 PS4_SYSV_ABI posix_mkdir(const char* path, u16 mode) {
LOG_INFO(Kernel_Fs, "path = {} mode = {}", path, mode);
if (path == nullptr) {
- return ORBIS_KERNEL_ERROR_EINVAL;
+ *__Error() = POSIX_ENOTDIR;
+ return -1;
}
auto* mnt = Common::Singleton::Instance();
@@ -361,88 +448,79 @@ int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) {
const auto dir_name = mnt->GetHostPath(path, &ro);
if (std::filesystem::exists(dir_name)) {
- return ORBIS_KERNEL_ERROR_EEXIST;
+ *__Error() = POSIX_EEXIST;
+ return -1;
}
if (ro) {
- return ORBIS_KERNEL_ERROR_EROFS;
+ *__Error() = POSIX_EROFS;
+ return -1;
}
// CUSA02456: path = /aotl after sceSaveDataMount(mode = 1)
std::error_code ec;
if (dir_name.empty() || !std::filesystem::create_directory(dir_name, ec)) {
- return ORBIS_KERNEL_ERROR_EIO;
+ *__Error() = POSIX_EIO;
+ return -1;
}
if (!std::filesystem::exists(dir_name)) {
- return ORBIS_KERNEL_ERROR_ENOENT;
+ *__Error() = POSIX_ENOENT;
+ return -1;
}
return ORBIS_OK;
}
-int PS4_SYSV_ABI posix_mkdir(const char* path, u16 mode) {
- int result = sceKernelMkdir(path, mode);
+s32 PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) {
+ s32 result = posix_mkdir(path, mode);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_mkdir: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-int PS4_SYSV_ABI sceKernelRmdir(const char* path) {
+s32 PS4_SYSV_ABI posix_rmdir(const char* path) {
auto* mnt = Common::Singleton::Instance();
bool ro = false;
const std::filesystem::path dir_name = mnt->GetHostPath(path, &ro);
- if (dir_name.empty()) {
- LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, permission denied",
- fmt::UTF(dir_name.u8string()));
- return ORBIS_KERNEL_ERROR_EACCES;
+ if (dir_name.empty() || !std::filesystem::is_directory(dir_name)) {
+ *__Error() = POSIX_ENOTDIR;
+ return -1;
}
if (ro) {
- LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, directory is read only",
- fmt::UTF(dir_name.u8string()));
- return ORBIS_KERNEL_ERROR_EROFS;
- }
-
- if (!std::filesystem::is_directory(dir_name)) {
- LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, path is not a directory",
- fmt::UTF(dir_name.u8string()));
- return ORBIS_KERNEL_ERROR_ENOTDIR;
+ *__Error() = POSIX_EROFS;
+ return -1;
}
if (!std::filesystem::exists(dir_name)) {
- LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, no such file or directory",
- fmt::UTF(dir_name.u8string()));
- return ORBIS_KERNEL_ERROR_ENOENT;
+ *__Error() = POSIX_ENOENT;
+ return -1;
}
std::error_code ec;
- int result = std::filesystem::remove_all(dir_name, ec);
+ s32 result = std::filesystem::remove_all(dir_name, ec);
- if (!ec) {
- LOG_INFO(Kernel_Fs, "Removed directory: {}", fmt::UTF(dir_name.u8string()));
- return ORBIS_OK;
+ if (ec) {
+ *__Error() = POSIX_EIO;
+ return -1;
}
- LOG_ERROR(Kernel_Fs, "Failed to remove directory: {}, error_code={}",
- fmt::UTF(dir_name.u8string()), ec.message());
- return ErrnoToSceKernelError(ec.value());
+ return ORBIS_OK;
}
-int PS4_SYSV_ABI posix_rmdir(const char* path) {
- int result = sceKernelRmdir(path);
+s32 PS4_SYSV_ABI sceKernelRmdir(const char* path) {
+ s32 result = posix_rmdir(path);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_rmdir: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) {
+s32 PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) {
LOG_INFO(Kernel_Fs, "(PARTIAL) path = {}", path);
auto* mnt = Common::Singleton::Instance();
bool ro = false;
@@ -451,7 +529,8 @@ int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) {
const bool is_dir = std::filesystem::is_directory(path_name);
const bool is_file = std::filesystem::is_regular_file(path_name);
if (!is_dir && !is_file) {
- return ORBIS_KERNEL_ERROR_ENOENT;
+ *__Error() = POSIX_ENOENT;
+ return -1;
}
if (std::filesystem::is_directory(path_name)) {
sb->st_mode = 0000777u | 0040000u;
@@ -461,7 +540,7 @@ int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) {
// TODO incomplete
} else {
sb->st_mode = 0000777u | 0100000u;
- sb->st_size = static_cast(std::filesystem::file_size(path_name));
+ sb->st_size = static_cast(std::filesystem::file_size(path_name));
sb->st_blksize = 512;
sb->st_blocks = (sb->st_size + 511) / 512;
// TODO incomplete
@@ -473,17 +552,16 @@ int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) {
return ORBIS_OK;
}
-int PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) {
- int result = sceKernelStat(path, sb);
+s32 PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) {
+ s32 result = posix_stat(path, sb);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_stat: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-int PS4_SYSV_ABI sceKernelCheckReachability(const char* path) {
+s32 PS4_SYSV_ABI sceKernelCheckReachability(const char* path) {
auto* mnt = Common::Singleton::Instance();
std::string_view guest_path{path};
for (const auto& prefix : available_device | std::views::keys) {
@@ -498,23 +576,165 @@ int PS4_SYSV_ABI sceKernelCheckReachability(const char* path) {
return ORBIS_OK;
}
-s64 PS4_SYSV_ABI sceKernelPreadv(int d, SceKernelIovec* iov, int iovcnt, s64 offset) {
- if (d < 3) {
- return ORBIS_KERNEL_ERROR_EPERM;
+s32 PS4_SYSV_ABI fstat(s32 fd, OrbisKernelStat* sb) {
+ LOG_INFO(Kernel_Fs, "(PARTIAL) fd = {}", fd);
+ if (sb == nullptr) {
+ *__Error() = POSIX_EFAULT;
+ return -1;
}
+ auto* h = Common::Singleton::Instance();
+ auto* file = h->GetFile(fd);
+ if (file == nullptr) {
+ *__Error() = POSIX_EBADF;
+ return -1;
+ }
+ std::memset(sb, 0, sizeof(OrbisKernelStat));
+
+ switch (file->type) {
+ case Core::FileSys::FileType::Device: {
+ s32 result = file->device->fstat(sb);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
+ }
+ case Core::FileSys::FileType::Regular: {
+ sb->st_mode = 0000777u | 0100000u;
+ sb->st_size = file->f.GetSize();
+ sb->st_blksize = 512;
+ sb->st_blocks = (sb->st_size + 511) / 512;
+ // TODO incomplete
+ break;
+ }
+ case Core::FileSys::FileType::Directory: {
+ sb->st_mode = 0000777u | 0040000u;
+ sb->st_size = 0;
+ sb->st_blksize = 512;
+ sb->st_blocks = 0;
+ // TODO incomplete
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI posix_fstat(s32 fd, OrbisKernelStat* sb) {
+ return fstat(fd, sb);
+}
+
+s32 PS4_SYSV_ABI sceKernelFstat(s32 fd, OrbisKernelStat* sb) {
+ s32 result = fstat(fd, sb);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s32 PS4_SYSV_ABI posix_ftruncate(s32 fd, s64 length) {
+ auto* h = Common::Singleton::Instance();
+ auto* file = h->GetFile(fd);
+
+ if (file == nullptr) {
+ *__Error() = POSIX_EBADF;
+ return -1;
+ }
+
+ if (file->type == Core::FileSys::FileType::Device) {
+ s32 result = file->device->ftruncate(length);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
+ }
+
+ if (file->m_host_name.empty()) {
+ *__Error() = POSIX_EACCES;
+ return -1;
+ }
+
+ file->f.SetSize(length);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceKernelFtruncate(s32 fd, s64 length) {
+ s32 result = posix_ftruncate(fd, length);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s32 PS4_SYSV_ABI posix_rename(const char* from, const char* to) {
+ auto* mnt = Common::Singleton::Instance();
+ bool ro = false;
+ const auto src_path = mnt->GetHostPath(from, &ro);
+ if (!std::filesystem::exists(src_path)) {
+ *__Error() = POSIX_ENOENT;
+ return -1;
+ }
+ if (ro) {
+ *__Error() = POSIX_EROFS;
+ return -1;
+ }
+ const auto dst_path = mnt->GetHostPath(to, &ro);
+ if (ro) {
+ *__Error() = POSIX_EROFS;
+ return -1;
+ }
+ const bool src_is_dir = std::filesystem::is_directory(src_path);
+ const bool dst_is_dir = std::filesystem::is_directory(dst_path);
+ if (src_is_dir && !dst_is_dir) {
+ *__Error() = POSIX_ENOTDIR;
+ return -1;
+ }
+ if (!src_is_dir && dst_is_dir) {
+ *__Error() = POSIX_EISDIR;
+ return -1;
+ }
+ if (dst_is_dir && !std::filesystem::is_empty(dst_path)) {
+ *__Error() = POSIX_ENOTEMPTY;
+ return -1;
+ }
+ std::filesystem::copy(src_path, dst_path, std::filesystem::copy_options::overwrite_existing);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceKernelRename(const char* from, const char* to) {
+ s32 result = posix_rename(from, to);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s64 PS4_SYSV_ABI posix_preadv(s32 fd, SceKernelIovec* iov, s32 iovcnt, s64 offset) {
if (offset < 0) {
- return ORBIS_KERNEL_ERROR_EINVAL;
+ *__Error() = POSIX_EINVAL;
+ return -1;
}
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->preadv(iov, iovcnt, offset);
+ s64 result = file->device->preadv(iov, iovcnt, offset);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
const s64 pos = file->f.Tell();
@@ -522,8 +742,8 @@ s64 PS4_SYSV_ABI sceKernelPreadv(int d, SceKernelIovec* iov, int iovcnt, s64 off
file->f.Seek(pos);
};
if (!file->f.Seek(offset)) {
- LOG_CRITICAL(Kernel_Fs, "failed to seek");
- return ORBIS_KERNEL_ERROR_EINVAL;
+ *__Error() = POSIX_EIO;
+ return -1;
}
size_t total_read = 0;
for (int i = 0; i < iovcnt; i++) {
@@ -532,118 +752,72 @@ s64 PS4_SYSV_ABI sceKernelPreadv(int d, SceKernelIovec* iov, int iovcnt, s64 off
return total_read;
}
-s64 PS4_SYSV_ABI sceKernelPread(int d, void* buf, size_t nbytes, s64 offset) {
- SceKernelIovec iovec{buf, nbytes};
- return sceKernelPreadv(d, &iovec, 1, offset);
-}
-
-int PS4_SYSV_ABI sceKernelFStat(int fd, OrbisKernelStat* sb) {
- LOG_INFO(Kernel_Fs, "(PARTIAL) fd = {}", fd);
- if (fd < 3) {
- return ORBIS_KERNEL_ERROR_EPERM;
- }
- if (sb == nullptr) {
- return ORBIS_KERNEL_ERROR_EFAULT;
- }
- auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(fd);
- if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
- }
- std::memset(sb, 0, sizeof(OrbisKernelStat));
-
- switch (file->type) {
- case Core::FileSys::FileType::Device:
- return file->device->fstat(sb);
- case Core::FileSys::FileType::Regular:
- sb->st_mode = 0000777u | 0100000u;
- sb->st_size = file->f.GetSize();
- sb->st_blksize = 512;
- sb->st_blocks = (sb->st_size + 511) / 512;
- // TODO incomplete
- break;
- case Core::FileSys::FileType::Directory:
- sb->st_mode = 0000777u | 0040000u;
- sb->st_size = 0;
- sb->st_blksize = 512;
- sb->st_blocks = 0;
- // TODO incomplete
- break;
- default:
- UNREACHABLE();
- }
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI posix_fstat(int fd, OrbisKernelStat* sb) {
- int result = sceKernelFStat(fd, sb);
+s64 PS4_SYSV_ABI sceKernelPreadv(s32 fd, SceKernelIovec* iov, s32 iovcnt, s64 offset) {
+ s64 result = posix_preadv(fd, iov, iovcnt, offset);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_fstat: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-s32 PS4_SYSV_ABI sceKernelFsync(int fd) {
+s64 PS4_SYSV_ABI posix_pread(s32 fd, void* buf, size_t nbytes, s64 offset) {
+ SceKernelIovec iovec{buf, nbytes};
+ return posix_preadv(fd, &iovec, 1, offset);
+}
+
+s64 PS4_SYSV_ABI sceKernelPread(s32 fd, void* buf, size_t nbytes, s64 offset) {
+ SceKernelIovec iovec{buf, nbytes};
+ return sceKernelPreadv(fd, &iovec, 1, offset);
+}
+
+s32 PS4_SYSV_ABI posix_fsync(s32 fd) {
auto* h = Common::Singleton::Instance();
auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->fsync();
+ s32 result = file->device->fsync();
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
file->f.Flush();
return ORBIS_OK;
}
-s32 PS4_SYSV_ABI posix_fsync(int fd) {
- s32 result = sceKernelFsync(fd);
+s32 PS4_SYSV_ABI sceKernelFsync(s32 fd) {
+ s32 result = posix_fsync(fd);
if (result < 0) {
- LOG_ERROR(Kernel_Pthread, "posix_fsync: error = {}", result);
- ErrSceToPosix(result);
- return -1;
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
return result;
}
-int PS4_SYSV_ABI sceKernelFtruncate(int fd, s64 length) {
- auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(fd);
-
- if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
- }
-
- if (file->type == Core::FileSys::FileType::Device) {
- return file->device->ftruncate(length);
- }
-
- if (file->m_host_name.empty()) {
- return ORBIS_KERNEL_ERROR_EACCES;
- }
-
- file->f.SetSize(length);
- return ORBIS_OK;
-}
-
-static int GetDents(int fd, char* buf, int nbytes, s64* basep) {
- if (fd < 3) {
- return ORBIS_KERNEL_ERROR_EBADF;
- }
-
+static s32 GetDents(s32 fd, char* buf, s32 nbytes, s64* basep) {
if (buf == nullptr) {
- return ORBIS_KERNEL_ERROR_EFAULT;
+ *__Error() = POSIX_EFAULT;
+ return -1;
}
auto* h = Common::Singleton::Instance();
auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->getdents(buf, nbytes, basep);
+ s32 result = file->device->getdents(buf, nbytes, basep);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
if (file->dirents_index == file->dirents.size()) {
@@ -651,7 +825,8 @@ static int GetDents(int fd, char* buf, int nbytes, s64* basep) {
}
if (file->type != Core::FileSys::FileType::Directory || nbytes < 512 ||
file->dirents_index > file->dirents.size()) {
- return ORBIS_KERNEL_ERROR_EINVAL;
+ *__Error() = POSIX_EINVAL;
+ return -1;
}
const auto& entry = file->dirents.at(file->dirents_index++);
auto str = entry.name;
@@ -672,118 +847,178 @@ static int GetDents(int fd, char* buf, int nbytes, s64* basep) {
return sizeof(OrbisKernelDirent);
}
-int PS4_SYSV_ABI sceKernelGetdents(int fd, char* buf, int nbytes) {
+s32 PS4_SYSV_ABI posix_getdents(s32 fd, char* buf, s32 nbytes) {
return GetDents(fd, buf, nbytes, nullptr);
}
-int PS4_SYSV_ABI sceKernelGetdirentries(int fd, char* buf, int nbytes, s64* basep) {
+s32 PS4_SYSV_ABI sceKernelGetdents(s32 fd, char* buf, s32 nbytes) {
+ s32 result = GetDents(fd, buf, nbytes, nullptr);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s32 PS4_SYSV_ABI getdirentries(s32 fd, char* buf, s32 nbytes, s64* basep) {
return GetDents(fd, buf, nbytes, basep);
}
-s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset) {
- if (d < 3) {
- return ORBIS_KERNEL_ERROR_EPERM;
+s32 PS4_SYSV_ABI posix_getdirentries(s32 fd, char* buf, s32 nbytes, s64* basep) {
+ return GetDents(fd, buf, nbytes, basep);
+}
+
+s32 PS4_SYSV_ABI sceKernelGetdirentries(s32 fd, char* buf, s32 nbytes, s64* basep) {
+ s32 result = GetDents(fd, buf, nbytes, basep);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
}
+ return result;
+}
+
+s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) {
if (offset < 0) {
- return ORBIS_KERNEL_ERROR_EINVAL;
+ *__Error() = POSIX_EINVAL;
+ return -1;
}
auto* h = Common::Singleton::Instance();
- auto* file = h->GetFile(d);
+ auto* file = h->GetFile(fd);
if (file == nullptr) {
- return ORBIS_KERNEL_ERROR_EBADF;
+ *__Error() = POSIX_EBADF;
+ return -1;
}
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
- return file->device->pwrite(buf, nbytes, offset);
+ s64 result = file->device->pwrite(buf, nbytes, offset);
+ if (result < 0) {
+ ErrSceToPosix(result);
+ return -1;
+ }
+ return result;
}
const s64 pos = file->f.Tell();
SCOPE_EXIT {
file->f.Seek(pos);
};
if (!file->f.Seek(offset)) {
- LOG_CRITICAL(Kernel_Fs, "sceKernelPwrite: failed to seek");
- return ORBIS_KERNEL_ERROR_EINVAL;
+ *__Error() = POSIX_EIO;
+ return -1;
}
return file->f.WriteRaw(buf, nbytes);
}
-s32 PS4_SYSV_ABI sceKernelRename(const char* from, const char* to) {
+s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset) {
+ s64 result = posix_pwrite(fd, buf, nbytes, offset);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
+
+s32 PS4_SYSV_ABI posix_unlink(const char* path) {
+ if (path == nullptr) {
+ *__Error() = POSIX_EINVAL;
+ return -1;
+ }
+
+ auto* h = Common::Singleton::Instance();
auto* mnt = Common::Singleton::Instance();
+
bool ro = false;
- const auto src_path = mnt->GetHostPath(from, &ro);
- if (!std::filesystem::exists(src_path)) {
- return ORBIS_KERNEL_ERROR_ENOENT;
+ const auto host_path = mnt->GetHostPath(path, &ro);
+ if (host_path.empty()) {
+ *__Error() = POSIX_ENOENT;
+ return -1;
}
+
if (ro) {
- return ORBIS_KERNEL_ERROR_EROFS;
+ *__Error() = POSIX_EROFS;
+ return -1;
}
- const auto dst_path = mnt->GetHostPath(to, &ro);
- if (ro) {
- return ORBIS_KERNEL_ERROR_EROFS;
+
+ if (std::filesystem::is_directory(host_path)) {
+ *__Error() = POSIX_EPERM;
+ return -1;
}
- const bool src_is_dir = std::filesystem::is_directory(src_path);
- const bool dst_is_dir = std::filesystem::is_directory(dst_path);
- if (src_is_dir && !dst_is_dir) {
- return ORBIS_KERNEL_ERROR_ENOTDIR;
+
+ auto* file = h->GetFile(host_path);
+ if (file == nullptr) {
+ // File to unlink hasn't been opened, manually open and unlink it.
+ Common::FS::IOFile file(host_path, Common::FS::FileAccessMode::ReadWrite);
+ file.Unlink();
+ } else {
+ file->f.Unlink();
}
- if (!src_is_dir && dst_is_dir) {
- return ORBIS_KERNEL_ERROR_EISDIR;
- }
- if (dst_is_dir && !std::filesystem::is_empty(dst_path)) {
- return ORBIS_KERNEL_ERROR_ENOTEMPTY;
- }
- std::filesystem::copy(src_path, dst_path, std::filesystem::copy_options::overwrite_existing);
+
+ LOG_INFO(Kernel_Fs, "Unlinked {}", path);
return ORBIS_OK;
}
-void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
- LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
- LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
- LIB_FUNCTION("wuCroIGjt2g", "libkernel", 1, "libkernel", 1, 1, open);
- LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, sceKernelClose);
- LIB_FUNCTION("bY-PO6JhzhQ", "libkernel", 1, "libkernel", 1, 1, posix_close);
- LIB_FUNCTION("bY-PO6JhzhQ", "libScePosix", 1, "libkernel", 1, 1, posix_close);
- LIB_FUNCTION("4wSze92BhLI", "libkernel", 1, "libkernel", 1, 1, sceKernelWrite);
+s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) {
+ s32 result = posix_unlink(path);
+ if (result < 0) {
+ LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
+ return ErrnoToSceKernelError(*__Error());
+ }
+ return result;
+}
- LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv);
- LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev);
- LIB_FUNCTION("Oy6IpwgtYOk", "libkernel", 1, "libkernel", 1, 1, posix_lseek);
+void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
+ LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1, open);
+ LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
+ LIB_FUNCTION("wuCroIGjt2g", "libkernel", 1, "libkernel", 1, 1, posix_open);
+ LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
+ LIB_FUNCTION("NNtFaKJbPt0", "libkernel", 1, "libkernel", 1, 1, close);
+ LIB_FUNCTION("bY-PO6JhzhQ", "libScePosix", 1, "libkernel", 1, 1, posix_close);
+ LIB_FUNCTION("bY-PO6JhzhQ", "libkernel", 1, "libkernel", 1, 1, posix_close);
+ LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, sceKernelClose);
+ LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, write);
+ LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, posix_write);
+ LIB_FUNCTION("FN4gaPmuFV8", "libkernel", 1, "libkernel", 1, 1, posix_write);
+ LIB_FUNCTION("4wSze92BhLI", "libkernel", 1, "libkernel", 1, 1, sceKernelWrite);
+ LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, readv);
+ LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, writev);
LIB_FUNCTION("Oy6IpwgtYOk", "libScePosix", 1, "libkernel", 1, 1, posix_lseek);
+ LIB_FUNCTION("Oy6IpwgtYOk", "libkernel", 1, "libkernel", 1, 1, posix_lseek);
LIB_FUNCTION("oib76F-12fk", "libkernel", 1, "libkernel", 1, 1, sceKernelLseek);
- LIB_FUNCTION("Cg4srZ6TKbU", "libkernel", 1, "libkernel", 1, 1, sceKernelRead);
+ LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, read);
LIB_FUNCTION("AqBioC2vF3I", "libScePosix", 1, "libkernel", 1, 1, posix_read);
- LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir);
+ LIB_FUNCTION("AqBioC2vF3I", "libkernel", 1, "libkernel", 1, 1, posix_read);
+ LIB_FUNCTION("Cg4srZ6TKbU", "libkernel", 1, "libkernel", 1, 1, sceKernelRead);
LIB_FUNCTION("JGMio+21L4c", "libScePosix", 1, "libkernel", 1, 1, posix_mkdir);
LIB_FUNCTION("JGMio+21L4c", "libkernel", 1, "libkernel", 1, 1, posix_mkdir);
- LIB_FUNCTION("naInUjYt3so", "libkernel", 1, "libkernel", 1, 1, sceKernelRmdir);
+ LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir);
LIB_FUNCTION("c7ZnT7V1B98", "libScePosix", 1, "libkernel", 1, 1, posix_rmdir);
LIB_FUNCTION("c7ZnT7V1B98", "libkernel", 1, "libkernel", 1, 1, posix_rmdir);
- LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat);
- LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFStat);
- LIB_FUNCTION("mqQMh1zPPT8", "libScePosix", 1, "libkernel", 1, 1, posix_fstat);
- LIB_FUNCTION("mqQMh1zPPT8", "libkernel", 1, "libkernel", 1, 1, posix_fstat);
- LIB_FUNCTION("VW3TVZiM4-E", "libkernel", 1, "libkernel", 1, 1, sceKernelFtruncate);
- LIB_FUNCTION("52NcYU9+lEo", "libkernel", 1, "libkernel", 1, 1, sceKernelRename);
-
+ LIB_FUNCTION("naInUjYt3so", "libkernel", 1, "libkernel", 1, 1, sceKernelRmdir);
LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat);
LIB_FUNCTION("E6ao34wPw+U", "libkernel", 1, "libkernel", 1, 1, posix_stat);
- LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
- LIB_FUNCTION("yTj62I7kw4s", "libkernel", 1, "libkernel", 1, 1, sceKernelPreadv);
+ LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat);
LIB_FUNCTION("uWyW3v98sU4", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckReachability);
- LIB_FUNCTION("fTx66l5iWIA", "libkernel", 1, "libkernel", 1, 1, sceKernelFsync);
- LIB_FUNCTION("juWbTNM+8hw", "libkernel", 1, "libkernel", 1, 1, posix_fsync);
+ LIB_FUNCTION("mqQMh1zPPT8", "libScePosix", 1, "libkernel", 1, 1, posix_fstat);
+ LIB_FUNCTION("mqQMh1zPPT8", "libkernel", 1, "libkernel", 1, 1, posix_fstat);
+ LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFstat);
+ LIB_FUNCTION("ih4CD9-gghM", "libkernel", 1, "libkernel", 1, 1, posix_ftruncate);
+ LIB_FUNCTION("VW3TVZiM4-E", "libkernel", 1, "libkernel", 1, 1, sceKernelFtruncate);
+ LIB_FUNCTION("52NcYU9+lEo", "libkernel", 1, "libkernel", 1, 1, sceKernelRename);
+ LIB_FUNCTION("yTj62I7kw4s", "libkernel", 1, "libkernel", 1, 1, sceKernelPreadv);
+ LIB_FUNCTION("ezv-RSBNKqI", "libScePosix", 1, "libkernel", 1, 1, posix_pread);
+ LIB_FUNCTION("ezv-RSBNKqI", "libkernel", 1, "libkernel", 1, 1, posix_pread);
+ LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
LIB_FUNCTION("juWbTNM+8hw", "libScePosix", 1, "libkernel", 1, 1, posix_fsync);
+ LIB_FUNCTION("juWbTNM+8hw", "libkernel", 1, "libkernel", 1, 1, posix_fsync);
+ LIB_FUNCTION("fTx66l5iWIA", "libkernel", 1, "libkernel", 1, 1, sceKernelFsync);
LIB_FUNCTION("j2AIqSqJP0w", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdents);
+ LIB_FUNCTION("sfKygSjIbI8", "libkernel", 1, "libkernel", 1, 1, getdirentries);
LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries);
+ LIB_FUNCTION("C2kJ-byS5rM", "libkernel", 1, "libkernel", 1, 1, posix_pwrite);
LIB_FUNCTION("nKWi-N2HBV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPwrite);
LIB_FUNCTION("AUXVxWeJU-A", "libkernel", 1, "libkernel", 1, 1, sceKernelUnlink);
-
- // openOrbis (to check if it is valid out of OpenOrbis
- LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1,
- posix_open); // _open should be equal to open function
}
} // namespace Libraries::Kernel
diff --git a/src/core/libraries/kernel/file_system.h b/src/core/libraries/kernel/file_system.h
index 1838df2fe..77ce3ec3d 100644
--- a/src/core/libraries/kernel/file_system.h
+++ b/src/core/libraries/kernel/file_system.h
@@ -65,10 +65,10 @@ constexpr int ORBIS_KERNEL_O_DSYNC = 0x1000;
constexpr int ORBIS_KERNEL_O_DIRECT = 0x00010000;
constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000;
-s64 PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes);
-s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes);
-s64 PS4_SYSV_ABI sceKernelPread(int d, void* buf, size_t nbytes, s64 offset);
-s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset);
+s64 PS4_SYSV_ABI sceKernelWrite(s32 fd, const void* buf, size_t nbytes);
+s64 PS4_SYSV_ABI sceKernelRead(s32 fd, void* buf, size_t nbytes);
+s64 PS4_SYSV_ABI sceKernelPread(s32 fd, void* buf, size_t nbytes, s64 offset);
+s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset);
void RegisterFileSystem(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Kernel
diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp
index 2b7735219..9227cf45a 100644
--- a/src/core/libraries/kernel/kernel.cpp
+++ b/src/core/libraries/kernel/kernel.cpp
@@ -85,17 +85,23 @@ int ErrnoToSceKernelError(int error) {
}
void SetPosixErrno(int e) {
- // Some error numbers are different between supported OSes or the PS4
+ // Some error numbers are different between supported OSes
switch (e) {
case EPERM:
g_posix_errno = POSIX_EPERM;
break;
- case EAGAIN:
- g_posix_errno = POSIX_EAGAIN;
+ case ENOENT:
+ g_posix_errno = POSIX_ENOENT;
+ break;
+ case EDEADLK:
+ g_posix_errno = POSIX_EDEADLK;
break;
case ENOMEM:
g_posix_errno = POSIX_ENOMEM;
break;
+ case EACCES:
+ g_posix_errno = POSIX_EACCES;
+ break;
case EINVAL:
g_posix_errno = POSIX_EINVAL;
break;
@@ -105,13 +111,14 @@ void SetPosixErrno(int e) {
case ERANGE:
g_posix_errno = POSIX_ERANGE;
break;
- case EDEADLK:
- g_posix_errno = POSIX_EDEADLK;
+ case EAGAIN:
+ g_posix_errno = POSIX_EAGAIN;
break;
case ETIMEDOUT:
g_posix_errno = POSIX_ETIMEDOUT;
break;
default:
+ LOG_WARNING(Kernel, "Unhandled errno {}", e);
g_posix_errno = e;
}
}
@@ -133,14 +140,6 @@ void PS4_SYSV_ABI sceLibcHeapGetTraceInfo(HeapInfoInfo* info) {
info->getSegmentInfo = 0;
}
-s64 PS4_SYSV_ABI ps4__write(int d, const char* buf, std::size_t nbytes) {
- return sceKernelWrite(d, buf, nbytes);
-}
-
-s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) {
- return sceKernelRead(d, buf, nbytes);
-}
-
struct OrbisKernelUuid {
u32 timeLow;
u16 timeMid;
@@ -229,13 +228,10 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error);
- LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize);
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
sceLibcHeapGetTraceInfo);
- LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
- LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, ps4__write);
}
} // namespace Libraries::Kernel
diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp
index 074cf524e..cd0fe650b 100644
--- a/src/core/libraries/libs.cpp
+++ b/src/core/libraries/libs.cpp
@@ -115,6 +115,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::NpParty::RegisterlibSceNpParty(sym);
Libraries::Zlib::RegisterlibSceZlib(sym);
Libraries::Hmd::RegisterlibSceHmd(sym);
+ Libraries::DiscMap::RegisterlibSceDiscMap(sym);
}
} // namespace Libraries
diff --git a/src/core/libraries/ngs2/ngs2.cpp b/src/core/libraries/ngs2/ngs2.cpp
index 7eb663413..0b42e2471 100644
--- a/src/core/libraries/ngs2/ngs2.cpp
+++ b/src/core/libraries/ngs2/ngs2.cpp
@@ -5,21 +5,480 @@
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/ngs2/ngs2.h"
+#include "core/libraries/ngs2/ngs2_custom.h"
#include "core/libraries/ngs2/ngs2_error.h"
+#include "core/libraries/ngs2/ngs2_geom.h"
#include "core/libraries/ngs2/ngs2_impl.h"
+#include "core/libraries/ngs2/ngs2_pan.h"
+#include "core/libraries/ngs2/ngs2_report.h"
namespace Libraries::Ngs2 {
-int PS4_SYSV_ABI sceNgs2CalcWaveformBlock() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
+// Ngs2
+
+s32 PS4_SYSV_ABI sceNgs2CalcWaveformBlock(const OrbisNgs2WaveformFormat* format, u32 samplePos,
+ u32 numSamples, OrbisNgs2WaveformBlock* outBlock) {
+ LOG_INFO(Lib_Ngs2, "samplePos = {}, numSamples = {}", samplePos, numSamples);
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
+s32 PS4_SYSV_ABI sceNgs2GetWaveformFrameInfo(const OrbisNgs2WaveformFormat* format,
+ u32* outFrameSize, u32* outNumFrameSamples,
+ u32* outUnitsPerFrame, u32* outNumDelaySamples) {
+ LOG_INFO(Lib_Ngs2, "called");
return ORBIS_OK;
}
+s32 PS4_SYSV_ABI sceNgs2ParseWaveformData(const void* data, size_t dataSize,
+ OrbisNgs2WaveformInfo* outInfo) {
+ LOG_INFO(Lib_Ngs2, "dataSize = {}", dataSize);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2ParseWaveformFile(const char* path, u64 offset,
+ OrbisNgs2WaveformInfo* outInfo) {
+ LOG_INFO(Lib_Ngs2, "path = {}, offset = {}", path, offset);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2ParseWaveformUser(OrbisNgs2ParseReadHandler handler, uintptr_t userData,
+ OrbisNgs2WaveformInfo* outInfo) {
+ LOG_INFO(Lib_Ngs2, "userData = {}", userData);
+ if (!handler) {
+ LOG_ERROR(Lib_Ngs2, "handler is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackCreate(OrbisNgs2Handle systemHandle, u32 rackId,
+ const OrbisNgs2RackOption* option,
+ const OrbisNgs2ContextBufferInfo* bufferInfo,
+ OrbisNgs2Handle* outHandle) {
+ LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackCreateWithAllocator(OrbisNgs2Handle systemHandle, u32 rackId,
+ const OrbisNgs2RackOption* option,
+ const OrbisNgs2BufferAllocator* allocator,
+ OrbisNgs2Handle* outHandle) {
+ LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackDestroy(OrbisNgs2Handle rackHandle,
+ OrbisNgs2ContextBufferInfo* outBufferInfo) {
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2RackInfo* outInfo,
+ size_t infoSize) {
+ LOG_INFO(Lib_Ngs2, "infoSize = {}", infoSize);
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackGetUserData(OrbisNgs2Handle rackHandle, uintptr_t* outUserData) {
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackGetVoiceHandle(OrbisNgs2Handle rackHandle, u32 voiceIndex,
+ OrbisNgs2Handle* outHandle) {
+ LOG_INFO(Lib_Ngs2, "voiceIndex = {}", voiceIndex);
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackLock(OrbisNgs2Handle rackHandle) {
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackQueryBufferSize(u32 rackId, const OrbisNgs2RackOption* option,
+ OrbisNgs2ContextBufferInfo* outBufferInfo) {
+ LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackSetUserData(OrbisNgs2Handle rackHandle, uintptr_t userData) {
+ LOG_INFO(Lib_Ngs2, "userData = {}", userData);
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2RackUnlock(OrbisNgs2Handle rackHandle) {
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemCreate(const OrbisNgs2SystemOption* option,
+ const OrbisNgs2ContextBufferInfo* bufferInfo,
+ OrbisNgs2Handle* outHandle) {
+ s32 result;
+ OrbisNgs2ContextBufferInfo localInfo;
+ if (!bufferInfo || !outHandle) {
+ if (!bufferInfo) {
+ result = ORBIS_NGS2_ERROR_INVALID_BUFFER_INFO;
+ LOG_ERROR(Lib_Ngs2, "Invalid system buffer info {}", (void*)bufferInfo);
+ } else {
+ result = ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS;
+ LOG_ERROR(Lib_Ngs2, "Invalid system handle address {}", (void*)outHandle);
+ }
+
+ // TODO: Report errors?
+ } else {
+ // Make bufferInfo copy
+ localInfo.hostBuffer = bufferInfo->hostBuffer;
+ localInfo.hostBufferSize = bufferInfo->hostBufferSize;
+ for (int i = 0; i < 5; i++) {
+ localInfo.reserved[i] = bufferInfo->reserved[i];
+ }
+ localInfo.userData = bufferInfo->userData;
+
+ result = SystemSetup(option, &localInfo, 0, outHandle);
+ }
+
+ // TODO: API reporting?
+
+ LOG_INFO(Lib_Ngs2, "called");
+ return result;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemCreateWithAllocator(const OrbisNgs2SystemOption* option,
+ const OrbisNgs2BufferAllocator* allocator,
+ OrbisNgs2Handle* outHandle) {
+ s32 result;
+ if (allocator && allocator->allocHandler != 0) {
+ OrbisNgs2BufferAllocHandler hostAlloc = allocator->allocHandler;
+ if (outHandle) {
+ OrbisNgs2BufferFreeHandler hostFree = allocator->freeHandler;
+ OrbisNgs2ContextBufferInfo* bufferInfo = 0;
+ result = SystemSetup(option, bufferInfo, 0, 0);
+ if (result >= 0) {
+ uintptr_t sysUserData = allocator->userData;
+ result = hostAlloc(bufferInfo);
+ if (result >= 0) {
+ OrbisNgs2Handle* handleCopy = outHandle;
+ result = SystemSetup(option, bufferInfo, hostFree, handleCopy);
+ if (result < 0) {
+ if (hostFree) {
+ hostFree(bufferInfo);
+ }
+ }
+ }
+ }
+ } else {
+ result = ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS;
+ LOG_ERROR(Lib_Ngs2, "Invalid system handle address {}", (void*)outHandle);
+ }
+ } else {
+ result = ORBIS_NGS2_ERROR_INVALID_BUFFER_ALLOCATOR;
+ LOG_ERROR(Lib_Ngs2, "Invalid system buffer allocator {}", (void*)allocator);
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return result;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemDestroy(OrbisNgs2Handle systemHandle,
+ OrbisNgs2ContextBufferInfo* outBufferInfo) {
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemEnumHandles(OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
+ LOG_INFO(Lib_Ngs2, "maxHandles = {}", maxHandles);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemEnumRackHandles(OrbisNgs2Handle systemHandle,
+ OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
+ LOG_INFO(Lib_Ngs2, "maxHandles = {}", maxHandles);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2SystemInfo* outInfo,
+ size_t infoSize) {
+ LOG_INFO(Lib_Ngs2, "infoSize = {}", infoSize);
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemGetUserData(OrbisNgs2Handle systemHandle, uintptr_t* outUserData) {
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemLock(OrbisNgs2Handle systemHandle) {
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemQueryBufferSize(const OrbisNgs2SystemOption* option,
+ OrbisNgs2ContextBufferInfo* outBufferInfo) {
+ s32 result;
+ if (outBufferInfo) {
+ result = SystemSetup(option, outBufferInfo, 0, 0);
+ LOG_INFO(Lib_Ngs2, "called");
+ } else {
+ result = ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS;
+ LOG_ERROR(Lib_Ngs2, "Invalid system buffer info {}", (void*)outBufferInfo);
+ }
+
+ return result;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemRender(OrbisNgs2Handle systemHandle,
+ const OrbisNgs2RenderBufferInfo* aBufferInfo,
+ u32 numBufferInfo) {
+ LOG_INFO(Lib_Ngs2, "numBufferInfo = {}", numBufferInfo);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+static s32 PS4_SYSV_ABI sceNgs2SystemResetOption(OrbisNgs2SystemOption* outOption) {
+ static const OrbisNgs2SystemOption option = {
+ sizeof(OrbisNgs2SystemOption), "", 0, 512, 256, 48000, {0}};
+
+ if (!outOption) {
+ LOG_ERROR(Lib_Ngs2, "Invalid system option address {}", (void*)outOption);
+ return ORBIS_NGS2_ERROR_INVALID_OPTION_ADDRESS;
+ }
+ *outOption = option;
+
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemSetGrainSamples(OrbisNgs2Handle systemHandle, u32 numSamples) {
+ LOG_INFO(Lib_Ngs2, "numSamples = {}", numSamples);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemSetSampleRate(OrbisNgs2Handle systemHandle, u32 sampleRate) {
+ LOG_INFO(Lib_Ngs2, "sampleRate = {}", sampleRate);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemSetUserData(OrbisNgs2Handle systemHandle, uintptr_t userData) {
+ LOG_INFO(Lib_Ngs2, "userData = {}", userData);
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2SystemUnlock(OrbisNgs2Handle systemHandle) {
+ if (!systemHandle) {
+ LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2VoiceControl(OrbisNgs2Handle voiceHandle,
+ const OrbisNgs2VoiceParamHeader* paramList) {
+ if (!voiceHandle) {
+ LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2VoiceGetMatrixInfo(OrbisNgs2Handle voiceHandle, u32 matrixId,
+ OrbisNgs2VoiceMatrixInfo* outInfo, size_t outInfoSize) {
+ LOG_INFO(Lib_Ngs2, "matrixId = {}, outInfoSize = {}", matrixId, outInfoSize);
+ if (!voiceHandle) {
+ LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2VoiceGetOwner(OrbisNgs2Handle voiceHandle, OrbisNgs2Handle* outRackHandle,
+ u32* outVoiceId) {
+ if (!voiceHandle) {
+ LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2VoiceGetPortInfo(OrbisNgs2Handle voiceHandle, u32 port,
+ OrbisNgs2VoicePortInfo* outInfo, size_t outInfoSize) {
+ LOG_INFO(Lib_Ngs2, "port = {}, outInfoSize = {}", port, outInfoSize);
+ if (!voiceHandle) {
+ LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2VoiceGetState(OrbisNgs2Handle voiceHandle, OrbisNgs2VoiceState* outState,
+ size_t stateSize) {
+ LOG_INFO(Lib_Ngs2, "stateSize = {}", stateSize);
+ if (!voiceHandle) {
+ LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2VoiceGetStateFlags(OrbisNgs2Handle voiceHandle, u32* outStateFlags) {
+ if (!voiceHandle) {
+ LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+// Ngs2Custom
+
+s32 PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo(OrbisNgs2Handle rackHandle, u32 moduleIndex,
+ OrbisNgs2CustomModuleInfo* outInfo,
+ size_t infoSize) {
+ LOG_INFO(Lib_Ngs2, "moduleIndex = {}, infoSize = {}", moduleIndex, infoSize);
+ if (!rackHandle) {
+ LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+// Ngs2Geom
+
+s32 PS4_SYSV_ABI sceNgs2GeomResetListenerParam(OrbisNgs2GeomListenerParam* outListenerParam) {
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2GeomResetSourceParam(OrbisNgs2GeomSourceParam* outSourceParam) {
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2GeomCalcListener(const OrbisNgs2GeomListenerParam* param,
+ OrbisNgs2GeomListenerWork* outWork, u32 flags) {
+ LOG_INFO(Lib_Ngs2, "flags = {}", flags);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2GeomApply(const OrbisNgs2GeomListenerWork* listener,
+ const OrbisNgs2GeomSourceParam* source,
+ OrbisNgs2GeomAttribute* outAttrib, u32 flags) {
+ LOG_INFO(Lib_Ngs2, "flags = {}", flags);
+ return ORBIS_OK;
+}
+
+// Ngs2Pan
+
+s32 PS4_SYSV_ABI sceNgs2PanInit(OrbisNgs2PanWork* work, const float* aSpeakerAngle, float unitAngle,
+ u32 numSpeakers) {
+ LOG_INFO(Lib_Ngs2, "aSpeakerAngle = {}, unitAngle = {}, numSpeakers = {}", *aSpeakerAngle,
+ unitAngle, numSpeakers);
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2PanGetVolumeMatrix(OrbisNgs2PanWork* work, const OrbisNgs2PanParam* aParam,
+ u32 numParams, u32 matrixFormat,
+ float* outVolumeMatrix) {
+ LOG_INFO(Lib_Ngs2, "numParams = {}, matrixFormat = {}", numParams, matrixFormat);
+ return ORBIS_OK;
+}
+
+// Ngs2Report
+
+s32 PS4_SYSV_ABI sceNgs2ReportRegisterHandler(u32 reportType, OrbisNgs2ReportHandler handler,
+ uintptr_t userData, OrbisNgs2Handle* outHandle) {
+ LOG_INFO(Lib_Ngs2, "reportType = {}, userData = {}", reportType, userData);
+ if (!handler) {
+ LOG_ERROR(Lib_Ngs2, "handler is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
+ }
+ return ORBIS_OK;
+}
+
+s32 PS4_SYSV_ABI sceNgs2ReportUnregisterHandler(OrbisNgs2Handle reportHandle) {
+ if (!reportHandle) {
+ LOG_ERROR(Lib_Ngs2, "reportHandle is nullptr");
+ return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
+ }
+ LOG_INFO(Lib_Ngs2, "called");
+ return ORBIS_OK;
+}
+
+// Unknown
+
int PS4_SYSV_ABI sceNgs2FftInit() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
@@ -35,31 +494,6 @@ int PS4_SYSV_ABI sceNgs2FftQuerySize() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2GeomApply() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2GeomCalcListener() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2GeomResetListenerParam() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2GeomResetSourceParam() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2GetWaveformFrameInfo() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2JobSchedulerResetOption() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
@@ -80,71 +514,6 @@ int PS4_SYSV_ABI sceNgs2ModuleQueueEnumItems() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2PanGetVolumeMatrix() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2PanInit() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2ParseWaveformData() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2ParseWaveformFile() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2ParseWaveformUser() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackCreate() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackCreateWithAllocator() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackDestroy() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackGetInfo() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackGetUserData() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackGetVoiceHandle() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackLock() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackQueryBufferSize() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2RackQueryInfo() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
@@ -155,116 +524,21 @@ int PS4_SYSV_ABI sceNgs2RackRunCommands() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2RackSetUserData() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2RackUnlock() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2ReportRegisterHandler() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2ReportUnregisterHandler() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemCreate() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemCreateWithAllocator() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemDestroy() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemEnumHandles() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemEnumRackHandles() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemGetInfo() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemGetUserData() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemLock() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemQueryBufferSize() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2SystemQueryInfo() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2SystemRender() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemResetOption() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2SystemRunCommands() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2SystemSetGrainSamples() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2SystemSetLoudThreshold() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2SystemSetSampleRate() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemSetUserData() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2SystemUnlock() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2StreamCreate() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
@@ -300,36 +574,6 @@ int PS4_SYSV_ABI sceNgs2StreamRunCommands() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceNgs2VoiceControl() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2VoiceGetMatrixInfo() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2VoiceGetOwner() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2VoiceGetPortInfo() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2VoiceGetState() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
-int PS4_SYSV_ABI sceNgs2VoiceGetStateFlags() {
- LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
- return ORBIS_OK;
-}
-
int PS4_SYSV_ABI sceNgs2VoiceQueryInfo() {
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
return ORBIS_OK;
diff --git a/src/core/libraries/ngs2/ngs2.h b/src/core/libraries/ngs2/ngs2.h
index a5f1f52a6..a34bf21d4 100644
--- a/src/core/libraries/ngs2/ngs2.h
+++ b/src/core/libraries/ngs2/ngs2.h
@@ -3,7 +3,11 @@
#pragma once
+#include "core/libraries/ngs2/ngs2_impl.h"
+
#include
+#include
+#include
#include "common/types.h"
namespace Core::Loader {
@@ -12,60 +16,253 @@ class SymbolsResolver;
namespace Libraries::Ngs2 {
-class Ngs2;
+typedef s32 (*OrbisNgs2ParseReadHandler)(uintptr_t userData, u32 offset, void* data, size_t size);
-using SceNgs2Handle = Ngs2*;
-
-enum class SceNgs2HandleType : u32 {
- System = 0,
+enum class OrbisNgs2HandleType : u32 {
+ Invalid = 0,
+ System = 1,
+ Rack = 2,
+ Voice = 3,
+ VoiceControl = 6
};
-struct Ngs2Handle {
- void* selfPointer;
- void* dataPointer;
- std::atomic* atomicPtr;
- u32 handleType;
- u32 flags_unk;
+static const int ORBIS_NGS2_MAX_VOICE_CHANNELS = 8;
+static const int ORBIS_NGS2_WAVEFORM_INFO_MAX_BLOCKS = 4;
+static const int ORBIS_NGS2_MAX_MATRIX_LEVELS =
+ (ORBIS_NGS2_MAX_VOICE_CHANNELS * ORBIS_NGS2_MAX_VOICE_CHANNELS);
- u32 uid;
- u16 maxGrainSamples;
- u16 minGrainSamples;
- u16 currentGrainSamples;
- u16 numGrainSamples;
- u16 unknown2;
+struct OrbisNgs2WaveformFormat {
+ u32 waveformType;
+ u32 numChannels;
u32 sampleRate;
- u32 unknown3;
-
- void* flushMutex;
- u32 flushMutexInitialized;
- void* processMutex;
- u32 processMutexInitialized;
-
- // Linked list pointers for system list
- Ngs2Handle* prev;
- Ngs2Handle* next;
+ u32 configData;
+ u32 frameOffset;
+ u32 frameMargin;
};
-struct SystemOptions {
- char padding[6];
- s32 maxGrainSamples;
- s32 numGrainSamples;
- s32 sampleRate;
+struct OrbisNgs2WaveformBlock {
+ u32 dataOffset;
+ u32 dataSize;
+ u32 numRepeats;
+ u32 numSkipSamples;
+ u32 numSamples;
+ u32 reserved;
+ uintptr_t userData;
};
-struct SystemState {
- // TODO
+struct OrbisNgs2WaveformInfo {
+ OrbisNgs2WaveformFormat format;
+
+ u32 dataOffset;
+ u32 dataSize;
+
+ u32 loopBeginPosition;
+ u32 loopEndPosition;
+ u32 numSamples;
+
+ u32 audioUnitSize;
+ u32 numAudioUnitSamples;
+ u32 numAudioUnitPerFrame;
+
+ u32 audioFrameSize;
+ u32 numAudioFrameSamples;
+
+ u32 numDelaySamples;
+
+ u32 numBlocks;
+ OrbisNgs2WaveformBlock aBlock[ORBIS_NGS2_WAVEFORM_INFO_MAX_BLOCKS];
};
-struct StackBuffer {
- void** top;
- void* base;
- void* curr;
- size_t usedSize;
- size_t totalSize;
- size_t alignment;
- char isVerifyEnabled;
- char padding[7];
+struct OrbisNgs2EnvelopePoint {
+ u32 curve;
+ u32 duration;
+ float height;
+};
+
+struct OrbisNgs2UserFxProcessContext {
+ float** aChannelData;
+ uintptr_t userData0;
+ uintptr_t userData1;
+ uintptr_t userData2;
+ u32 flags;
+ u32 numChannels;
+ u32 numGrainSamples;
+ u32 sampleRate;
+};
+
+typedef s32 (*OrbisNgs2UserFxProcessHandler)(OrbisNgs2UserFxProcessContext* context);
+
+struct OrbisNgs2UserFx2SetupContext {
+ void* common;
+ void* param;
+ void* work;
+ uintptr_t userData;
+ u32 maxVoices;
+ u32 voiceIndex;
+ u64 reserved[4];
+};
+
+typedef s32 (*OrbisNgs2UserFx2SetupHandler)(OrbisNgs2UserFx2SetupContext* context);
+
+struct OrbisNgs2UserFx2CleanupContext {
+ void* common;
+ void* param;
+ void* work;
+ uintptr_t userData;
+ u32 maxVoices;
+ u32 voiceIndex;
+ u64 reserved[4];
+};
+
+typedef s32 (*OrbisNgs2UserFx2CleanupHandler)(OrbisNgs2UserFx2CleanupContext* context);
+
+struct OrbisNgs2UserFx2ControlContext {
+ const void* data;
+ size_t dataSize;
+ void* common;
+ void* param;
+ uintptr_t userData;
+ u64 reserved[4];
+};
+
+typedef s32 (*OrbisNgs2UserFx2ControlHandler)(OrbisNgs2UserFx2ControlContext* context);
+
+struct OrbisNgs2UserFx2ProcessContext {
+ float** aChannelData;
+ void* common;
+ const void* param;
+ void* work;
+ void* state;
+ uintptr_t userData;
+ u32 flags;
+ u32 numInputChannels;
+ u32 numOutputChannels;
+ u32 numGrainSamples;
+ u32 sampleRate;
+ u32 reserved;
+ u64 reserved2[4];
+};
+
+typedef s32 (*OrbisNgs2UserFx2ProcessHandler)(OrbisNgs2UserFx2ProcessContext* context);
+
+struct OrbisNgs2BufferAllocator {
+ OrbisNgs2BufferAllocHandler allocHandler;
+ OrbisNgs2BufferFreeHandler freeHandler;
+ uintptr_t userData;
+};
+
+struct OrbisNgs2RenderBufferInfo {
+ void* buffer;
+ size_t bufferSize;
+ u32 waveformType;
+ u32 numChannels;
+};
+
+struct OrbisNgs2RackOption {
+ size_t size;
+ char name[ORBIS_NGS2_RACK_NAME_LENGTH];
+
+ u32 flags;
+ u32 maxGrainSamples;
+ u32 maxVoices;
+ u32 maxInputDelayBlocks;
+ u32 maxMatrices;
+ u32 maxPorts;
+ u32 aReserved[20];
+};
+
+struct OrbisNgs2VoiceParamHeader {
+ u16 size;
+ s16 next;
+ u32 id;
+};
+
+struct OrbisNgs2VoiceMatrixLevelsParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 matrixId;
+ u32 numLevels;
+ const float* aLevel;
+};
+
+struct OrbisNgs2VoicePortMatrixParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 port;
+ s32 matrixId;
+};
+
+struct OrbisNgs2VoicePortVolumeParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 port;
+ float level;
+};
+
+struct OrbisNgs2VoicePortDelayParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 port;
+ u32 numSamples;
+};
+
+struct OrbisNgs2VoicePatchParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 port;
+ u32 destInputId;
+ OrbisNgs2Handle destHandle;
+};
+
+struct OrbisNgs2VoiceEventParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 eventId;
+};
+
+struct OrbisNgs2VoiceCallbackInfo {
+ uintptr_t callbackData;
+ OrbisNgs2Handle voiceHandle;
+ u32 flag;
+ u32 reserved;
+ union {
+ struct {
+ uintptr_t userData;
+ const void* data;
+ u32 dataSize;
+ u32 repeatedCount;
+ u32 attributeFlags;
+ u32 reserved2;
+ } waveformBlock;
+ } param;
+};
+
+typedef void (*OrbisNgs2VoiceCallbackHandler)(const OrbisNgs2VoiceCallbackInfo* info);
+
+struct OrbisNgs2VoiceCallbackParam {
+ OrbisNgs2VoiceParamHeader header;
+ OrbisNgs2VoiceCallbackHandler callbackHandler;
+
+ uintptr_t callbackData;
+ u32 flags;
+ u32 reserved;
+};
+
+struct OrbisNgs2VoicePortInfo {
+ s32 matrixId;
+ float volume;
+ u32 numDelaySamples;
+ u32 destInputId;
+ OrbisNgs2Handle destHandle;
+};
+
+struct OrbisNgs2VoiceMatrixInfo {
+ u32 numLevels;
+ float aLevel[ORBIS_NGS2_MAX_MATRIX_LEVELS];
+};
+
+struct OrbisNgs2VoiceState {
+ u32 stateFlags;
};
void RegisterlibSceNgs2(Core::Loader::SymbolsResolver* sym);
diff --git a/src/core/libraries/ngs2/ngs2_custom.cpp b/src/core/libraries/ngs2/ngs2_custom.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_custom.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_custom.h b/src/core/libraries/ngs2/ngs2_custom.h
new file mode 100644
index 000000000..0c45a5d81
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_custom.h
@@ -0,0 +1,444 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+#include "ngs2_reverb.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Custom;
+
+static const int ORBIS_NGS2_CUSTOM_MAX_MODULES = 24;
+static const int ORBIS_NGS2_CUSTOM_MAX_PORTS = 16;
+static const int ORBIS_NGS2_CUSTOM_DELAY_MAX_TAPS = 8;
+
+struct OrbisNgs2CustomModuleOption {
+ u32 size;
+};
+
+struct OrbisNgs2CustomEnvelopeModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+
+ u32 maxPoints;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomReverbModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+
+ u32 reverbSize;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomChorusModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+
+ u32 maxPhases;
+ u32 reserved;
+} OrbisNgs2CustomChorusModuleOption;
+
+struct OrbisNgs2CustomPeakMeterModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+ u32 numBlocks;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomDelayModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+
+ u32 type;
+ u32 maxTaps;
+ float maxLength;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomPitchShiftModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+
+ u32 quality;
+};
+
+struct OrbisNgs2CustomUserFx2ModuleOption {
+ OrbisNgs2CustomModuleOption customModuleOption;
+
+ OrbisNgs2UserFx2SetupHandler setupHandler;
+ OrbisNgs2UserFx2CleanupHandler cleanupHandler;
+ OrbisNgs2UserFx2ControlHandler controlHandler;
+ OrbisNgs2UserFx2ProcessHandler processHandler;
+
+ size_t commonSize;
+ size_t paramSize;
+ size_t workSize;
+ uintptr_t userData;
+};
+
+struct OrbisNgs2CustomRackModuleInfo {
+ const OrbisNgs2CustomModuleOption* option;
+
+ u32 moduleId;
+ u32 sourceBufferId;
+ u32 extraBufferId;
+ u32 destBufferId;
+ u32 stateOffset;
+ u32 stateSize;
+ u32 reserved;
+ u32 reserved2;
+};
+
+struct OrbisNgs2CustomRackPortInfo {
+ u32 sourceBufferId;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomRackOption {
+ OrbisNgs2RackOption rackOption;
+ u32 stateSize;
+ u32 numBuffers;
+ u32 numModules;
+ u32 reserved;
+ OrbisNgs2CustomRackModuleInfo aModule[ORBIS_NGS2_CUSTOM_MAX_MODULES];
+ OrbisNgs2CustomRackPortInfo aPort[ORBIS_NGS2_CUSTOM_MAX_PORTS];
+};
+
+struct OrbisNgs2CustomSamplerRackOption {
+ OrbisNgs2CustomRackOption customRackOption;
+
+ u32 maxChannelWorks;
+ u32 maxWaveformBlocks;
+ u32 maxAtrac9Decoders;
+ u32 maxAtrac9ChannelWorks;
+ u32 maxAjmAtrac9Decoders;
+ u32 maxCodecCaches;
+};
+
+struct OrbisNgs2CustomSubmixerRackOption {
+ OrbisNgs2CustomRackOption customRackOption;
+
+ u32 maxChannels;
+ u32 maxInputs;
+};
+
+struct OrbisNgs2CustomMasteringRackOption {
+ OrbisNgs2CustomRackOption customRackOption;
+
+ u32 maxChannels;
+ u32 maxInputs;
+};
+
+struct OrbisNgs2CustomSamplerVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+ OrbisNgs2WaveformFormat format;
+ u32 flags;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomSamplerVoiceWaveformBlocksParam {
+ OrbisNgs2VoiceParamHeader header;
+ const void* data;
+ u32 flags;
+ u32 numBlocks;
+ const OrbisNgs2WaveformBlock* aBlock;
+};
+
+struct OrbisNgs2CustomSamplerVoiceWaveformAddressParam {
+ OrbisNgs2VoiceParamHeader header;
+ const void* from;
+ const void* to;
+};
+
+struct OrbisNgs2CustomSamplerVoiceWaveformFrameOffsetParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 frameOffset;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomSamplerVoiceExitLoopParam {
+ OrbisNgs2VoiceParamHeader header;
+};
+
+struct OrbisNgs2CustomSamplerVoicePitchParam {
+ OrbisNgs2VoiceParamHeader header;
+ float ratio;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomSamplerVoiceState {
+ OrbisNgs2VoiceState voiceState;
+ char padding[32];
+ const void* waveformData;
+ u64 numDecodedSamples;
+ u64 decodedDataSize;
+ u64 userData;
+ u32 reserved;
+ u32 reserved2;
+};
+
+struct OrbisNgs2CustomSubmixerVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 numInputChannels;
+ u32 numOutputChannels;
+ u32 flags;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomSubmixerVoiceState {
+ OrbisNgs2VoiceState voiceState; // Voice state
+ u32 reserved;
+ u32 reserved2;
+};
+
+struct OrbisNgs2CustomMasteringVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 numInputChannels;
+ u32 flags;
+};
+
+struct OrbisNgs2CustomMasteringVoiceOutputParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 outputId;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomMasteringVoiceState {
+ OrbisNgs2VoiceState voiceState;
+ u32 reserved;
+ u32 reserved2;
+};
+
+struct OrbisNgs2CustomVoiceEnvelopeParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 numForwardPoints;
+ u32 numReleasePoints;
+ const OrbisNgs2EnvelopePoint* aPoint;
+};
+
+struct OrbisNgs2CustomVoiceDistortionParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 flags;
+ float a;
+ float b;
+ float clip;
+ float gate;
+ float wetLevel;
+ float dryLevel;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomVoiceCompressorParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 flags;
+ float threshold;
+ float ratio;
+ float knee;
+ float attackTime;
+ float releaseTime;
+ float level;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomVoiceFilterParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 type;
+ u32 channelMask;
+ union {
+ struct {
+ float i0;
+ float i1;
+ float i2;
+ float o1;
+ float o2;
+ } direct;
+ struct {
+ float fc;
+ float q;
+ float level;
+ u32 reserved;
+ u32 reserved2;
+ } fcq;
+ } param;
+ u32 reserved3;
+};
+
+struct OrbisNgs2CustomVoiceLfeFilterParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 enableFlag;
+ u32 fc;
+};
+
+struct OrbisNgs2CustomVoiceGainParam {
+ OrbisNgs2VoiceParamHeader header;
+ float aLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+};
+
+struct OrbisNgs2CustomVoiceMixerParam {
+ OrbisNgs2VoiceParamHeader header;
+ float aSourceLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+ float aDestLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+};
+
+struct OrbisNgs2CustomVoiceChannelMixerParam {
+ OrbisNgs2VoiceParamHeader header;
+ float aLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS][ORBIS_NGS2_MAX_VOICE_CHANNELS];
+};
+
+struct OrbisNgs2CustomVoiceUserFxParam {
+ OrbisNgs2VoiceParamHeader header;
+ OrbisNgs2UserFxProcessHandler handler;
+
+ uintptr_t userData0;
+ uintptr_t userData1;
+ uintptr_t userData2;
+};
+
+struct OrbisNgs2CustomVoiceUserFx2Param {
+ OrbisNgs2VoiceParamHeader header;
+ const void* data;
+ size_t dataSize;
+};
+
+struct OrbisNgs2CustomVoiceOutputParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 outputId;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomVoicePeakMeterParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 enableFlag;
+ u32 reserved;
+} OrbisNgs2CustomVoicePeakMeterParam;
+
+struct OrbisNgs2CustomVoiceReverbParam {
+ OrbisNgs2VoiceParamHeader header;
+ OrbisNgs2ReverbI3DL2Param i3dl2;
+};
+
+struct OrbisNgs2CustomVoiceChorusParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 flags;
+ u32 numPhases;
+ u32 channelMask;
+ float inputLevel;
+ float delayTime;
+ float modulationRatio;
+ float modulationDepth;
+ float feedbackLevel;
+ float wetLevel;
+ float dryLevel;
+};
+
+struct OrbisNgs2DelayTapInfo {
+ float tapLevel;
+ float delayTime;
+};
+
+struct OrbisNgs2CustomVoiceDelayParam {
+ OrbisNgs2VoiceParamHeader header;
+ float dryLevel;
+ float wetLevel;
+ float inputLevel;
+ float feedbackLevel;
+ float lowpassFc;
+ u32 numTaps;
+ OrbisNgs2DelayTapInfo aTap[ORBIS_NGS2_CUSTOM_DELAY_MAX_TAPS];
+ float aInputMixLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+ u32 channelMask;
+ u32 flags;
+};
+
+struct OrbisNgs2CustomVoiceNoiseGateParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 flags;
+ float threshold;
+ float attackTime;
+ float releaseTime;
+};
+
+struct OrbisNgs2CustomVoicePitchShiftParam {
+ OrbisNgs2VoiceParamHeader header;
+ s32 cent;
+};
+
+struct OrbisNgs2CustomEnvelopeModuleState {
+ float height;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomCompressorModuleState {
+ float peakHeight;
+ float compressorHeight;
+};
+
+struct OrbisNgs2CustomPeakMeterModuleState {
+ float peak;
+ float aChannelPeak[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomNoiseGateModuleState {
+ float gateHeight;
+};
+
+struct OrbisNgs2CustomRackInfo {
+ OrbisNgs2RackInfo rackInfo;
+ u32 stateSize;
+ u32 numBuffers;
+ u32 numModules;
+ u32 reserved;
+ OrbisNgs2CustomRackModuleInfo aModule[ORBIS_NGS2_CUSTOM_MAX_MODULES];
+ OrbisNgs2CustomRackPortInfo aPort[ORBIS_NGS2_CUSTOM_MAX_PORTS];
+};
+
+struct OrbisNgs2CustomSamplerRackInfo {
+ OrbisNgs2CustomRackInfo customRackInfo;
+
+ u32 maxChannelWorks;
+ u32 maxWaveformBlocks;
+ u32 maxAtrac9Decoders;
+ u32 maxAtrac9ChannelWorks;
+ u32 maxAjmAtrac9Decoders;
+ u32 maxCodecCaches;
+};
+
+struct OrbisNgs2CustomSubmixerRackInfo {
+ OrbisNgs2CustomRackInfo customRackInfo;
+
+ u32 maxChannels;
+ u32 maxInputs;
+};
+
+struct OrbisNgs2CustomMasteringRackInfo {
+ OrbisNgs2CustomRackInfo customRackInfo;
+
+ u32 maxChannels;
+ u32 maxInputs;
+};
+
+struct OrbisNgs2CustomModuleInfo {
+ u32 moduleId;
+ u32 sourceBufferId;
+ u32 extraBufferId;
+ u32 destBufferId;
+ u32 stateOffset;
+ u32 stateSize;
+ u32 reserved;
+ u32 reserved2;
+};
+
+struct OrbisNgs2CustomEnvelopeModuleInfo {
+ OrbisNgs2CustomModuleInfo moduleInfo;
+
+ u32 maxPoints;
+ u32 reserved;
+};
+
+struct OrbisNgs2CustomReverbModuleInfo {
+ OrbisNgs2CustomModuleInfo moduleInfo;
+
+ u32 reverbSize;
+ u32 reserved;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_eq.cpp b/src/core/libraries/ngs2/ngs2_eq.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_eq.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_eq.h b/src/core/libraries/ngs2/ngs2_eq.h
new file mode 100644
index 000000000..99688f24e
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_eq.h
@@ -0,0 +1,41 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Eq;
+
+struct OrbisNgs2EqVoiceSetupParam {
+ u32 numChannels;
+};
+
+struct OrbisNgs2EqVoiceFilterParam {
+ u32 type;
+ u32 channelMask;
+ union {
+ struct {
+ float i0;
+ float i1;
+ float i2;
+ float o1;
+ float o2;
+ } direct;
+ struct {
+ float fc;
+ float q;
+ float level;
+ u32 reserved;
+ u32 reserved2;
+ } fcq;
+ } param;
+};
+
+struct OrbisNgs2EqVoiceState {
+ u32 stateFlags;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_geom.cpp b/src/core/libraries/ngs2/ngs2_geom.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_geom.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_geom.h b/src/core/libraries/ngs2/ngs2_geom.h
new file mode 100644
index 000000000..93af99d8d
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_geom.h
@@ -0,0 +1,80 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Geom;
+
+struct OrbisNgs2GeomVector {
+ float x;
+ float y;
+ float z;
+};
+
+struct OrbisNgs2GeomCone {
+ float innerLevel;
+ float innerAngle;
+ float outerLevel;
+ float outerAngle;
+};
+
+struct OrbisNgs2GeomRolloff {
+ u32 model;
+ float maxDistance;
+ float rolloffFactor;
+ float referenceDistance;
+};
+
+struct OrbisNgs2GeomListenerParam {
+ OrbisNgs2GeomVector position;
+ OrbisNgs2GeomVector orientFront;
+ OrbisNgs2GeomVector orientUp;
+ OrbisNgs2GeomVector velocity;
+ float soundSpeed;
+ u32 reserved[2];
+};
+
+struct OrbisNgs2GeomListenerWork {
+ float matrix[4][4];
+ OrbisNgs2GeomVector velocity;
+ float soundSpeed;
+ u32 coordinate;
+ u32 reserved[3];
+};
+
+struct OrbisNgs2GeomSourceParam {
+ OrbisNgs2GeomVector position;
+ OrbisNgs2GeomVector velocity;
+ OrbisNgs2GeomVector direction;
+ OrbisNgs2GeomCone cone;
+ OrbisNgs2GeomRolloff rolloff;
+ float dopplerFactor;
+ float fbwLevel;
+ float lfeLevel;
+ float maxLevel;
+ float minLevel;
+ float radius;
+ u32 numSpeakers;
+ u32 matrixFormat;
+ u32 reserved[2];
+};
+
+struct OrbisNgs2GeomA3dAttribute {
+ OrbisNgs2GeomVector position;
+ float volume;
+ u32 reserved[4];
+};
+
+struct OrbisNgs2GeomAttribute {
+ float pitchRatio;
+ float aLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS * ORBIS_NGS2_MAX_VOICE_CHANNELS];
+
+ OrbisNgs2GeomA3dAttribute a3dAttrib;
+ u32 reserved[4];
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_impl.cpp b/src/core/libraries/ngs2/ngs2_impl.cpp
index b358a05f7..1248f76d7 100644
--- a/src/core/libraries/ngs2/ngs2_impl.cpp
+++ b/src/core/libraries/ngs2/ngs2_impl.cpp
@@ -12,153 +12,171 @@ using namespace Libraries::Kernel;
namespace Libraries::Ngs2 {
-s32 Ngs2::ReportInvalid(Ngs2Handle* handle, u32 handle_type) const {
- uintptr_t hAddress = reinterpret_cast(handle);
- switch (handle_type) {
+s32 HandleReportInvalid(OrbisNgs2Handle handle, u32 handleType) {
+ switch (handleType) {
case 1:
- LOG_ERROR(Lib_Ngs2, "Invalid system handle {}", hAddress);
+ LOG_ERROR(Lib_Ngs2, "Invalid system handle {}", handle);
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
case 2:
- LOG_ERROR(Lib_Ngs2, "Invalid rack handle {}", hAddress);
+ LOG_ERROR(Lib_Ngs2, "Invalid rack handle {}", handle);
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
case 4:
- LOG_ERROR(Lib_Ngs2, "Invalid voice handle {}", hAddress);
+ LOG_ERROR(Lib_Ngs2, "Invalid voice handle {}", handle);
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
case 8:
- LOG_ERROR(Lib_Ngs2, "Invalid report handle {}", hAddress);
+ LOG_ERROR(Lib_Ngs2, "Invalid report handle {}", handle);
return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
default:
- LOG_ERROR(Lib_Ngs2, "Invalid handle {}", hAddress);
+ LOG_ERROR(Lib_Ngs2, "Invalid handle {}", handle);
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
}
}
-s32 Ngs2::HandleSetup(Ngs2Handle* handle, void* data, std::atomic* atomic, u32 type,
- u32 flags) {
- handle->dataPointer = data;
- handle->atomicPtr = atomic;
- handle->handleType = type;
- handle->flags_unk = flags;
- return ORBIS_OK;
+void* MemoryClear(void* buffer, size_t size) {
+ return memset(buffer, 0, size);
}
-s32 Ngs2::HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut) {
- if (handle && handle->selfPointer == handle) {
- std::atomic* tmp_atomic = handle->atomicPtr;
- if (tmp_atomic && handle->handleType == hType) {
- while (tmp_atomic->load() != 0) {
- u32 expected = 1;
- if (tmp_atomic->compare_exchange_strong(expected, 0)) {
- if (dataOut) {
- dataOut = handle->dataPointer;
- }
- // sceNgs2MemoryClear(handle, 32);
- return ORBIS_OK;
- }
- tmp_atomic = handle->atomicPtr;
- }
- }
- }
- return this->ReportInvalid(handle, hType);
-}
-
-s32 Ngs2::HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut) {
- if (!handle) {
- return this->ReportInvalid(handle, 0);
- }
-
- if (handle->selfPointer != handle || !handle->atomicPtr || !handle->dataPointer ||
- (~hType & handle->handleType)) {
- return this->ReportInvalid(handle, handle->handleType);
- }
-
- std::atomic* atomic = handle->atomicPtr;
- while (true) {
- u32 i = atomic->load();
- if (i == 0) {
- return this->ReportInvalid(handle, handle->handleType);
- }
- if (atomic->compare_exchange_strong(i, i + 1)) {
- break;
- }
- }
-
- if (handleOut) {
- handleOut = handle;
+s32 StackBufferClose(StackBuffer* stackBuffer, size_t* outTotalSize) {
+ if (outTotalSize) {
+ *outTotalSize = stackBuffer->usedSize + stackBuffer->alignment;
}
return ORBIS_OK;
}
-s32 Ngs2::HandleLeave(Ngs2Handle* handle) {
- std::atomic* tmp_atomic;
- u32 i;
- do {
- tmp_atomic = handle->atomicPtr;
- i = tmp_atomic->load();
- } while (!tmp_atomic->compare_exchange_strong(i, i - 1));
- return ORBIS_OK;
-}
+s32 StackBufferOpen(StackBuffer* stackBuffer, void* bufferStart, size_t bufferSize,
+ void** outBuffer, u8 flags) {
+ stackBuffer->top = outBuffer;
+ stackBuffer->base = bufferStart;
+ stackBuffer->size = (size_t)bufferStart;
+ stackBuffer->currentOffset = (size_t)bufferStart;
+ stackBuffer->usedSize = 0;
+ stackBuffer->totalSize = bufferSize;
+ stackBuffer->alignment = 8; // this is a fixed value
+ stackBuffer->flags = flags;
-s32 Ngs2::StackBufferOpen(StackBuffer* buf, void* base_addr, size_t size, void** stackTop,
- bool verify) {
- buf->top = stackTop;
- buf->base = base_addr;
- buf->curr = base_addr;
- buf->usedSize = 0;
- buf->totalSize = size;
- buf->alignment = 8;
- buf->isVerifyEnabled = verify;
-
- if (stackTop) {
- *stackTop = nullptr;
+ if (outBuffer != NULL) {
+ *outBuffer = NULL;
}
return ORBIS_OK;
}
-s32 Ngs2::StackBufferClose(StackBuffer* buf, size_t* usedSize) {
- if (usedSize) {
- *usedSize = buf->usedSize + buf->alignment;
+s32 SystemCleanup(OrbisNgs2Handle systemHandle, OrbisNgs2ContextBufferInfo* outInfo) {
+ if (!systemHandle) {
+ return ORBIS_NGS2_ERROR_INVALID_HANDLE;
}
+ // TODO
+
return ORBIS_OK;
}
-s32 Ngs2::SystemSetupCore(StackBuffer* buf, SystemOptions* options, Ngs2Handle** sysOut) {
+s32 SystemSetupCore(StackBuffer* stackBuffer, const OrbisNgs2SystemOption* option,
+ SystemInternal* outSystem) {
u32 maxGrainSamples = 512;
u32 numGrainSamples = 256;
u32 sampleRate = 48000;
- if (options) {
- maxGrainSamples = options->maxGrainSamples;
- numGrainSamples = options->numGrainSamples;
- sampleRate = options->sampleRate;
+ if (option) {
+ sampleRate = option->sampleRate;
+ maxGrainSamples = option->maxGrainSamples;
+ numGrainSamples = option->numGrainSamples;
}
- // Validate maxGrainSamples
- if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 0x3F) != 0) {
+ if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 63) != 0) {
LOG_ERROR(Lib_Ngs2, "Invalid system option (maxGrainSamples={},x64)", maxGrainSamples);
return ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES;
}
- // Validate numGrainSamples
- if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 0x3F) != 0) {
+ if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 63) != 0) {
LOG_ERROR(Lib_Ngs2, "Invalid system option (numGrainSamples={},x64)", numGrainSamples);
return ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES;
}
- // Validate sampleRate
if (sampleRate != 11025 && sampleRate != 12000 && sampleRate != 22050 && sampleRate != 24000 &&
- sampleRate != 44100 && sampleRate != 48000 && sampleRate != 88200 && sampleRate != 96000) {
+ sampleRate != 44100 && sampleRate != 48000 && sampleRate != 88200 && sampleRate != 96000 &&
+ sampleRate != 176400 && sampleRate != 192000) {
LOG_ERROR(Lib_Ngs2, "Invalid system option(sampleRate={}:44.1/48kHz series)", sampleRate);
return ORBIS_NGS2_ERROR_INVALID_SAMPLE_RATE;
}
- int result = ORBIS_OK;
+ return ORBIS_OK;
+}
+s32 SystemSetup(const OrbisNgs2SystemOption* option, OrbisNgs2ContextBufferInfo* hostBufferInfo,
+ OrbisNgs2BufferFreeHandler hostFree, OrbisNgs2Handle* outHandle) {
+ u8 optionFlags = 0;
+ StackBuffer stackBuffer;
+ SystemInternal setupResult;
+ void* systemList = NULL;
+ size_t requiredBufferSize = 0;
+ u32 result = ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE;
+
+ if (option) {
+ if (option->size != 64) {
+ LOG_ERROR(Lib_Ngs2, "Invalid system option size ({})", option->size);
+ return ORBIS_NGS2_ERROR_INVALID_OPTION_SIZE;
+ }
+ optionFlags = option->flags >> 31;
+ }
+
+ // Init
+ StackBufferOpen(&stackBuffer, NULL, 0, NULL, optionFlags);
+ result = SystemSetupCore(&stackBuffer, option, 0);
+
+ if (result < 0) {
+ return result;
+ }
+
+ StackBufferClose(&stackBuffer, &requiredBufferSize);
+
+ // outHandle unprovided
+ if (!outHandle) {
+ hostBufferInfo->hostBuffer = NULL;
+ hostBufferInfo->hostBufferSize = requiredBufferSize;
+ MemoryClear(&hostBufferInfo->reserved, sizeof(hostBufferInfo->reserved));
+ return ORBIS_OK;
+ }
+
+ if (!hostBufferInfo->hostBuffer) {
+ LOG_ERROR(Lib_Ngs2, "Invalid system buffer address ({})", hostBufferInfo->hostBuffer);
+ return ORBIS_NGS2_ERROR_INVALID_BUFFER_ADDRESS;
+ }
+
+ if (hostBufferInfo->hostBufferSize < requiredBufferSize) {
+ LOG_ERROR(Lib_Ngs2, "Invalid system buffer size ({}<{}[byte])",
+ hostBufferInfo->hostBufferSize, requiredBufferSize);
+ return ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE;
+ }
+
+ // Setup
+ StackBufferOpen(&stackBuffer, hostBufferInfo->hostBuffer, hostBufferInfo->hostBufferSize,
+ &systemList, optionFlags);
+ result = SystemSetupCore(&stackBuffer, option, &setupResult);
+
+ if (result < 0) {
+ return result;
+ }
+
+ StackBufferClose(&stackBuffer, &requiredBufferSize);
+
+ // Copy buffer results
+ setupResult.bufferInfo = *hostBufferInfo;
+ setupResult.hostFree = hostFree;
// TODO
+ // setupResult.systemList = systemList;
- return result; // Success
+ OrbisNgs2Handle systemHandle = setupResult.systemHandle;
+ if (hostBufferInfo->hostBufferSize >= requiredBufferSize) {
+ *outHandle = systemHandle;
+ return ORBIS_OK;
+ }
+
+ SystemCleanup(systemHandle, 0);
+
+ LOG_ERROR(Lib_Ngs2, "Invalid system buffer size ({}<{}[byte])", hostBufferInfo->hostBufferSize,
+ requiredBufferSize);
+ return ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE;
}
} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_impl.h b/src/core/libraries/ngs2/ngs2_impl.h
index fea87c51c..7be0f89cc 100644
--- a/src/core/libraries/ngs2/ngs2_impl.h
+++ b/src/core/libraries/ngs2/ngs2_impl.h
@@ -3,23 +3,176 @@
#pragma once
-#include "ngs2.h"
+#include "core/libraries/kernel/threads/pthread.h"
namespace Libraries::Ngs2 {
-class Ngs2 {
-public:
- s32 ReportInvalid(Ngs2Handle* handle, u32 handle_type) const;
- s32 HandleSetup(Ngs2Handle* handle, void* data, std::atomic* atomic, u32 type, u32 flags);
- s32 HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut);
- s32 HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut);
- s32 HandleLeave(Ngs2Handle* handle);
- s32 StackBufferOpen(StackBuffer* buf, void* base_addr, size_t size, void** stackTop,
- bool verify);
- s32 StackBufferClose(StackBuffer* buf, size_t* usedSize);
- s32 SystemSetupCore(StackBuffer* buf, SystemOptions* options, Ngs2Handle** sysOut);
+static const int ORBIS_NGS2_SYSTEM_NAME_LENGTH = 16;
+static const int ORBIS_NGS2_RACK_NAME_LENGTH = 16;
-private:
+typedef uintptr_t OrbisNgs2Handle;
+
+struct OrbisNgs2ContextBufferInfo {
+ void* hostBuffer;
+ size_t hostBufferSize;
+ uintptr_t reserved[5];
+ uintptr_t userData;
};
+struct OrbisNgs2SystemOption {
+ size_t size;
+ char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH];
+
+ u32 flags;
+ u32 maxGrainSamples;
+ u32 numGrainSamples;
+ u32 sampleRate;
+ u32 aReserved[6];
+};
+
+typedef s32 (*OrbisNgs2BufferAllocHandler)(OrbisNgs2ContextBufferInfo* ioBufferInfo);
+typedef s32 (*OrbisNgs2BufferFreeHandler)(OrbisNgs2ContextBufferInfo* ioBufferInfo);
+
+struct OrbisNgs2SystemInfo {
+ char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH]; // 0
+
+ OrbisNgs2Handle systemHandle; // 16
+ OrbisNgs2ContextBufferInfo bufferInfo; // 24
+
+ u32 uid; // 88
+ u32 minGrainSamples; // 92
+ u32 maxGrainSamples; // 96
+
+ u32 stateFlags; // 100
+ u32 rackCount; // 104
+ float lastRenderRatio; // 108
+ s64 lastRenderTick; // 112
+ s64 renderCount; // 120
+ u32 sampleRate; // 128
+ u32 numGrainSamples; // 132
+};
+
+struct OrbisNgs2RackInfo {
+ char name[ORBIS_NGS2_RACK_NAME_LENGTH]; // 0
+
+ OrbisNgs2Handle rackHandle; // 16
+ OrbisNgs2ContextBufferInfo bufferInfo; // 24
+
+ OrbisNgs2Handle ownerSystemHandle; // 88
+
+ u32 type; // 96
+ u32 rackId; // 100
+ u32 uid; // 104
+ u32 minGrainSamples; // 108
+ u32 maxGrainSamples; // 112
+ u32 maxVoices; // 116
+ u32 maxChannelWorks; // 120
+ u32 maxInputs; // 124
+ u32 maxMatrices; // 128
+ u32 maxPorts; // 132
+
+ u32 stateFlags; // 136
+ float lastProcessRatio; // 140
+ u64 lastProcessTick; // 144
+ u64 renderCount; // 152
+ u32 activeVoiceCount; // 160
+ u32 activeChannelWorkCount; // 164
+};
+
+struct StackBuffer {
+ void** top;
+ void* base;
+ size_t size;
+ size_t currentOffset;
+ size_t usedSize;
+ size_t totalSize;
+ size_t alignment;
+ u8 flags;
+ char padding[7];
+};
+
+struct SystemInternal {
+ // setup init
+ char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH]; // 0
+ OrbisNgs2ContextBufferInfo bufferInfo; // 16
+ OrbisNgs2BufferFreeHandler hostFree; // 80
+ OrbisNgs2Handle systemHandle; // 88
+ void* unknown1; // 96
+ void* unknown2; // 104
+ OrbisNgs2Handle rackHandle; // 112
+ uintptr_t* userData; // 120
+ SystemInternal* systemList; // 128
+ StackBuffer* stackBuffer; // 136
+ OrbisNgs2SystemInfo ownerSystemInfo; // 144
+
+ struct rackList {
+ void* prev;
+ void* next;
+ void* unknown;
+ };
+
+ rackList rackListPreset; // 152
+ rackList rackListNormal; // 176
+ rackList rackListMaster; // 200
+
+ void* unknown3; // 208
+ void* systemListPrev; // 216
+ void* unknown4; // 224
+ void* systemListNext; // 232
+ void* rackFunction; // 240
+
+ Kernel::PthreadMutex processLock; // 248
+ u32 hasProcessMutex; // 256
+ u32 unknown5; // 260
+ Kernel::PthreadMutex flushLock; // 264
+ u32 hasFlushMutex; // 272
+ u32 unknown6; // 276
+
+ // info
+ u64 lastRenderTick; // 280
+ u64 renderCount; // 288
+ u32 isActive; // 296
+ std::atomic lockCount; // 300
+ u32 uid; // 304
+ u32 systemType; // 308
+
+ struct {
+ u8 isBufferValid : 1;
+ u8 isRendering : 1;
+ u8 isSorted : 1;
+ u8 isFlushReady : 1;
+ } flags; // 312
+
+ u16 currentMaxGrainSamples; // 316
+ u16 minGrainSamples; // 318
+ u16 maxGrainSamples; // 320
+ u16 numGrainSamples; // 322
+ u32 currentNumGrainSamples; // 324
+ u32 sampleRate; // 328
+ u32 currentSampleRate; // 332
+ u32 rackCount; // 336
+ float lastRenderRatio; // 340
+ float cpuLoad; // 344
+};
+
+struct HandleInternal {
+ HandleInternal* selfPtr; // 0
+ SystemInternal* systemData; // 8
+ std::atomic refCount; // 16
+ u32 handleType; // 24
+ u32 handleID; // 28
+};
+
+s32 StackBufferClose(StackBuffer* stackBuffer, size_t* outTotalSize);
+s32 StackBufferOpen(StackBuffer* stackBuffer, void* buffer, size_t bufferSize, void** outBuffer,
+ u8 flags);
+s32 SystemSetupCore(StackBuffer* stackBuffer, const OrbisNgs2SystemOption* option,
+ SystemInternal* outSystem);
+
+s32 HandleReportInvalid(OrbisNgs2Handle handle, u32 handleType);
+void* MemoryClear(void* buffer, size_t size);
+s32 SystemCleanup(OrbisNgs2Handle systemHandle, OrbisNgs2ContextBufferInfo* outInfo);
+s32 SystemSetup(const OrbisNgs2SystemOption* option, OrbisNgs2ContextBufferInfo* hostBufferInfo,
+ OrbisNgs2BufferFreeHandler hostFree, OrbisNgs2Handle* outHandle);
+
} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_mastering.cpp b/src/core/libraries/ngs2/ngs2_mastering.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_mastering.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_mastering.h b/src/core/libraries/ngs2/ngs2_mastering.h
new file mode 100644
index 000000000..e0ba478c3
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_mastering.h
@@ -0,0 +1,81 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Mastering;
+
+struct OrbisNgs2MasteringRackOption {
+ OrbisNgs2RackOption rackOption;
+ u32 maxChannels;
+ u32 numPeakMeterBlocks;
+};
+
+struct OrbisNgs2MasteringVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 numInputChannels;
+ u32 flags;
+};
+
+struct OrbisNgs2MasteringVoiceMatrixParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 type;
+ u32 numLevels;
+ const float* aLevel;
+};
+
+struct OrbisNgs2MasteringVoiceLfeParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 enableFlag;
+ u32 fc;
+};
+
+struct OrbisNgs2MasteringVoiceLimiterParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 enableFlag;
+ float threshold;
+};
+
+struct OrbisNgs2MasteringVoiceGainParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ float fbwLevel;
+ float lfeLevel;
+};
+
+struct OrbisNgs2MasteringVoiceOutputParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 outputId;
+ u32 reserved;
+};
+
+struct OrbisNgs2MasteringVoicePeakMeterParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 enableFlag;
+ u32 reserved;
+};
+
+struct OrbisNgs2MasteringVoiceState {
+ OrbisNgs2VoiceState voiceState;
+ float limiterPeakLevel;
+ float limiterPressLevel;
+ float aInputPeakHeight[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+ float aOutputPeakHeight[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+};
+
+struct OrbisNgs2MasteringRackInfo {
+ OrbisNgs2RackInfo rackInfo;
+ u32 maxChannels;
+ u32 reserved;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_pan.cpp b/src/core/libraries/ngs2/ngs2_pan.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_pan.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_pan.h b/src/core/libraries/ngs2/ngs2_pan.h
new file mode 100644
index 000000000..d39ec67cd
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_pan.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Pan;
+
+struct OrbisNgs2PanParam {
+ float angle;
+ float distance;
+ float fbwLevel;
+ float lfeLevel;
+};
+
+struct OrbisNgs2PanWork {
+ float aSpeakerAngle[ORBIS_NGS2_MAX_VOICE_CHANNELS];
+ float unitAngle;
+ u32 numSpeakers;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_report.cpp b/src/core/libraries/ngs2/ngs2_report.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_report.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_report.h b/src/core/libraries/ngs2/ngs2_report.h
new file mode 100644
index 000000000..88f6d1df0
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_report.h
@@ -0,0 +1,78 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+#include // va_list
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Report;
+
+struct OrbisNgs2ReportDataHeader {
+ size_t size;
+ OrbisNgs2Handle handle;
+ u32 type;
+ s32 result;
+};
+
+typedef void (*OrbisNgs2ReportHandler)(const OrbisNgs2ReportDataHeader* data, uintptr_t userData);
+
+struct OrbisNgs2ReportMessageData {
+ OrbisNgs2ReportDataHeader header;
+ const char* message;
+};
+
+struct OrbisNgs2ReportApiData {
+ OrbisNgs2ReportDataHeader header;
+ const char* functionName;
+ const char* format;
+ va_list argument;
+};
+
+struct OrbisNgs2ReportControlData {
+ OrbisNgs2ReportDataHeader header;
+ const OrbisNgs2VoiceParamHeader* param;
+};
+
+struct OrbisNgs2ReportOutputData {
+ OrbisNgs2ReportDataHeader header;
+ const OrbisNgs2RenderBufferInfo* bufferInfo;
+
+ u32 bufferIndex;
+ u32 sampleRate;
+ u32 numGrainSamples;
+ u32 reserved;
+};
+
+struct OrbisNgs2ReportCpuLoadData {
+ OrbisNgs2ReportDataHeader header;
+ float totalRatio;
+ float flushRatio;
+ float processRatio;
+ float feedbackRatio;
+};
+
+struct OrbisNgs2ReportRenderStateData {
+ OrbisNgs2ReportDataHeader header;
+ u32 state;
+ u32 reserved;
+};
+
+struct OrbisNgs2ReportVoiceWaveformData {
+ OrbisNgs2ReportDataHeader header;
+ u32 location;
+ u32 waveformType;
+ u32 numChannels;
+ u32 sampleRate;
+ u32 numGrainSamples;
+ u32 reserved;
+ void* const* aData;
+};
+
+s32 PS4_SYSV_ABI sceNgs2ReportRegisterHandler(u32 reportType, OrbisNgs2ReportHandler handler,
+ uintptr_t userData, OrbisNgs2Handle* outHandle);
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_reverb.cpp b/src/core/libraries/ngs2/ngs2_reverb.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_reverb.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_reverb.h b/src/core/libraries/ngs2/ngs2_reverb.h
new file mode 100644
index 000000000..715d7480a
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_reverb.h
@@ -0,0 +1,61 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Reverb;
+
+struct OrbisNgs2ReverbRackOption {
+ OrbisNgs2RackOption rackOption;
+ u32 maxChannels;
+ u32 reverbSize;
+};
+
+struct OrbisNgs2ReverbI3DL2Param {
+ float wet;
+ float dry;
+ s32 room;
+ s32 roomHF;
+ u32 reflectionPattern;
+ float decayTime;
+ float decayHFRatio;
+ s32 reflections;
+ float reflectionsDelay;
+ s32 reverb;
+ float reverbDelay;
+ float diffusion;
+ float density;
+ float HFReference;
+ u32 reserve[8];
+};
+
+struct OrbisNgs2ReverbVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 numInputChannels;
+ u32 numOutputChannels;
+ u32 flags;
+ u32 reserved;
+};
+
+struct OrbisNgs2ReverbVoiceI3DL2Param {
+ OrbisNgs2VoiceParamHeader header;
+
+ OrbisNgs2ReverbI3DL2Param i3dl2;
+};
+
+struct OrbisNgs2ReverbVoiceState {
+ OrbisNgs2VoiceState voiceState;
+};
+
+struct OrbisNgs2ReverbRackInfo {
+ OrbisNgs2RackInfo rackInfo;
+ u32 maxChannels;
+ u32 reverbSize;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_sampler.cpp b/src/core/libraries/ngs2/ngs2_sampler.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_sampler.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_sampler.h b/src/core/libraries/ngs2/ngs2_sampler.h
new file mode 100644
index 000000000..0842b9cb2
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_sampler.h
@@ -0,0 +1,162 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Sampler;
+
+struct OrbisNgs2SamplerRackOption {
+ OrbisNgs2RackOption rackOption;
+ u32 maxChannelWorks;
+ u32 maxCodecCaches;
+ u32 maxWaveformBlocks;
+ u32 maxEnvelopePoints;
+ u32 maxFilters;
+ u32 maxAtrac9Decoders;
+ u32 maxAtrac9ChannelWorks;
+ u32 maxAjmAtrac9Decoders;
+ u32 numPeakMeterBlocks;
+};
+
+struct OrbisNgs2SamplerVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ OrbisNgs2WaveformFormat format;
+ u32 flags;
+ u32 reserved;
+};
+
+struct OrbisNgs2SamplerVoiceWaveformBlocksParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ const void* data;
+ u32 flags;
+ u32 numBlocks;
+ const OrbisNgs2WaveformBlock* aBlock;
+ // Blocks
+};
+
+struct OrbisNgs2SamplerVoiceWaveformAddressParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ const void* from;
+ const void* to;
+};
+
+struct OrbisNgs2SamplerVoiceWaveformFrameOffsetParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 frameOffset;
+ u32 reserved;
+};
+
+struct OrbisNgs2SamplerVoiceExitLoopParam {
+ OrbisNgs2VoiceParamHeader header;
+};
+
+struct OrbisNgs2SamplerVoicePitchParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ float ratio;
+ u32 reserved;
+};
+
+struct OrbisNgs2SamplerVoiceEnvelopeParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 numForwardPoints;
+ u32 numReleasePoints;
+ const OrbisNgs2EnvelopePoint* aPoint;
+};
+
+struct OrbisNgs2SamplerVoiceDistortionParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 flags;
+ float a;
+ float b;
+ float clip;
+ float gate;
+ float wetLevel;
+ float dryLevel;
+ u32 reserved;
+};
+
+struct OrbisNgs2SamplerVoiceUserFxParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ OrbisNgs2UserFxProcessHandler handler;
+
+ uintptr_t userData0;
+ uintptr_t userData1;
+ uintptr_t userData2;
+};
+
+struct OrbisNgs2SamplerVoicePeakMeterParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 enableFlag;
+ u32 reserved;
+};
+
+struct OrbisNgs2SamplerVoiceFilterParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 index;
+ u32 location;
+ u32 type;
+ u32 channelMask;
+ union {
+ struct {
+ float i0;
+ float i1;
+ float i2;
+ float o1;
+ float o2;
+ } direct;
+ struct {
+ float fc;
+ float q;
+ float level;
+ u32 reserved;
+ u32 reserved2;
+ } fcq;
+ } param;
+ u32 reserved3;
+};
+
+struct OrbisNgs2SamplerVoiceNumFilters {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 numFilters;
+ u32 reserved;
+};
+
+struct OrbisNgs2SamplerVoiceState {
+ OrbisNgs2VoiceState voiceState;
+ float envelopeHeight;
+ float peakHeight;
+ u32 reserved;
+ u64 numDecodedSamples;
+ u64 decodedDataSize;
+ u64 userData;
+ const void* waveformData;
+};
+
+struct OrbisNgs2SamplerRackInfo {
+ OrbisNgs2RackInfo rackInfo;
+ u32 maxChannelWorks;
+ u32 maxCodecCaches;
+ u32 maxWaveformBlocks;
+ u32 maxEnvelopePoints;
+ u32 maxFilters;
+ u32 maxAtrac9Decoders;
+ u32 maxAtrac9ChannelWorks;
+ u32 maxAjmAtrac9Decoders;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_submixer.cpp b/src/core/libraries/ngs2/ngs2_submixer.cpp
new file mode 100644
index 000000000..8c82e4e49
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_submixer.cpp
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ngs2_error.h"
+#include "ngs2_impl.h"
+
+#include "common/logging/log.h"
+#include "core/libraries/error_codes.h"
+
+using namespace Libraries::Kernel;
+
+namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
diff --git a/src/core/libraries/ngs2/ngs2_submixer.h b/src/core/libraries/ngs2/ngs2_submixer.h
new file mode 100644
index 000000000..df2d8a835
--- /dev/null
+++ b/src/core/libraries/ngs2/ngs2_submixer.h
@@ -0,0 +1,126 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "ngs2.h"
+
+namespace Libraries::Ngs2 {
+
+class Ngs2Submixer;
+
+struct OrbisNgs2SubmixerRackOption {
+ OrbisNgs2RackOption rackOption;
+ u32 maxChannels;
+ u32 maxEnvelopePoints;
+ u32 maxFilters;
+ u32 maxInputs;
+ u32 numPeakMeterBlocks;
+};
+
+struct OrbisNgs2SubmixerVoiceSetupParam {
+ OrbisNgs2VoiceParamHeader header;
+ u32 numIoChannels;
+ u32 flags;
+};
+
+struct OrbisNgs2SubmixerVoiceEnvelopeParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 numForwardPoints;
+ u32 numReleasePoints;
+ const OrbisNgs2EnvelopePoint* aPoint;
+};
+
+struct OrbisNgs2SubmixerVoiceCompressorParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 flags;
+ float threshold;
+ float ratio;
+ float knee;
+ float attackTime;
+ float releaseTime;
+ float level;
+ u32 reserved;
+};
+
+struct OrbisNgs2SubmixerVoiceDistortionParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 flags;
+ float a;
+ float b;
+ float clip;
+ float gate;
+ float wetLevel;
+ float dryLevel;
+ u32 reserved;
+};
+
+struct OrbisNgs2SubmixerVoiceUserFxParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ OrbisNgs2UserFxProcessHandler handler;
+
+ uintptr_t userData0;
+ uintptr_t userData1;
+ uintptr_t userData2;
+};
+
+struct OrbisNgs2SubmixerVoicePeakMeterParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 enableFlag;
+ u32 reserved;
+};
+
+struct OrbisNgs2SubmixerVoiceFilterParam {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 index;
+ u32 location;
+ u32 type;
+ u32 channelMask;
+ union {
+ struct {
+ float i0;
+ float i1;
+ float i2;
+ float o1;
+ float o2;
+ } direct;
+ struct {
+ float fc;
+ float q;
+ float level;
+ u32 reserved;
+ u32 reserved2;
+ } fcq;
+ } param;
+ u32 reserved3;
+};
+
+struct OrbisNgs2SubmixerVoiceNumFilters {
+ OrbisNgs2VoiceParamHeader header;
+
+ u32 numFilters;
+ u32 reserved;
+};
+
+struct OrbisNgs2SubmixerVoiceState {
+ OrbisNgs2VoiceState voiceState;
+ float envelopeHeight;
+ float peakHeight;
+ float compressorHeight;
+};
+
+struct OrbisNgs2SubmixerRackInfo {
+ OrbisNgs2RackInfo rackInfo;
+ u32 maxChannels;
+ u32 maxEnvelopePoints;
+ u32 maxFilters;
+ u32 maxInputs;
+};
+
+} // namespace Libraries::Ngs2
diff --git a/src/core/loader.cpp b/src/core/loader.cpp
deleted file mode 100644
index f80bfbb81..000000000
--- a/src/core/loader.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/io_file.h"
-#include "common/types.h"
-#include "loader.h"
-
-namespace Loader {
-
-FileTypes DetectFileType(const std::filesystem::path& filepath) {
- // No file loaded
- if (filepath.empty()) {
- return FileTypes::Unknown;
- }
- Common::FS::IOFile file;
- file.Open(filepath, Common::FS::FileAccessMode::Read);
- file.Seek(0);
- u32 magic;
- file.Read(magic);
- file.Close();
- switch (magic) {
- case PkgMagic:
- return FileTypes::Pkg;
- }
- return FileTypes::Unknown;
-}
-
-} // namespace Loader
diff --git a/src/core/loader.h b/src/core/loader.h
deleted file mode 100644
index 608970dca..000000000
--- a/src/core/loader.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-
-namespace Loader {
-
-constexpr static u32 PkgMagic = 0x544e437f;
-
-enum class FileTypes {
- Unknown,
- Pkg,
-};
-
-FileTypes DetectFileType(const std::filesystem::path& filepath);
-} // namespace Loader
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 98d587e00..8b108a654 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -38,6 +38,16 @@ void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1
bool use_extended_mem2) {
const bool is_neo = ::Libraries::Kernel::sceKernelIsNeoMode();
auto total_size = is_neo ? SCE_KERNEL_TOTAL_MEM_PRO : SCE_KERNEL_TOTAL_MEM;
+ if (Config::isDevKitConsole()) {
+ const auto old_size = total_size;
+ // Assuming 2gb is neo for now, will need to link it with sceKernelIsDevKit
+ total_size += is_neo ? 2_GB : 768_MB;
+ LOG_WARNING(Kernel_Vmm,
+ "Config::isDevKitConsole is enabled! Added additional {:s} of direct memory.",
+ is_neo ? "2 GB" : "768 MB");
+ LOG_WARNING(Kernel_Vmm, "Old Direct Size: {:#x} -> New Direct Size: {:#x}", old_size,
+ total_size);
+ }
if (!use_extended_mem1 && is_neo) {
total_size -= 256_MB;
}
diff --git a/src/emulator.cpp b/src/emulator.cpp
index 4ec62995b..5f94f008a 100644
--- a/src/emulator.cpp
+++ b/src/emulator.cpp
@@ -289,13 +289,12 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector ModulesToLoad{
+ constexpr std::array ModulesToLoad{
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
{"libSceUlt.sprx", nullptr},
{"libSceJson.sprx", nullptr},
{"libSceJson2.sprx", nullptr},
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
- {"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
{"libSceCesCs.sprx", nullptr},
{"libSceFont.sprx", nullptr},
diff --git a/src/images/controller_icon.png b/src/images/controller_icon.png
index 40c92a89b..0d5556329 100644
Binary files a/src/images/controller_icon.png and b/src/images/controller_icon.png differ
diff --git a/src/images/fullscreen_icon.png b/src/images/fullscreen_icon.png
new file mode 100644
index 000000000..719ffe4a1
Binary files /dev/null and b/src/images/fullscreen_icon.png differ
diff --git a/src/images/pause_icon.png b/src/images/pause_icon.png
index 5375689b7..86bbc6acb 100644
Binary files a/src/images/pause_icon.png and b/src/images/pause_icon.png differ
diff --git a/src/images/play_icon.png b/src/images/play_icon.png
index 2815be39d..d50d404b7 100644
Binary files a/src/images/play_icon.png and b/src/images/play_icon.png differ
diff --git a/src/images/refresh_icon.png b/src/images/refresh_icon.png
deleted file mode 100644
index 00fe69c20..000000000
Binary files a/src/images/refresh_icon.png and /dev/null differ
diff --git a/src/images/refreshlist_icon.png b/src/images/refreshlist_icon.png
new file mode 100644
index 000000000..7de6685b2
Binary files /dev/null and b/src/images/refreshlist_icon.png differ
diff --git a/src/images/restart_game_icon.png b/src/images/restart_game_icon.png
new file mode 100644
index 000000000..1e549e101
Binary files /dev/null and b/src/images/restart_game_icon.png differ
diff --git a/src/images/settings_icon.png b/src/images/settings_icon.png
index c88cd7a6f..81127bfa3 100644
Binary files a/src/images/settings_icon.png and b/src/images/settings_icon.png differ
diff --git a/src/images/stop_icon.png b/src/images/stop_icon.png
index 74c615f65..55b6b01c7 100644
Binary files a/src/images/stop_icon.png and b/src/images/stop_icon.png differ
diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp
index 4c0607571..170215f3d 100644
--- a/src/qt_gui/game_list_frame.cpp
+++ b/src/qt_gui/game_list_frame.cpp
@@ -185,7 +185,8 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
// Recompute if opacity changed or we switched to a different game
if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
- QImage original_image(QString::fromStdString(game.pic_path.string()));
+ auto image_path = game.pic_path.u8string();
+ QImage original_image(QString::fromStdString({image_path.begin(), image_path.end()}));
if (!original_image.isNull()) {
backgroundImage = m_game_list_utils.ChangeImageOpacity(
original_image, original_image.rect(), opacity / 100.0f);
diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h
index 0cc0e48dc..7dcb006ba 100644
--- a/src/qt_gui/gui_context_menus.h
+++ b/src/qt_gui/gui_context_menus.h
@@ -7,7 +7,6 @@
#include
#include
#include
-#include
#include
#include
@@ -599,30 +598,6 @@ public:
return -1;
}
- void RequestGameMenuPKGViewer(
- const QPoint& pos, QStringList m_pkg_app_list, QTreeWidget* treeWidget,
- std::function InstallDragDropPkg) {
- QPoint global_pos = treeWidget->viewport()->mapToGlobal(pos); // context menu position
- QTreeWidgetItem* currentItem = treeWidget->currentItem(); // current clicked item
- int itemIndex = GetRowIndex(treeWidget, currentItem); // row
-
- QMenu menu(treeWidget);
- QAction installPackage(tr("Install PKG"), treeWidget);
-
- menu.addAction(&installPackage);
-
- auto selected = menu.exec(global_pos);
- if (!selected) {
- return;
- }
-
- if (selected == &installPackage) {
- QStringList pkg_app_ = m_pkg_app_list[itemIndex].split(";;");
- std::filesystem::path path = Common::FS::PathFromQString(pkg_app_[9]);
- InstallDragDropPkg(path, 1, 1);
- }
- }
-
private:
bool convertPngToIco(const QString& pngFilePath, const QString& icoFilePath) {
// Load the PNG image
diff --git a/src/qt_gui/install_dir_select.cpp b/src/qt_gui/install_dir_select.cpp
deleted file mode 100644
index e90a10ee6..000000000
--- a/src/qt_gui/install_dir_select.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "install_dir_select.h"
-
-InstallDirSelect::InstallDirSelect() : selected_dir() {
- auto install_dirs = Config::getGameInstallDirs();
- selected_dir = install_dirs.empty() ? "" : install_dirs.front();
-
- if (!install_dirs.empty() && install_dirs.size() == 1) {
- accept();
- }
-
- auto layout = new QVBoxLayout(this);
-
- layout->addWidget(SetupInstallDirList());
- layout->addStretch();
- layout->addWidget(SetupDialogActions());
-
- setWindowTitle(tr("shadPS4 - Choose directory"));
- setWindowIcon(QIcon(":images/shadps4.ico"));
-}
-
-InstallDirSelect::~InstallDirSelect() {}
-
-QWidget* InstallDirSelect::SetupInstallDirList() {
- auto group = new QGroupBox(tr("Select which directory you want to install to."));
- auto vlayout = new QVBoxLayout();
-
- auto m_path_list = new QListWidget();
- QList qt_list;
- for (const auto& str : Config::getGameInstallDirs()) {
- QString installDirPath;
- Common::FS::PathToQString(installDirPath, str);
- qt_list.append(installDirPath);
- }
- m_path_list->insertItems(0, qt_list);
- m_path_list->setSpacing(1);
-
- connect(m_path_list, &QListWidget::itemClicked, this, &InstallDirSelect::setSelectedDirectory);
- connect(m_path_list, &QListWidget::itemActivated, this,
- &InstallDirSelect::setSelectedDirectory);
-
- vlayout->addWidget(m_path_list);
-
- auto checkbox = new QCheckBox(tr("Install All Queued to Selected Folder"));
- connect(checkbox, &QCheckBox::toggled, this, &InstallDirSelect::setUseForAllQueued);
- vlayout->addWidget(checkbox);
-
- auto checkbox2 = new QCheckBox(tr("Delete PKG File on Install"));
- connect(checkbox2, &QCheckBox::toggled, this, &InstallDirSelect::setDeleteFileOnInstall);
- vlayout->addWidget(checkbox2);
-
- group->setLayout(vlayout);
- return group;
-}
-
-void InstallDirSelect::setSelectedDirectory(QListWidgetItem* item) {
- if (item) {
- const auto highlighted_path = Common::FS::PathFromQString(item->text());
- if (!highlighted_path.empty()) {
- selected_dir = highlighted_path;
- }
- }
-}
-
-void InstallDirSelect::setUseForAllQueued(bool enabled) {
- use_for_all_queued = enabled;
-}
-
-void InstallDirSelect::setDeleteFileOnInstall(bool enabled) {
- delete_file_on_install = enabled;
-}
-
-QWidget* InstallDirSelect::SetupDialogActions() {
- auto actions = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
-
- connect(actions, &QDialogButtonBox::accepted, this, &InstallDirSelect::accept);
- connect(actions, &QDialogButtonBox::rejected, this, &InstallDirSelect::reject);
-
- return actions;
-}
diff --git a/src/qt_gui/install_dir_select.h b/src/qt_gui/install_dir_select.h
deleted file mode 100644
index e11cbf381..000000000
--- a/src/qt_gui/install_dir_select.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include
-
-#include "common/config.h"
-#include "common/path_util.h"
-
-class QLineEdit;
-
-class InstallDirSelect final : public QDialog {
- Q_OBJECT
-
-public:
- InstallDirSelect();
- ~InstallDirSelect();
-
- std::filesystem::path getSelectedDirectory() {
- return selected_dir;
- }
-
- bool useForAllQueued() {
- return use_for_all_queued;
- }
-
- bool deleteFileOnInstall() {
- return delete_file_on_install;
- }
-
-private:
- QWidget* SetupInstallDirList();
- QWidget* SetupDialogActions();
- void setSelectedDirectory(QListWidgetItem* item);
- void setDeleteFileOnInstall(bool enabled);
- void setUseForAllQueued(bool enabled);
- std::filesystem::path selected_dir;
- bool delete_file_on_install = false;
- bool use_for_all_queued = false;
-};
diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp
index d70294e40..bd9dca6ce 100644
--- a/src/qt_gui/main.cpp
+++ b/src/qt_gui/main.cpp
@@ -157,13 +157,8 @@ int main(int argc, char* argv[]) {
}
}
- bool allInstallDirsDisabled =
- std::all_of(Config::getGameInstallDirsEnabled().begin(),
- Config::getGameInstallDirsEnabled().end(), [](bool val) { return !val; });
-
- // If no game directory is set and no command line argument, prompt for it
- if (Config::getGameInstallDirs().empty() && allInstallDirsDisabled &&
- !has_command_line_argument) {
+ // If no game directories are set and no command line argument, prompt for it
+ if (Config::getGameInstallDirsEnabled().empty() && !has_command_line_argument) {
GameInstallDialog dlg;
dlg.exec();
}
diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp
index 27551e997..5d8f8e717 100644
--- a/src/qt_gui/main_window.cpp
+++ b/src/qt_gui/main_window.cpp
@@ -1,10 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "SDL3/SDL_events.h"
+
#include
#include
#include
#include
+#include
#include "about_dialog.h"
#include "cheats_patches.h"
@@ -17,10 +20,7 @@
#include "common/string_util.h"
#include "common/version.h"
#include "control_settings.h"
-#include "core/file_format/pkg.h"
-#include "core/loader.h"
#include "game_install_dialog.h"
-#include "install_dir_select.h"
#include "kbm_gui.h"
#include "main_window.h"
#include "settings_dialog.h"
@@ -132,23 +132,160 @@ void MainWindow::CreateActions() {
m_theme_act_group->addAction(ui->setThemeOled);
}
+void MainWindow::PauseGame() {
+ SDL_Event event;
+ SDL_memset(&event, 0, sizeof(event));
+ event.type = SDL_EVENT_TOGGLE_PAUSE;
+ is_paused = !is_paused;
+ UpdateToolbarButtons();
+ SDL_PushEvent(&event);
+}
+
+void MainWindow::toggleLabelsUnderIcons() {
+ bool showLabels = ui->toggleLabelsAct->isChecked();
+ Config::setShowLabelsUnderIcons();
+ UpdateToolbarLabels();
+ if (isGameRunning) {
+ UpdateToolbarButtons();
+ }
+}
+
+void MainWindow::toggleFullscreen() {
+ SDL_Event event;
+ SDL_memset(&event, 0, sizeof(event));
+ event.type = SDL_EVENT_TOGGLE_FULLSCREEN;
+ SDL_PushEvent(&event);
+}
+
+QWidget* MainWindow::createButtonWithLabel(QPushButton* button, const QString& labelText,
+ bool showLabel) {
+ QWidget* container = new QWidget(this);
+ QVBoxLayout* layout = new QVBoxLayout(container);
+ layout->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(button);
+
+ QLabel* label = nullptr;
+ if (showLabel && ui->toggleLabelsAct->isChecked()) {
+ label = new QLabel(labelText, this);
+ label->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
+ layout->addWidget(label);
+ button->setToolTip("");
+ } else {
+ button->setToolTip(labelText);
+ }
+
+ container->setLayout(layout);
+ container->setProperty("buttonLabel", QVariant::fromValue(label));
+ return container;
+}
+
+QWidget* createSpacer(QWidget* parent) {
+ QWidget* spacer = new QWidget(parent);
+ spacer->setFixedWidth(15);
+ spacer->setFixedHeight(15);
+ return spacer;
+}
+
void MainWindow::AddUiWidgets() {
// add toolbar widgets
QApplication::setStyle("Fusion");
- ui->toolBar->setObjectName("mw_toolbar");
- ui->toolBar->addWidget(ui->playButton);
- ui->toolBar->addWidget(ui->pauseButton);
- ui->toolBar->addWidget(ui->stopButton);
- ui->toolBar->addWidget(ui->refreshButton);
- ui->toolBar->addWidget(ui->settingsButton);
- ui->toolBar->addWidget(ui->controllerButton);
- ui->toolBar->addWidget(ui->keyboardButton);
+
+ bool showLabels = ui->toggleLabelsAct->isChecked();
+ ui->toolBar->clear();
+
+ ui->toolBar->addWidget(createSpacer(this));
+ ui->toolBar->addWidget(createButtonWithLabel(ui->playButton, tr("Play"), showLabels));
+ ui->toolBar->addWidget(createButtonWithLabel(ui->pauseButton, tr("Pause"), showLabels));
+ ui->toolBar->addWidget(createButtonWithLabel(ui->stopButton, tr("Stop"), showLabels));
+ ui->toolBar->addWidget(createButtonWithLabel(ui->restartButton, tr("Restart"), showLabels));
+ ui->toolBar->addWidget(createSpacer(this));
+ ui->toolBar->addWidget(createButtonWithLabel(ui->settingsButton, tr("Settings"), showLabels));
+ ui->toolBar->addWidget(
+ createButtonWithLabel(ui->fullscreenButton, tr("Full Screen"), showLabels));
+ ui->toolBar->addWidget(createSpacer(this));
+ ui->toolBar->addWidget(
+ createButtonWithLabel(ui->controllerButton, tr("Controllers"), showLabels));
+ ui->toolBar->addWidget(createButtonWithLabel(ui->keyboardButton, tr("Keyboard"), showLabels));
+ ui->toolBar->addWidget(createSpacer(this));
QFrame* line = new QFrame(this);
- line->setFrameShape(QFrame::StyledPanel);
+ line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
+ line->setMinimumWidth(2);
ui->toolBar->addWidget(line);
- ui->toolBar->addWidget(ui->sizeSliderContainer);
- ui->toolBar->addWidget(ui->mw_searchbar);
+ ui->toolBar->addWidget(createSpacer(this));
+ if (showLabels) {
+ QLabel* pauseButtonLabel = ui->pauseButton->parentWidget()->findChild();
+ if (pauseButtonLabel) {
+ pauseButtonLabel->setVisible(false);
+ }
+ }
+ ui->toolBar->addWidget(
+ createButtonWithLabel(ui->refreshButton, tr("Refresh List"), showLabels));
+ ui->toolBar->addWidget(createSpacer(this));
+
+ QBoxLayout* toolbarLayout = new QBoxLayout(QBoxLayout::TopToBottom);
+ toolbarLayout->setSpacing(2);
+ toolbarLayout->setContentsMargins(2, 2, 2, 2);
+ ui->sizeSliderContainer->setFixedWidth(150);
+
+ QWidget* searchSliderContainer = new QWidget(this);
+ QBoxLayout* searchSliderLayout = new QBoxLayout(QBoxLayout::TopToBottom);
+ searchSliderLayout->setContentsMargins(0, 0, 6, 6);
+ searchSliderLayout->setSpacing(2);
+ ui->mw_searchbar->setFixedWidth(150);
+
+ searchSliderLayout->addWidget(ui->sizeSliderContainer);
+ searchSliderLayout->addWidget(ui->mw_searchbar);
+
+ searchSliderContainer->setLayout(searchSliderLayout);
+
+ ui->toolBar->addWidget(searchSliderContainer);
+
+ if (!showLabels) {
+ toolbarLayout->addWidget(searchSliderContainer);
+ }
+
+ ui->playButton->setVisible(true);
+ ui->pauseButton->setVisible(false);
+}
+
+void MainWindow::UpdateToolbarButtons() {
+ // add toolbar widgets when game is running
+ bool showLabels = ui->toggleLabelsAct->isChecked();
+
+ ui->playButton->setVisible(false);
+ ui->pauseButton->setVisible(true);
+
+ if (showLabels) {
+ QLabel* playButtonLabel = ui->playButton->parentWidget()->findChild();
+ if (playButtonLabel)
+ playButtonLabel->setVisible(false);
+ }
+
+ if (is_paused) {
+ ui->pauseButton->setIcon(ui->playButton->icon());
+ ui->pauseButton->setToolTip(tr("Resume"));
+ } else {
+ if (isIconBlack) {
+ ui->pauseButton->setIcon(QIcon(":images/pause_icon.png"));
+ } else {
+ ui->pauseButton->setIcon(RecolorIcon(QIcon(":images/pause_icon.png"), isWhite));
+ }
+ ui->pauseButton->setToolTip(tr("Pause"));
+ }
+
+ if (showLabels) {
+ QLabel* pauseButtonLabel = ui->pauseButton->parentWidget()->findChild