disable hdd->hdd threading. only open log write on write to allow for reads. log fw/ams version.
hdd->hdd threading is disabled due to a bug in libusbhsfs which causes a deadlock if 2 fs calls happen at the same time.
This commit is contained in:
@@ -198,7 +198,7 @@ FetchContent_Declare(zstd
|
||||
|
||||
FetchContent_Declare(libusbhsfs
|
||||
GIT_REPOSITORY https://github.com/ITotalJustice/libusbhsfs.git
|
||||
GIT_TAG db2bf2a
|
||||
GIT_TAG d0a973e
|
||||
)
|
||||
|
||||
FetchContent_Declare(libnxtc
|
||||
|
||||
@@ -12,10 +12,14 @@ namespace fs {
|
||||
|
||||
struct FsPath {
|
||||
FsPath() = default;
|
||||
constexpr FsPath(const auto& str) { From(str); }
|
||||
|
||||
constexpr FsPath(const FsPath& p) { From(p); }
|
||||
constexpr FsPath(const char* str) { From(str); }
|
||||
constexpr FsPath(const std::string& str) { From(str); }
|
||||
constexpr FsPath(const std::string_view& str) { From(str); }
|
||||
|
||||
constexpr void From(const FsPath& p) {
|
||||
*this = p;
|
||||
From(p.s);
|
||||
}
|
||||
|
||||
constexpr void From(const char* str) {
|
||||
@@ -40,6 +44,10 @@ struct FsPath {
|
||||
return s;
|
||||
}
|
||||
|
||||
constexpr auto starts_with(std::string_view str) const -> bool {
|
||||
return !strncasecmp(s, str.data(), str.length());
|
||||
}
|
||||
|
||||
constexpr auto empty() const {
|
||||
return s[0] == '\0';
|
||||
}
|
||||
@@ -65,6 +73,11 @@ struct FsPath {
|
||||
constexpr char& operator[](std::size_t idx) { return s[idx]; }
|
||||
constexpr const char& operator[](std::size_t idx) const { return s[idx]; }
|
||||
|
||||
constexpr FsPath& operator=(const FsPath& p) noexcept {
|
||||
From(p.s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr FsPath operator+(const FsPath& v) const noexcept {
|
||||
FsPath r{*this};
|
||||
return r += v;
|
||||
@@ -186,9 +199,6 @@ struct File {
|
||||
FsFile m_native{};
|
||||
std::FILE* m_stdio{};
|
||||
s64 m_stdio_off{};
|
||||
// sadly, fatfs doesn't support fstat, so we have to manually
|
||||
// stat the file to get it's size.
|
||||
FsPath m_path{};
|
||||
};
|
||||
|
||||
struct Dir {
|
||||
|
||||
@@ -12,6 +12,8 @@ extern "C" {
|
||||
bool log_file_init();
|
||||
bool log_nxlink_init();
|
||||
void log_file_exit();
|
||||
bool log_is_init();
|
||||
|
||||
void log_nxlink_exit();
|
||||
void log_write(const char* s, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void log_write_arg(const char* s, va_list* v);
|
||||
|
||||
@@ -40,17 +40,17 @@ Result TransferPull(ui::ProgressBox* pbox, s64 size, ReadCallback rfunc, StartCa
|
||||
|
||||
// helper for extract zips.
|
||||
// this will multi-thread unzip if size >= 512KiB, otherwise it'll single pass.
|
||||
Result TransferUnzip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, s64 size, u32 crc32 = 0);
|
||||
Result TransferUnzip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, s64 size, u32 crc32 = 0, Mode mode = Mode::SingleThreadedIfSmaller);
|
||||
|
||||
// same as above but for zipping files.
|
||||
Result TransferZip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, u32* crc32 = nullptr);
|
||||
Result TransferZip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, u32* crc32 = nullptr, Mode mode = Mode::SingleThreadedIfSmaller);
|
||||
|
||||
// passes the name inside the zip an final output path.
|
||||
using UnzipAllFilter = std::function<bool(const fs::FsPath& name, fs::FsPath& path)>;
|
||||
|
||||
// helper all-in-one unzip function that unzips a zip (either open or path provided).
|
||||
// the filter function can be used to modify the path and filter out unwanted files.
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter = nullptr);
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, const fs::FsPath& zip_out, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter = nullptr);
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter = nullptr, Mode mode = Mode::SingleThreadedIfSmaller);
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, const fs::FsPath& zip_out, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter = nullptr, Mode mode = Mode::SingleThreadedIfSmaller);
|
||||
|
||||
} // namespace sphaira::thread
|
||||
|
||||
@@ -39,9 +39,9 @@ struct ProgressBox final : Widget {
|
||||
auto ShouldExitResult() -> Result;
|
||||
|
||||
// helper functions
|
||||
auto CopyFile(fs::Fs* fs_src, fs::Fs* fs_dst, const fs::FsPath& src, const fs::FsPath& dst) -> Result;
|
||||
auto CopyFile(fs::Fs* fs, const fs::FsPath& src, const fs::FsPath& dst) -> Result;
|
||||
auto CopyFile(const fs::FsPath& src, const fs::FsPath& dst) -> Result;
|
||||
auto CopyFile(fs::Fs* fs_src, fs::Fs* fs_dst, const fs::FsPath& src, const fs::FsPath& dst, bool single_threaded = false) -> Result;
|
||||
auto CopyFile(fs::Fs* fs, const fs::FsPath& src, const fs::FsPath& dst, bool single_threaded = false) -> Result;
|
||||
auto CopyFile(const fs::FsPath& src, const fs::FsPath& dst, bool single_threaded = false) -> Result;
|
||||
void Yield();
|
||||
|
||||
auto GetCpuId() const {
|
||||
|
||||
@@ -1292,21 +1292,6 @@ App::App(const char* argv0) {
|
||||
__nx_applet_exit_mode = 1;
|
||||
}
|
||||
|
||||
// get emummc config.
|
||||
alignas(0x1000) AmsEmummcPaths paths{};
|
||||
SecmonArgs args{};
|
||||
args.X[0] = 0xF0000404; /* smcAmsGetEmunandConfig */
|
||||
args.X[1] = 0; /* EXO_EMUMMC_MMC_NAND*/
|
||||
args.X[2] = (u64)&paths; /* out path */
|
||||
svcCallSecureMonitor(&args);
|
||||
m_emummc_paths = paths;
|
||||
|
||||
log_write("emummc : %u\n", App::IsEmummc());
|
||||
if (App::IsEmummc()) {
|
||||
log_write("[emummc] file based path: %s\n", m_emummc_paths.file_based_path);
|
||||
log_write("[emummc] nintendo path: %s\n", m_emummc_paths.nintendo);
|
||||
}
|
||||
|
||||
fs::FsNativeSd fs;
|
||||
fs.CreateDirectoryRecursively("/config/sphaira");
|
||||
fs.CreateDirectory("/config/sphaira/assoc");
|
||||
@@ -1370,6 +1355,48 @@ App::App(const char* argv0) {
|
||||
App::Notify("Warning! Logs are enabled, Sphaira will run slowly!"_i18n);
|
||||
}
|
||||
|
||||
if (log_is_init()) {
|
||||
SetSysFirmwareVersion fw_version{};
|
||||
setsysInitialize();
|
||||
ON_SCOPE_EXIT(setsysExit());
|
||||
setsysGetFirmwareVersion(&fw_version);
|
||||
|
||||
log_write("[version] platform: %s\n", fw_version.platform);
|
||||
log_write("[version] version_hash: %s\n", fw_version.version_hash);
|
||||
log_write("[version] display_version: %s\n", fw_version.display_version);
|
||||
log_write("[version] display_title: %s\n", fw_version.display_title);
|
||||
|
||||
splInitialize();
|
||||
ON_SCOPE_EXIT(splExit());
|
||||
|
||||
u64 out{};
|
||||
splGetConfig((SplConfigItem)65000, &out);
|
||||
log_write("[ams] version: %lu.%lu.%lu\n", (out >> 56) & 0xFF, (out >> 48) & 0xFF, (out >> 40) & 0xFF);
|
||||
log_write("[ams] target version: %lu.%lu.%lu\n", (out >> 24) & 0xFF, (out >> 16) & 0xFF, (out >> 8) & 0xFF);
|
||||
log_write("[ams] key gen: %lu\n", (out >> 32) & 0xFF);
|
||||
|
||||
splGetConfig((SplConfigItem)65003, &out);
|
||||
log_write("[ams] hash: %lx\n", out);
|
||||
|
||||
splGetConfig((SplConfigItem)65010, &out);
|
||||
log_write("[ams] usb 3.0 enabled: %lu\n", out);
|
||||
}
|
||||
|
||||
// get emummc config.
|
||||
alignas(0x1000) AmsEmummcPaths paths{};
|
||||
SecmonArgs args{};
|
||||
args.X[0] = 0xF0000404; /* smcAmsGetEmunandConfig */
|
||||
args.X[1] = 0; /* EXO_EMUMMC_MMC_NAND*/
|
||||
args.X[2] = (u64)&paths; /* out path */
|
||||
svcCallSecureMonitor(&args);
|
||||
m_emummc_paths = paths;
|
||||
|
||||
log_write("[emummc] enabled: %u\n", App::IsEmummc());
|
||||
if (App::IsEmummc()) {
|
||||
log_write("[emummc] file based path: %s\n", m_emummc_paths.file_based_path);
|
||||
log_write("[emummc] nintendo path: %s\n", m_emummc_paths.nintendo);
|
||||
}
|
||||
|
||||
if (App::GetMtpEnable()) {
|
||||
haze::Init();
|
||||
}
|
||||
|
||||
@@ -500,7 +500,6 @@ Result OpenFile(fs::Fs* fs, const fs::FsPath& path, u32 mode, File* f) {
|
||||
}
|
||||
|
||||
R_UNLESS(f->m_stdio, Result_FsUnknownStdioError);
|
||||
std::strcpy(f->m_path, path);
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
@@ -580,17 +579,7 @@ Result File::GetSize(s64* out) {
|
||||
R_TRY(fsFileGetSize(&m_native, out));
|
||||
} else {
|
||||
struct stat st;
|
||||
const auto fd = fileno(m_stdio);
|
||||
bool did_stat{};
|
||||
|
||||
if (fd && !fstat(fd, &st)) {
|
||||
did_stat = true;
|
||||
}
|
||||
|
||||
if (!did_stat) {
|
||||
R_UNLESS(!lstat(m_path, &st), Result_FsUnknownStdioError);
|
||||
}
|
||||
|
||||
R_UNLESS(!fstat(fileno(m_stdio), &st), Result_FsUnknownStdioError);
|
||||
*out = st.st_size;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,17 +10,27 @@ namespace {
|
||||
|
||||
constexpr const char* logpath = "/config/sphaira/log.txt";
|
||||
|
||||
std::FILE* file{};
|
||||
int nxlink_socket{};
|
||||
bool g_file_open{};
|
||||
std::mutex mutex{};
|
||||
|
||||
void log_write_arg_internal(const char* s, std::va_list* v) {
|
||||
if (file) {
|
||||
std::vfprintf(file, s, *v);
|
||||
std::fflush(file);
|
||||
const auto t = std::time(nullptr);
|
||||
const auto tm = std::localtime(&t);
|
||||
|
||||
static char buf[512];
|
||||
const auto len = std::snprintf(buf, sizeof(buf), "[%02u:%02u:%02u] -> ", tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
std::vsnprintf(buf + len, sizeof(buf) - len, s, *v);
|
||||
|
||||
if (g_file_open) {
|
||||
auto file = std::fopen(logpath, "a");
|
||||
if (file) {
|
||||
std::fprintf(file, "%s", buf);
|
||||
std::fclose(file);
|
||||
}
|
||||
}
|
||||
if (nxlink_socket) {
|
||||
std::vprintf(s, *v);
|
||||
std::printf("%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +40,18 @@ extern "C" {
|
||||
|
||||
auto log_file_init() -> bool {
|
||||
std::scoped_lock lock{mutex};
|
||||
if (file) {
|
||||
if (g_file_open) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file = std::fopen(logpath, "w");
|
||||
return file != nullptr;
|
||||
auto file = std::fopen(logpath, "w");
|
||||
if (file) {
|
||||
g_file_open = true;
|
||||
std::fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto log_nxlink_init() -> bool {
|
||||
@@ -50,9 +66,8 @@ auto log_nxlink_init() -> bool {
|
||||
|
||||
void log_file_exit() {
|
||||
std::scoped_lock lock{mutex};
|
||||
if (file) {
|
||||
std::fclose(file);
|
||||
file = nullptr;
|
||||
if (g_file_open) {
|
||||
g_file_open = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,12 +79,17 @@ void log_nxlink_exit() {
|
||||
}
|
||||
}
|
||||
|
||||
void log_write(const char* s, ...) {
|
||||
bool log_is_init() {
|
||||
std::scoped_lock lock{mutex};
|
||||
if (!file && !nxlink_socket) {
|
||||
return g_file_open || nxlink_socket;
|
||||
}
|
||||
|
||||
void log_write(const char* s, ...) {
|
||||
if (!log_is_init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::scoped_lock lock{mutex};
|
||||
std::va_list v{};
|
||||
va_start(v, s);
|
||||
log_write_arg_internal(s, &v);
|
||||
@@ -77,11 +97,11 @@ void log_write(const char* s, ...) {
|
||||
}
|
||||
|
||||
void log_write_arg(const char* s, va_list* v) {
|
||||
std::scoped_lock lock{mutex};
|
||||
if (!file && !nxlink_socket) {
|
||||
if (!log_is_init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::scoped_lock lock{mutex};
|
||||
log_write_arg_internal(s, v);
|
||||
}
|
||||
|
||||
|
||||
@@ -416,21 +416,21 @@ Result TransferInternal(ui::ProgressBox* pbox, s64 size, ReadCallback rfunc, Wri
|
||||
} // namespace
|
||||
|
||||
Result Transfer(ui::ProgressBox* pbox, s64 size, ReadCallback rfunc, WriteCallback wfunc, Mode mode) {
|
||||
return TransferInternal(pbox, size, rfunc, wfunc, nullptr, Mode::MultiThreaded);
|
||||
return TransferInternal(pbox, size, rfunc, wfunc, nullptr, mode);
|
||||
}
|
||||
|
||||
Result TransferPull(ui::ProgressBox* pbox, s64 size, ReadCallback rfunc, StartCallback sfunc, Mode mode) {
|
||||
return TransferInternal(pbox, size, rfunc, nullptr, [sfunc](StartThreadCallback start, PullCallback pull) -> Result {
|
||||
R_TRY(start());
|
||||
return sfunc(pull);
|
||||
}, Mode::MultiThreaded);
|
||||
}, mode);
|
||||
}
|
||||
|
||||
Result TransferPull(ui::ProgressBox* pbox, s64 size, ReadCallback rfunc, StartCallback2 sfunc, Mode mode) {
|
||||
return TransferInternal(pbox, size, rfunc, nullptr, sfunc, Mode::MultiThreaded);
|
||||
return TransferInternal(pbox, size, rfunc, nullptr, sfunc, mode);
|
||||
}
|
||||
|
||||
Result TransferUnzip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, s64 size, u32 crc32) {
|
||||
Result TransferUnzip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, s64 size, u32 crc32, Mode mode) {
|
||||
Result rc;
|
||||
if (R_FAILED(rc = fs->CreateDirectoryRecursivelyWithPath(path)) && rc != FsError_PathAlreadyExists) {
|
||||
log_write("failed to create folder: %s 0x%04X\n", path.s, rc);
|
||||
@@ -471,7 +471,7 @@ Result TransferUnzip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::F
|
||||
[&](const void* data, s64 off, s64 size) -> Result {
|
||||
return f.Write(off, data, size, FsWriteOption_None);
|
||||
},
|
||||
nullptr, Mode::SingleThreadedIfSmaller, SMALL_BUFFER_SIZE
|
||||
nullptr, mode, SMALL_BUFFER_SIZE
|
||||
));
|
||||
|
||||
// validate crc32 (if set in the info).
|
||||
@@ -480,7 +480,7 @@ Result TransferUnzip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::F
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TransferZip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, u32* crc32) {
|
||||
Result TransferZip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& path, u32* crc32, Mode mode) {
|
||||
fs::File f;
|
||||
R_TRY(fs->OpenFile(path, FsOpenMode_Read, &f));
|
||||
|
||||
@@ -506,11 +506,11 @@ Result TransferZip(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsP
|
||||
}
|
||||
R_SUCCEED();
|
||||
},
|
||||
nullptr, Mode::SingleThreadedIfSmaller, SMALL_BUFFER_SIZE
|
||||
nullptr, mode, SMALL_BUFFER_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter) {
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter, Mode mode) {
|
||||
unz_global_info64 ginfo;
|
||||
if (UNZ_OK != unzGetGlobalInfo64(zfile, &ginfo)) {
|
||||
R_THROW(Result_UnzGetGlobalInfo64);
|
||||
@@ -560,14 +560,14 @@ Result TransferUnzipAll(ui::ProgressBox* pbox, void* zfile, fs::Fs* fs, const fs
|
||||
R_THROW(rc);
|
||||
}
|
||||
} else {
|
||||
R_TRY(TransferUnzip(pbox, zfile, fs, path, info.uncompressed_size, info.crc));
|
||||
R_TRY(TransferUnzip(pbox, zfile, fs, path, info.uncompressed_size, info.crc, mode));
|
||||
}
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, const fs::FsPath& zip_out, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter) {
|
||||
Result TransferUnzipAll(ui::ProgressBox* pbox, const fs::FsPath& zip_out, fs::Fs* fs, const fs::FsPath& base_path, UnzipAllFilter filter, Mode mode) {
|
||||
zlib_filefunc64_def file_func;
|
||||
mz::FileFuncStdio(&file_func);
|
||||
|
||||
@@ -575,7 +575,7 @@ Result TransferUnzipAll(ui::ProgressBox* pbox, const fs::FsPath& zip_out, fs::Fs
|
||||
R_UNLESS(zfile, Result_UnzOpen2_64);
|
||||
ON_SCOPE_EXIT(unzClose(zfile));
|
||||
|
||||
return TransferUnzipAll(pbox, zfile, fs, base_path, filter);
|
||||
return TransferUnzipAll(pbox, zfile, fs, base_path, filter, mode);
|
||||
}
|
||||
|
||||
} // namespace::thread
|
||||
|
||||
@@ -442,6 +442,8 @@ FsView::~FsView() {
|
||||
}
|
||||
|
||||
void FsView::Update(Controller* controller, TouchInfo* touch) {
|
||||
Widget::Update(controller, touch);
|
||||
|
||||
m_list->OnUpdate(controller, touch, m_index, m_entries_current.size(), [this](bool touch, auto i) {
|
||||
if (touch && m_index == i) {
|
||||
FireAction(Button::A);
|
||||
@@ -728,10 +730,12 @@ void FsView::UnzipFiles(fs::FsPath dir_path) {
|
||||
}
|
||||
|
||||
App::Push(std::make_shared<ui::ProgressBox>(0, "Extracting "_i18n, "", [this, dir_path, targets](auto pbox) -> Result {
|
||||
const auto is_hdd_fs = m_fs->Root().starts_with("ums");
|
||||
|
||||
for (auto& e : targets) {
|
||||
pbox->SetTitle(e.GetName());
|
||||
const auto zip_out = GetNewPath(e);
|
||||
R_TRY(thread::TransferUnzipAll(pbox, zip_out, m_fs.get(), dir_path));
|
||||
R_TRY(thread::TransferUnzipAll(pbox, zip_out, m_fs.get(), dir_path, nullptr, is_hdd_fs ? thread::Mode::SingleThreaded : thread::Mode::SingleThreadedIfSmaller));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
@@ -786,6 +790,7 @@ void FsView::ZipFiles(fs::FsPath zip_out) {
|
||||
App::Push(std::make_shared<ui::ProgressBox>(0, "Compressing "_i18n, "", [this, zip_out, targets](auto pbox) -> Result {
|
||||
const auto t = std::time(NULL);
|
||||
const auto tm = std::localtime(&t);
|
||||
const auto is_hdd_fs = m_fs->Root().starts_with("ums");
|
||||
|
||||
// pre-calculate the time rather than calculate it in the loop.
|
||||
zip_fileinfo zip_info{};
|
||||
@@ -825,7 +830,7 @@ void FsView::ZipFiles(fs::FsPath zip_out) {
|
||||
}
|
||||
ON_SCOPE_EXIT(zipCloseFileInZip(zfile));
|
||||
|
||||
return thread::TransferZip(pbox, zfile, m_fs.get(), file_path);
|
||||
return thread::TransferZip(pbox, zfile, m_fs.get(), file_path, nullptr, is_hdd_fs ? thread::Mode::SingleThreaded : thread::Mode::SingleThreadedIfSmaller);
|
||||
};
|
||||
|
||||
for (auto& e : targets) {
|
||||
@@ -1207,6 +1212,7 @@ void FsView::OnPasteCallback() {
|
||||
App::Push(std::make_shared<ProgressBox>(0, "Pasting"_i18n, "", [this](auto pbox) -> Result {
|
||||
auto& selected = m_menu->m_selected;
|
||||
auto src_fs = selected.m_view->GetFs();
|
||||
const auto is_same_fs = selected.SameFs(this);
|
||||
|
||||
if (selected.SameFs(this) && selected.m_type == SelectedType::Cut) {
|
||||
for (const auto& p : selected.m_files) {
|
||||
@@ -1271,7 +1277,7 @@ void FsView::OnPasteCallback() {
|
||||
} else {
|
||||
pbox->SetTitle(p.name);
|
||||
pbox->NewTransfer("Copying "_i18n + src_path);
|
||||
R_TRY(pbox->CopyFile(src_fs, m_fs.get(), src_path, dst_path));
|
||||
R_TRY(pbox->CopyFile(src_fs, m_fs.get(), src_path, dst_path, is_same_fs));
|
||||
R_TRY(on_paste_file(src_path, dst_path));
|
||||
}
|
||||
}
|
||||
@@ -1301,7 +1307,7 @@ void FsView::OnPasteCallback() {
|
||||
|
||||
pbox->SetTitle(p.name);
|
||||
pbox->NewTransfer("Copying "_i18n + src_path);
|
||||
R_TRY(pbox->CopyFile(src_fs, m_fs.get(), src_path, dst_path));
|
||||
R_TRY(pbox->CopyFile(src_fs, m_fs.get(), src_path, dst_path, is_same_fs));
|
||||
R_TRY(on_paste_file(src_path, dst_path));
|
||||
}
|
||||
}
|
||||
@@ -1880,9 +1886,9 @@ void Menu::Update(Controller* controller, TouchInfo* touch) {
|
||||
// workaround the buttons not being display properly.
|
||||
// basically, inherit all actions from the view, draw them,
|
||||
// then restore state after.
|
||||
const auto actions_copy = GetActions();
|
||||
ON_SCOPE_EXIT(m_actions = actions_copy);
|
||||
m_actions.insert_range(view->GetActions());
|
||||
// const auto actions_copy = GetActions();
|
||||
// ON_SCOPE_EXIT(m_actions = actions_copy);
|
||||
// m_actions.insert_range(view->GetActions());
|
||||
|
||||
MenuBase::Update(controller, touch);
|
||||
view->Update(controller, touch);
|
||||
|
||||
@@ -263,7 +263,7 @@ auto ProgressBox::ShouldExitResult() -> Result {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
auto ProgressBox::CopyFile(fs::Fs* fs_src, fs::Fs* fs_dst, const fs::FsPath& src_path, const fs::FsPath& dst_path) -> Result {
|
||||
auto ProgressBox::CopyFile(fs::Fs* fs_src, fs::Fs* fs_dst, const fs::FsPath& src_path, const fs::FsPath& dst_path, bool single_threaded) -> Result {
|
||||
const auto is_file_based_emummc = App::IsFileBaseEmummc();
|
||||
const auto is_both_native = fs_src->IsNative() && fs_dst->IsNative();
|
||||
|
||||
@@ -300,20 +300,20 @@ auto ProgressBox::CopyFile(fs::Fs* fs_src, fs::Fs* fs_dst, const fs::FsPath& src
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
}, single_threaded ? thread::Mode::SingleThreaded : thread::Mode::MultiThreaded
|
||||
));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
auto ProgressBox::CopyFile(fs::Fs* fs, const fs::FsPath& src_path, const fs::FsPath& dst_path) -> Result {
|
||||
return CopyFile(fs, fs, src_path, dst_path);
|
||||
auto ProgressBox::CopyFile(fs::Fs* fs, const fs::FsPath& src_path, const fs::FsPath& dst_path, bool single_threaded) -> Result {
|
||||
return CopyFile(fs, fs, src_path, dst_path, single_threaded);
|
||||
}
|
||||
|
||||
auto ProgressBox::CopyFile(const fs::FsPath& src_path, const fs::FsPath& dst_path) -> Result {
|
||||
auto ProgressBox::CopyFile(const fs::FsPath& src_path, const fs::FsPath& dst_path, bool single_threaded) -> Result {
|
||||
fs::FsNativeSd fs;
|
||||
R_TRY(fs.GetFsOpenResult());
|
||||
return CopyFile(&fs, src_path, dst_path);
|
||||
return CopyFile(&fs, src_path, dst_path, single_threaded);
|
||||
}
|
||||
|
||||
void ProgressBox::Yield() {
|
||||
|
||||
Reference in New Issue
Block a user