mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 08:22:32 +00:00
Merge branch 'shadps4-emu:main' into disable-heap-malloc
This commit is contained in:
commit
b354f104ce
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
namespace Audio {
|
namespace Audio {
|
||||||
|
|
||||||
|
constexpr int AUDIO_STREAM_BUFFER_THRESHOLD = 65536; // Define constant for buffer threshold
|
||||||
|
|
||||||
int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
||||||
Libraries::AudioOut::OrbisAudioOutParamFormat format) {
|
Libraries::AudioOut::OrbisAudioOutParamFormat format) {
|
||||||
using Libraries::AudioOut::OrbisAudioOutParamFormat;
|
using Libraries::AudioOut::OrbisAudioOutParamFormat;
|
||||||
@ -80,7 +82,7 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
|||||||
SDL_zero(fmt);
|
SDL_zero(fmt);
|
||||||
fmt.format = sampleFormat;
|
fmt.format = sampleFormat;
|
||||||
fmt.channels = port.channels_num;
|
fmt.channels = port.channels_num;
|
||||||
fmt.freq = 48000;
|
fmt.freq = freq; // Set frequency from the argument
|
||||||
port.stream =
|
port.stream =
|
||||||
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, NULL, NULL);
|
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, NULL, NULL);
|
||||||
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream));
|
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream));
|
||||||
@ -92,20 +94,27 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) {
|
s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) {
|
||||||
|
if (handle < 1 || handle > portsOut.size()) { // Add handle range check
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
return 0; // Nothing to output
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_lock lock{m_mutex};
|
std::shared_lock lock{m_mutex};
|
||||||
auto& port = portsOut[handle - 1];
|
auto& port = portsOut[handle - 1];
|
||||||
if (!port.isOpen) {
|
if (!port.isOpen) {
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
}
|
}
|
||||||
if (ptr == nullptr) {
|
|
||||||
return 0;
|
const size_t data_size = port.samples_num * port.sample_size * port.channels_num;
|
||||||
}
|
|
||||||
lock.unlock();
|
SDL_bool result = SDL_PutAudioStreamData(port.stream, ptr, data_size);
|
||||||
// TODO mixing channels
|
|
||||||
SDL_bool result = SDL_PutAudioStreamData(
|
lock.unlock(); // Unlock only after necessary operations
|
||||||
port.stream, ptr, port.samples_num * port.sample_size * port.channels_num);
|
|
||||||
// TODO find a correct value 8192 is estimated
|
while (SDL_GetAudioStreamAvailable(port.stream) > AUDIO_STREAM_BUFFER_THRESHOLD) {
|
||||||
while (SDL_GetAudioStreamAvailable(port.stream) > 65536) {
|
|
||||||
SDL_Delay(0);
|
SDL_Delay(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,12 +122,17 @@ s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) {
|
bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) {
|
||||||
|
if (handle < 1 || handle > portsOut.size()) { // Add handle range check
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
using Libraries::AudioOut::OrbisAudioOutParamFormat;
|
using Libraries::AudioOut::OrbisAudioOutParamFormat;
|
||||||
std::shared_lock lock{m_mutex};
|
std::shared_lock lock{m_mutex};
|
||||||
auto& port = portsOut[handle - 1];
|
auto& port = portsOut[handle - 1];
|
||||||
if (!port.isOpen) {
|
if (!port.isOpen) {
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < port.channels_num; i++, bitflag >>= 1u) {
|
for (int i = 0; i < port.channels_num; i++, bitflag >>= 1u) {
|
||||||
auto bit = bitflag & 0x1u;
|
auto bit = bitflag & 0x1u;
|
||||||
|
|
||||||
@ -152,6 +166,10 @@ bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SDLAudio::AudioOutGetStatus(s32 handle, int* type, int* channels_num) {
|
bool SDLAudio::AudioOutGetStatus(s32 handle, int* type, int* channels_num) {
|
||||||
|
if (handle < 1 || handle > portsOut.size()) { // Add handle range check
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_lock lock{m_mutex};
|
std::shared_lock lock{m_mutex};
|
||||||
auto& port = portsOut[handle - 1];
|
auto& port = portsOut[handle - 1];
|
||||||
*type = port.type;
|
*type = port.type;
|
||||||
|
@ -205,9 +205,9 @@ public:
|
|||||||
return WriteSpan(string);
|
return WriteSpan(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteBytes(const std::filesystem::path path, std::span<const u8> data) {
|
static size_t WriteBytes(const std::filesystem::path path, std::span<const u8> data) {
|
||||||
IOFile out(path, FileAccessMode::Write);
|
IOFile out(path, FileAccessMode::Write);
|
||||||
out.Write(data);
|
return out.Write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -249,12 +249,6 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||||||
file.Seek(currentPos);
|
file.Seek(currentPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract trophy files
|
|
||||||
if (!trp.Extract(extract_path)) {
|
|
||||||
// Do nothing some pkg come with no trp file.
|
|
||||||
// return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the seed
|
// Read the seed
|
||||||
std::array<u8, 16> seed;
|
std::array<u8, 16> seed;
|
||||||
if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) {
|
if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) {
|
||||||
|
@ -12,6 +12,7 @@ void TRP::GetNPcommID(const std::filesystem::path& trophyPath, int index) {
|
|||||||
std::filesystem::path trpPath = trophyPath / "sce_sys/npbind.dat";
|
std::filesystem::path trpPath = trophyPath / "sce_sys/npbind.dat";
|
||||||
Common::FS::IOFile npbindFile(trpPath, Common::FS::FileAccessMode::Read);
|
Common::FS::IOFile npbindFile(trpPath, Common::FS::FileAccessMode::Read);
|
||||||
if (!npbindFile.IsOpen()) {
|
if (!npbindFile.IsOpen()) {
|
||||||
|
LOG_CRITICAL(Common_Filesystem, "Failed to open npbind.dat file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!npbindFile.Seek(0x84 + (index * 0x180))) {
|
if (!npbindFile.Seek(0x84 + (index * 0x180))) {
|
||||||
@ -32,10 +33,10 @@ static void removePadding(std::vector<u8>& vec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TRP::Extract(const std::filesystem::path& trophyPath) {
|
bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string titleId) {
|
||||||
std::filesystem::path title = trophyPath.filename();
|
|
||||||
std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
|
std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
|
||||||
if (!std::filesystem::exists(gameSysDir)) {
|
if (!std::filesystem::exists(gameSysDir)) {
|
||||||
|
LOG_CRITICAL(Common_Filesystem, "Game sce_sys directory doesn't exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
||||||
@ -44,18 +45,21 @@ bool TRP::Extract(const std::filesystem::path& trophyPath) {
|
|||||||
|
|
||||||
Common::FS::IOFile file(it.path(), Common::FS::FileAccessMode::Read);
|
Common::FS::IOFile file(it.path(), Common::FS::FileAccessMode::Read);
|
||||||
if (!file.IsOpen()) {
|
if (!file.IsOpen()) {
|
||||||
|
LOG_CRITICAL(Common_Filesystem, "Unable to open trophy file for read");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrpHeader header;
|
TrpHeader header;
|
||||||
file.Read(header);
|
file.Read(header);
|
||||||
if (header.magic != 0xDCA24D00)
|
if (header.magic != 0xDCA24D00) {
|
||||||
|
LOG_CRITICAL(Common_Filesystem, "Wrong trophy magic number");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
s64 seekPos = sizeof(TrpHeader);
|
s64 seekPos = sizeof(TrpHeader);
|
||||||
std::filesystem::path trpFilesPath(
|
std::filesystem::path trpFilesPath(
|
||||||
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / title / "TrophyFiles" /
|
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / titleId /
|
||||||
it.path().stem());
|
"TrophyFiles" / it.path().stem());
|
||||||
std::filesystem::create_directories(trpFilesPath / "Icons");
|
std::filesystem::create_directories(trpFilesPath / "Icons");
|
||||||
std::filesystem::create_directory(trpFilesPath / "Xml");
|
std::filesystem::create_directory(trpFilesPath / "Xml");
|
||||||
|
|
||||||
@ -99,7 +103,14 @@ bool TRP::Extract(const std::filesystem::path& trophyPath) {
|
|||||||
size_t pos = xml_name.find("ESFM");
|
size_t pos = xml_name.find("ESFM");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
xml_name.replace(pos, xml_name.length(), "XML");
|
xml_name.replace(pos, xml_name.length(), "XML");
|
||||||
Common::FS::IOFile::WriteBytes(trpFilesPath / "Xml" / xml_name, XML);
|
std::filesystem::path path = trpFilesPath / "Xml" / xml_name;
|
||||||
|
size_t written = Common::FS::IOFile::WriteBytes(path, XML);
|
||||||
|
if (written != XML.size()) {
|
||||||
|
LOG_CRITICAL(
|
||||||
|
Common_Filesystem,
|
||||||
|
"Trophy XML {} write failed, wanted to write {} bytes, wrote {}",
|
||||||
|
fmt::UTF(path.u8string()), XML.size(), written);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class TRP {
|
|||||||
public:
|
public:
|
||||||
TRP();
|
TRP();
|
||||||
~TRP();
|
~TRP();
|
||||||
bool Extract(const std::filesystem::path& trophyPath);
|
bool Extract(const std::filesystem::path& trophyPath, const std::string titleId);
|
||||||
void GetNPcommID(const std::filesystem::path& trophyPath, int index);
|
void GetNPcommID(const std::filesystem::path& trophyPath, int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -253,7 +253,10 @@ int PS4_SYSV_ABI sceNpTrophyGetGameInfo(OrbisNpTrophyContext context, OrbisNpTro
|
|||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
||||||
|
|
||||||
ASSERT_MSG(result, "Couldnt parse trophy XML : {}", result.description());
|
if (!result) {
|
||||||
|
LOG_ERROR(Lib_NpTrophy, "Failed to parse trophy xml : {}", result.description());
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
GameTrophyInfo game_info{};
|
GameTrophyInfo game_info{};
|
||||||
|
|
||||||
@ -348,7 +351,10 @@ int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(OrbisNpTrophyContext context, OrbisNpTr
|
|||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
||||||
|
|
||||||
ASSERT_MSG(result, "Couldnt parse trophy XML : {}", result.description());
|
if (!result) {
|
||||||
|
LOG_ERROR(Lib_NpTrophy, "Failed to open trophy xml : {}", result.description());
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
GroupTrophyInfo group_info{};
|
GroupTrophyInfo group_info{};
|
||||||
|
|
||||||
@ -447,7 +453,10 @@ int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(OrbisNpTrophyContext context, OrbisNpT
|
|||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
||||||
|
|
||||||
ASSERT_MSG(result, "Couldnt parse trophy XML : {}", result.description());
|
if (!result) {
|
||||||
|
LOG_ERROR(Lib_NpTrophy, "Failed to open trophy xml : {}", result.description());
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
auto trophyconf = doc.child("trophyconf");
|
auto trophyconf = doc.child("trophyconf");
|
||||||
|
|
||||||
@ -509,7 +518,10 @@ s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(OrbisNpTrophyContext context,
|
|||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
||||||
|
|
||||||
ASSERT_MSG(result, "Couldnt parse trophy XML : {}", result.description());
|
if (!result) {
|
||||||
|
LOG_ERROR(Lib_NpTrophy, "Failed to open trophy xml : {}", result.description());
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int num_trophies = 0;
|
int num_trophies = 0;
|
||||||
auto trophyconf = doc.child("trophyconf");
|
auto trophyconf = doc.child("trophyconf");
|
||||||
@ -864,7 +876,10 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
|
|||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
pugi::xml_parse_result result = doc.load_file(trophy_file.native().c_str());
|
||||||
|
|
||||||
ASSERT_MSG(result, "Couldnt parse trophy XML : {}", result.description());
|
if (!result) {
|
||||||
|
LOG_ERROR(Lib_NpTrophy, "Failed to parse trophy xml : {}", result.description());
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
*platinumId = ORBIS_NP_TROPHY_INVALID_TROPHY_ID;
|
*platinumId = ORBIS_NP_TROPHY_INVALID_TROPHY_ID;
|
||||||
|
|
||||||
@ -966,7 +981,7 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.save_file((trophy_dir.string() + "/trophy00/Xml/TROP.XML").c_str());
|
doc.save_file((trophy_dir / "trophy00" / "Xml" / "TROP.XML").native().c_str());
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,13 @@ std::optional<TrophyUI> current_trophy_ui;
|
|||||||
std::queue<TrophyInfo> trophy_queue;
|
std::queue<TrophyInfo> trophy_queue;
|
||||||
std::mutex queueMtx;
|
std::mutex queueMtx;
|
||||||
|
|
||||||
TrophyUI::TrophyUI(std::filesystem::path trophyIconPath, std::string trophyName)
|
TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName)
|
||||||
: trophy_name(trophyName) {
|
: trophy_name(trophyName) {
|
||||||
if (std::filesystem::exists(trophyIconPath)) {
|
if (std::filesystem::exists(trophyIconPath)) {
|
||||||
trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath);
|
trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR(Lib_NpTrophy, "Couldnt load trophy icon at {}", trophyIconPath.string());
|
LOG_ERROR(Lib_NpTrophy, "Couldnt load trophy icon at {}",
|
||||||
|
fmt::UTF(trophyIconPath.u8string()));
|
||||||
}
|
}
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ void TrophyUI::Draw() {
|
|||||||
|
|
||||||
trophy_timer -= io.DeltaTime;
|
trophy_timer -= io.DeltaTime;
|
||||||
if (trophy_timer <= 0) {
|
if (trophy_timer <= 0) {
|
||||||
queueMtx.lock();
|
std::lock_guard<std::mutex> lock(queueMtx);
|
||||||
if (!trophy_queue.empty()) {
|
if (!trophy_queue.empty()) {
|
||||||
TrophyInfo next_trophy = trophy_queue.front();
|
TrophyInfo next_trophy = trophy_queue.front();
|
||||||
trophy_queue.pop();
|
trophy_queue.pop();
|
||||||
@ -74,12 +75,11 @@ void TrophyUI::Draw() {
|
|||||||
} else {
|
} else {
|
||||||
current_trophy_ui.reset();
|
current_trophy_ui.reset();
|
||||||
}
|
}
|
||||||
queueMtx.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTrophyToQueue(std::filesystem::path trophyIconPath, std::string trophyName) {
|
void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName) {
|
||||||
queueMtx.lock();
|
std::lock_guard<std::mutex> lock(queueMtx);
|
||||||
if (current_trophy_ui.has_value()) {
|
if (current_trophy_ui.has_value()) {
|
||||||
TrophyInfo new_trophy;
|
TrophyInfo new_trophy;
|
||||||
new_trophy.trophy_icon_path = trophyIconPath;
|
new_trophy.trophy_icon_path = trophyIconPath;
|
||||||
@ -88,7 +88,6 @@ void AddTrophyToQueue(std::filesystem::path trophyIconPath, std::string trophyNa
|
|||||||
} else {
|
} else {
|
||||||
current_trophy_ui.emplace(trophyIconPath, trophyName);
|
current_trophy_ui.emplace(trophyIconPath, trophyName);
|
||||||
}
|
}
|
||||||
queueMtx.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::NpTrophy
|
} // namespace Libraries::NpTrophy
|
@ -17,7 +17,7 @@ namespace Libraries::NpTrophy {
|
|||||||
|
|
||||||
class TrophyUI final : public ImGui::Layer {
|
class TrophyUI final : public ImGui::Layer {
|
||||||
public:
|
public:
|
||||||
TrophyUI(std::filesystem::path trophyIconPath, std::string trophyName);
|
TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName);
|
||||||
~TrophyUI() override;
|
~TrophyUI() override;
|
||||||
|
|
||||||
void Finish();
|
void Finish();
|
||||||
@ -35,6 +35,6 @@ struct TrophyInfo {
|
|||||||
std::string trophy_name;
|
std::string trophy_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddTrophyToQueue(std::filesystem::path trophyIconPath, std::string trophyName);
|
void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::string& trophyName);
|
||||||
|
|
||||||
}; // namespace Libraries::NpTrophy
|
}; // namespace Libraries::NpTrophy
|
@ -157,7 +157,11 @@ void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_cor
|
|||||||
if (copy_icon) {
|
if (copy_icon) {
|
||||||
const auto& src_icon = g_mnt->GetHostPath("/app0/sce_sys/save_data.png");
|
const auto& src_icon = g_mnt->GetHostPath("/app0/sce_sys/save_data.png");
|
||||||
if (fs::exists(src_icon)) {
|
if (fs::exists(src_icon)) {
|
||||||
fs::copy_file(src_icon, GetIconPath());
|
auto output_icon = GetIconPath();
|
||||||
|
if (fs::exists(output_icon)) {
|
||||||
|
fs::remove(output_icon);
|
||||||
|
}
|
||||||
|
fs::copy_file(src_icon, output_icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exists = true;
|
exists = true;
|
||||||
|
@ -207,7 +207,7 @@ void SetIcon(void* buf, size_t buf_size) {
|
|||||||
} else {
|
} else {
|
||||||
g_icon_memory.resize(buf_size);
|
g_icon_memory.resize(buf_size);
|
||||||
std::memcpy(g_icon_memory.data(), buf, buf_size);
|
std::memcpy(g_icon_memory.data(), buf, buf_size);
|
||||||
IOFile file(g_icon_path, Common::FS::FileAccessMode::Append);
|
IOFile file(g_icon_path, Common::FS::FileAccessMode::Write);
|
||||||
file.Seek(0);
|
file.Seek(0);
|
||||||
file.WriteRaw<u8>(g_icon_memory.data(), buf_size);
|
file.WriteRaw<u8>(g_icon_memory.data(), buf_size);
|
||||||
file.Close();
|
file.Close();
|
||||||
|
@ -262,6 +262,14 @@ struct OrbisSaveDataRestoreBackupData {
|
|||||||
s32 : 32;
|
s32 : 32;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OrbisSaveDataTransferringMount {
|
||||||
|
OrbisUserServiceUserId userId;
|
||||||
|
const OrbisSaveDataTitleId* titleId;
|
||||||
|
const OrbisSaveDataDirName* dirName;
|
||||||
|
const OrbisSaveDataFingerprint* fingerprint;
|
||||||
|
std::array<u8, 32> _reserved;
|
||||||
|
};
|
||||||
|
|
||||||
struct OrbisSaveDataDirNameSearchCond {
|
struct OrbisSaveDataDirNameSearchCond {
|
||||||
OrbisUserServiceUserId userId;
|
OrbisUserServiceUserId userId;
|
||||||
int : 32;
|
int : 32;
|
||||||
@ -357,7 +365,8 @@ static Error setNotInitializedError() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Error saveDataMount(const OrbisSaveDataMount2* mount_info,
|
static Error saveDataMount(const OrbisSaveDataMount2* mount_info,
|
||||||
OrbisSaveDataMountResult* mount_result) {
|
OrbisSaveDataMountResult* mount_result,
|
||||||
|
std::string_view title_id = g_game_serial) {
|
||||||
|
|
||||||
if (mount_info->userId < 0) {
|
if (mount_info->userId < 0) {
|
||||||
return Error::INVALID_LOGIN_USER;
|
return Error::INVALID_LOGIN_USER;
|
||||||
@ -369,8 +378,8 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info,
|
|||||||
|
|
||||||
// check backup status
|
// check backup status
|
||||||
{
|
{
|
||||||
const auto save_path = SaveInstance::MakeDirSavePath(mount_info->userId, g_game_serial,
|
const auto save_path =
|
||||||
mount_info->dirName->data);
|
SaveInstance::MakeDirSavePath(mount_info->userId, title_id, mount_info->dirName->data);
|
||||||
if (Backup::IsBackupExecutingFor(save_path) && g_fw_ver) {
|
if (Backup::IsBackupExecutingFor(save_path) && g_fw_ver) {
|
||||||
return Error::BACKUP_BUSY;
|
return Error::BACKUP_BUSY;
|
||||||
}
|
}
|
||||||
@ -409,7 +418,7 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info,
|
|||||||
return Error::MOUNT_FULL;
|
return Error::MOUNT_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveInstance save_instance{slot_num, mount_info->userId, g_game_serial, dir_name,
|
SaveInstance save_instance{slot_num, mount_info->userId, std::string{title_id}, dir_name,
|
||||||
(int)mount_info->blocks};
|
(int)mount_info->blocks};
|
||||||
|
|
||||||
if (save_instance.Mounted()) {
|
if (save_instance.Mounted()) {
|
||||||
@ -1573,6 +1582,7 @@ Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetu
|
|||||||
SaveMemory::SetIcon(nullptr, 0);
|
SaveMemory::SetIcon(nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SaveMemory::TriggerSaveWithoutEvent();
|
||||||
if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) {
|
if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) {
|
||||||
result->existedMemorySize = existed_size;
|
result->existedMemorySize = existed_size;
|
||||||
}
|
}
|
||||||
@ -1646,9 +1656,24 @@ Error PS4_SYSV_ABI sceSaveDataTerminate() {
|
|||||||
return Error::OK;
|
return Error::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceSaveDataTransferringMount() {
|
Error PS4_SYSV_ABI sceSaveDataTransferringMount(const OrbisSaveDataTransferringMount* mount,
|
||||||
LOG_ERROR(Lib_SaveData, "(STUBBED) called");
|
OrbisSaveDataMountResult* mountResult) {
|
||||||
return ORBIS_OK;
|
LOG_DEBUG(Lib_SaveData, "called");
|
||||||
|
if (!g_initialized) {
|
||||||
|
LOG_INFO(Lib_SaveData, "called without initialize");
|
||||||
|
return setNotInitializedError();
|
||||||
|
}
|
||||||
|
if (mount == nullptr || mount->titleId == nullptr || mount->dirName == nullptr) {
|
||||||
|
LOG_INFO(Lib_SaveData, "called with invalid parameter");
|
||||||
|
return Error::PARAMETER;
|
||||||
|
}
|
||||||
|
LOG_DEBUG(Lib_SaveData, "called titleId: {}, dirName: {}", mount->titleId->data.to_view(),
|
||||||
|
mount->dirName->data.to_view());
|
||||||
|
OrbisSaveDataMount2 mount_info{};
|
||||||
|
mount_info.userId = mount->userId;
|
||||||
|
mount_info.dirName = mount->dirName;
|
||||||
|
mount_info.mountMode = OrbisSaveDataMountMode::RDONLY;
|
||||||
|
return saveDataMount(&mount_info, mountResult, mount->titleId->data.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Error PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) {
|
Error PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) {
|
||||||
|
@ -70,6 +70,7 @@ struct OrbisSaveDataMountInfo;
|
|||||||
struct OrbisSaveDataMountPoint;
|
struct OrbisSaveDataMountPoint;
|
||||||
struct OrbisSaveDataMountResult;
|
struct OrbisSaveDataMountResult;
|
||||||
struct OrbisSaveDataRestoreBackupData;
|
struct OrbisSaveDataRestoreBackupData;
|
||||||
|
struct OrbisSaveDataTransferringMount;
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceSaveDataAbort();
|
int PS4_SYSV_ABI sceSaveDataAbort();
|
||||||
Error PS4_SYSV_ABI sceSaveDataBackup(const OrbisSaveDataBackup* backup);
|
Error PS4_SYSV_ABI sceSaveDataBackup(const OrbisSaveDataBackup* backup);
|
||||||
@ -174,7 +175,8 @@ int PS4_SYSV_ABI sceSaveDataSupportedFakeBrokenStatus();
|
|||||||
int PS4_SYSV_ABI sceSaveDataSyncCloudList();
|
int PS4_SYSV_ABI sceSaveDataSyncCloudList();
|
||||||
Error PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam);
|
Error PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam);
|
||||||
Error PS4_SYSV_ABI sceSaveDataTerminate();
|
Error PS4_SYSV_ABI sceSaveDataTerminate();
|
||||||
int PS4_SYSV_ABI sceSaveDataTransferringMount();
|
Error PS4_SYSV_ABI sceSaveDataTransferringMount(const OrbisSaveDataTransferringMount* mount,
|
||||||
|
OrbisSaveDataMountResult* mountResult);
|
||||||
Error PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint);
|
Error PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint);
|
||||||
int PS4_SYSV_ABI sceSaveDataUmountSys();
|
int PS4_SYSV_ABI sceSaveDataUmountSys();
|
||||||
Error PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint);
|
Error PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint);
|
||||||
|
@ -115,7 +115,7 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||||||
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles";
|
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles";
|
||||||
if (!std::filesystem::exists(trophyDir)) {
|
if (!std::filesystem::exists(trophyDir)) {
|
||||||
TRP trp;
|
TRP trp;
|
||||||
if (!trp.Extract(file.parent_path())) {
|
if (!trp.Extract(file.parent_path(), id)) {
|
||||||
LOG_ERROR(Loader, "Couldn't extract trophies");
|
LOG_ERROR(Loader, "Couldn't extract trophies");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,8 +343,8 @@ void CheckUpdate::DownloadUpdate(const QString& url) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString userPath =
|
QString userPath;
|
||||||
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::UserDir).string());
|
Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir));
|
||||||
QString tempDownloadPath = userPath + "/temp_download_update";
|
QString tempDownloadPath = userPath + "/temp_download_update";
|
||||||
QDir dir(tempDownloadPath);
|
QDir dir(tempDownloadPath);
|
||||||
if (!dir.exists()) {
|
if (!dir.exists()) {
|
||||||
@ -371,12 +371,13 @@ void CheckUpdate::DownloadUpdate(const QString& url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CheckUpdate::Install() {
|
void CheckUpdate::Install() {
|
||||||
QString userPath =
|
QString userPath;
|
||||||
QString::fromStdString(Common::FS::GetUserPath(Common::FS::PathType::UserDir).string());
|
Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir));
|
||||||
|
|
||||||
QString startingUpdate = tr("Starting Update...");
|
QString startingUpdate = tr("Starting Update...");
|
||||||
QString tempDirPath = userPath + "/temp_download_update";
|
QString tempDirPath = userPath + "/temp_download_update";
|
||||||
QString rootPath = QString::fromStdString(std::filesystem::current_path().string());
|
QString rootPath;
|
||||||
|
Common::FS::PathToQString(rootPath, std::filesystem::current_path());
|
||||||
|
|
||||||
QString scriptContent;
|
QString scriptContent;
|
||||||
QString scriptFileName;
|
QString scriptFileName;
|
||||||
|
@ -53,7 +53,7 @@ void GameGridFrame::onCurrentCellChanged(int currentRow, int currentColumn, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameGridFrame::PlayBackgroundMusic(QString path) {
|
void GameGridFrame::PlayBackgroundMusic(QString path) {
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty() || !Config::getPlayBGM()) {
|
||||||
BackgroundMusicPlayer::getInstance().stopMusic();
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ void GameListFrame::onCurrentCellChanged(int currentRow, int currentColumn, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
|
void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
|
||||||
if (!item) {
|
if (!item || !Config::getPlayBGM()) {
|
||||||
BackgroundMusicPlayer::getInstance().stopMusic();
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ void TrophyViewer::PopulateTrophyWidget(QString title) {
|
|||||||
QDir dir(trophyDirQt);
|
QDir dir(trophyDirQt);
|
||||||
if (!dir.exists()) {
|
if (!dir.exists()) {
|
||||||
std::filesystem::path path = Common::FS::PathFromQString(gameTrpPath_);
|
std::filesystem::path path = Common::FS::PathFromQString(gameTrpPath_);
|
||||||
if (!trp.Extract(path))
|
if (!trp.Extract(path, title.toStdString()))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QFileInfoList dirList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
QFileInfoList dirList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
Loading…
Reference in New Issue
Block a user