From 01bfcb05cdd1940ab855b5752fd3135519e74115 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Wed, 28 May 2025 15:00:31 +0100 Subject: [PATCH] fix gamecard install due to fs==NULL. more explicit yields for sd card transfers for file based emummc. --- sphaira/CMakeLists.txt | 2 +- sphaira/source/dumper.cpp | 7 ++++++- sphaira/source/fs.cpp | 19 +++++++++++++++++++ sphaira/source/hasher.cpp | 9 ++++++++- sphaira/source/ui/menus/filebrowser.cpp | 7 ++++++- sphaira/source/ui/menus/game_menu.cpp | 11 +++++++++-- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/sphaira/CMakeLists.txt b/sphaira/CMakeLists.txt index 0b7bae5..c8b6ca1 100644 --- a/sphaira/CMakeLists.txt +++ b/sphaira/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.13) -set(sphaira_VERSION 0.11.1) +set(sphaira_VERSION 0.11.2) project(sphaira VERSION ${sphaira_VERSION} diff --git a/sphaira/source/dumper.cpp b/sphaira/source/dumper.cpp index 9727acc..12c03e5 100644 --- a/sphaira/source/dumper.cpp +++ b/sphaira/source/dumper.cpp @@ -105,6 +105,7 @@ private: Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, BaseSource* source, std::span paths) { constexpr s64 BIG_FILE_SIZE = 1024ULL*1024ULL*1024ULL*4ULL; + const auto is_file_based_emummc = App::IsFileBaseEmummc(); for (const auto& path : paths) { const auto base_path = fs::AppendPath(root, path); @@ -130,7 +131,11 @@ Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, Bas return source->Read(path, data, off, size, bytes_read); }, [&](const void* data, s64 off, s64 size) -> Result { - return file.Write(off, data, size, FsWriteOption_None); + const auto rc = file.Write(off, data, size, FsWriteOption_None); + if (is_file_based_emummc) { + svcSleepThread(2e+6); // 2ms + } + return rc; } )); } diff --git a/sphaira/source/fs.cpp b/sphaira/source/fs.cpp index f772339..c09b825 100644 --- a/sphaira/source/fs.cpp +++ b/sphaira/source/fs.cpp @@ -510,6 +510,9 @@ File::~File() { } Result File::Read( s64 off, void* buf, u64 read_size, u32 option, u64* bytes_read) { + *bytes_read = 0; + R_UNLESS(m_fs, 0x1); + if (m_fs->IsNative()) { R_TRY(fsFileRead(&m_native, off, buf, read_size, option, bytes_read)); } else { @@ -534,6 +537,8 @@ Result File::Read( s64 off, void* buf, u64 read_size, u32 option, u64* bytes_rea } Result File::Write(s64 off, const void* buf, u64 write_size, u32 option) { + R_UNLESS(m_fs, 0x1); + if (m_fs->IsNative()) { R_TRY(fsFileWrite(&m_native, off, buf, write_size, option)); } else { @@ -554,6 +559,8 @@ Result File::Write(s64 off, const void* buf, u64 write_size, u32 option) { } Result File::SetSize(s64 sz) { + R_UNLESS(m_fs, 0x1); + if (m_fs->IsNative()) { R_TRY(fsFileSetSize(&m_native, sz)); } else { @@ -566,6 +573,8 @@ Result File::SetSize(s64 sz) { } Result File::GetSize(s64* out) { + R_UNLESS(m_fs, 0x1); + if (m_fs->IsNative()) { R_TRY(fsFileGetSize(&m_native, out)); } else { @@ -588,6 +597,10 @@ Result File::GetSize(s64* out) { } void File::Close() { + if (!m_fs) { + return; + } + if (m_fs->IsNative()) { if (serviceIsActive(&m_native.s)) { fsFileClose(&m_native); @@ -669,6 +682,7 @@ Dir::~Dir() { Result Dir::GetEntryCount(s64* out) { *out = 0; + R_UNLESS(m_fs, 0x1); if (m_fs->IsNative()) { R_TRY(fsDirGetEntryCount(&m_native, out)); @@ -689,6 +703,7 @@ Result Dir::GetEntryCount(s64* out) { Result Dir::ReadAll(std::vector& buf) { buf.clear(); + R_UNLESS(m_fs, 0x1); if (m_fs->IsNative()) { s64 count; @@ -731,6 +746,10 @@ Result Dir::ReadAll(std::vector& buf) { } void Dir::Close() { + if (!m_fs) { + return; + } + if (m_fs->IsNative()) { if (serviceIsActive(&m_native.s)) { fsDirClose(&m_native); diff --git a/sphaira/source/hasher.cpp b/sphaira/source/hasher.cpp index 8e2d015..624a6ae 100644 --- a/sphaira/source/hasher.cpp +++ b/sphaira/source/hasher.cpp @@ -1,4 +1,5 @@ #include "hasher.hpp" +#include "app.hpp" #include namespace sphaira::hash { @@ -11,6 +12,7 @@ consteval auto CalculateHashStrLen(s64 buf_size) { struct FileSource final : BaseSource { FileSource(fs::Fs* fs, const fs::FsPath& path) : m_fs{fs} { m_open_result = m_fs->OpenFile(path, FsOpenMode_Read, std::addressof(m_file)); + m_is_file_based_emummc = App::IsFileBaseEmummc(); } Result Size(s64* out) { @@ -18,13 +20,18 @@ struct FileSource final : BaseSource { } Result Read(void* buf, s64 off, s64 size, u64* bytes_read) { - return m_file.Read(off, buf, size, 0, bytes_read); + const auto rc = m_file.Read(off, buf, size, 0, bytes_read); + if (m_fs->IsNative() && m_is_file_based_emummc) { + svcSleepThread(2e+6); // 2ms + } + return rc; } private: fs::Fs* m_fs{}; fs::File m_file{}; Result m_open_result{}; + bool m_is_file_based_emummc{}; }; struct HashSource { diff --git a/sphaira/source/ui/menus/filebrowser.cpp b/sphaira/source/ui/menus/filebrowser.cpp index 7a2f392..1a90239 100644 --- a/sphaira/source/ui/menus/filebrowser.cpp +++ b/sphaira/source/ui/menus/filebrowser.cpp @@ -946,6 +946,7 @@ void FsView::UploadFiles() { const auto loc = network_locations[*op_index]; App::Push(std::make_shared(0, "Uploading"_i18n, "", [this, loc](auto pbox) -> Result { auto targets = GetSelectedEntries(); + const auto is_file_based_emummc = App::IsFileBaseEmummc(); const auto file_add = [&](s64 file_size, const fs::FsPath& file_path, const char* name) -> Result { // the file name needs to be relative to the current directory. @@ -958,7 +959,11 @@ void FsView::UploadFiles() { return thread::TransferPull(pbox, file_size, [&](void* data, s64 off, s64 size, u64* bytes_read) -> Result { - return f.Read(off, data, size, FsReadOption_None, bytes_read); + const auto rc = f.Read(off, data, size, FsReadOption_None, bytes_read); + if (m_fs->IsNative() && is_file_based_emummc) { + svcSleepThread(2e+6); // 2ms + } + return rc; }, [&](thread::PullCallback pull) -> Result { s64 offset{}; diff --git a/sphaira/source/ui/menus/game_menu.cpp b/sphaira/source/ui/menus/game_menu.cpp index e73534d..d31fc8a 100644 --- a/sphaira/source/ui/menus/game_menu.cpp +++ b/sphaira/source/ui/menus/game_menu.cpp @@ -186,7 +186,9 @@ private: }; struct NspSource final : dump::BaseSource { - NspSource(const std::vector& entries) : m_entries{entries} { } + NspSource(const std::vector& entries) : m_entries{entries} { + m_is_file_based_emummc = App::IsFileBaseEmummc(); + } Result Read(const std::string& path, void* buf, s64 off, s64 size, u64* bytes_read) override { const auto it = std::ranges::find_if(m_entries, [&path](auto& e){ @@ -194,7 +196,11 @@ struct NspSource final : dump::BaseSource { }); R_UNLESS(it != m_entries.end(), 0x1); - return it->Read(buf, off, size, bytes_read); + const auto rc = it->Read(buf, off, size, bytes_read); + if (m_is_file_based_emummc) { + svcSleepThread(2e+6); // 2ms + } + return rc; } auto GetName(const std::string& path) const -> std::string { @@ -235,6 +241,7 @@ struct NspSource final : dump::BaseSource { private: std::vector m_entries{}; + bool m_is_file_based_emummc{}; }; Result Notify(Result rc, const std::string& error_message) {