add save backup/restore, fix filebrowser touch screen, optimise all zip/unzip file code by using bigger stdio buffers.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "threaded_file_transfer.hpp"
|
||||
#include "nro.hpp"
|
||||
#include "web.hpp"
|
||||
#include "minizip_helper.hpp"
|
||||
|
||||
#include <minIni.h>
|
||||
#include <string>
|
||||
@@ -77,62 +78,6 @@ constexpr const char* ORDER_STR[] = {
|
||||
"Asc",
|
||||
};
|
||||
|
||||
struct MzMem {
|
||||
const void* buf;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
ZPOS64_T minizip_tell_file_func(voidpf opaque, voidpf stream) {
|
||||
auto mem = static_cast<const MzMem*>(opaque);
|
||||
return mem->offset;
|
||||
}
|
||||
|
||||
long minizip_seek_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) {
|
||||
auto mem = static_cast<MzMem*>(opaque);
|
||||
size_t new_offset = 0;
|
||||
|
||||
switch (origin) {
|
||||
case ZLIB_FILEFUNC_SEEK_SET: new_offset = offset; break;
|
||||
case ZLIB_FILEFUNC_SEEK_CUR: new_offset = mem->offset + offset; break;
|
||||
case ZLIB_FILEFUNC_SEEK_END: new_offset = (mem->size - 1) + offset; break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
if (new_offset > mem->size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem->offset = new_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
voidpf minizip_open_file_func(voidpf opaque, const void* filename, int mode) {
|
||||
return opaque;
|
||||
}
|
||||
|
||||
uLong minizip_read_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) {
|
||||
auto mem = static_cast<MzMem*>(opaque);
|
||||
|
||||
size = std::min(size, mem->size - mem->offset);
|
||||
std::memcpy(buf, (const u8*)mem->buf + mem->offset, size);
|
||||
mem->offset += size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int minizip_close_file_func(voidpf opaque, voidpf stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr zlib_filefunc64_def zlib_filefunc = {
|
||||
.zopen64_file = minizip_open_file_func,
|
||||
.zread_file = minizip_read_file_func,
|
||||
.ztell64_file = minizip_tell_file_func,
|
||||
.zseek64_file = minizip_seek_file_func,
|
||||
.zclose_file = minizip_close_file_func,
|
||||
};
|
||||
|
||||
auto BuildIconUrl(const Entry& e) -> std::string {
|
||||
char out[0x100];
|
||||
std::snprintf(out, sizeof(out), "%s/packages/%s/icon.png", URL_BASE, e.name.c_str());
|
||||
@@ -474,20 +419,17 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> Result {
|
||||
}
|
||||
}
|
||||
|
||||
struct MzMem mem{};
|
||||
mem.buf = api_result.data.data();
|
||||
mem.size = api_result.data.size();
|
||||
auto file_func = zlib_filefunc;
|
||||
file_func.opaque = &mem;
|
||||
|
||||
zlib_filefunc64_def* file_func_ptr{};
|
||||
mz::MzSpan mz_span{api_result.data};
|
||||
zlib_filefunc64_def file_func;
|
||||
if (!file_download) {
|
||||
file_func_ptr = &file_func;
|
||||
mz::FileFuncSpan(&mz_span, &file_func);
|
||||
} else {
|
||||
mz::FileFuncStdio(&file_func);
|
||||
}
|
||||
|
||||
// 3. extract the zip
|
||||
if (!pbox->ShouldExit()) {
|
||||
auto zfile = unzOpen2_64(zip_out, file_func_ptr);
|
||||
auto zfile = unzOpen2_64(zip_out, &file_func);
|
||||
R_UNLESS(zfile, 0x1);
|
||||
ON_SCOPE_EXIT(unzClose(zfile));
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "hasher.hpp"
|
||||
#include "location.hpp"
|
||||
#include "threaded_file_transfer.hpp"
|
||||
#include "minizip_helper.hpp"
|
||||
|
||||
#include "yati/yati.hpp"
|
||||
#include "yati/source/file.hpp"
|
||||
@@ -435,7 +436,6 @@ 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);
|
||||
@@ -790,7 +790,10 @@ void FsView::ZipFiles(fs::FsPath zip_out) {
|
||||
zip_info.tmz_date.tm_mon = tm->tm_mon;
|
||||
zip_info.tmz_date.tm_year = tm->tm_year;
|
||||
|
||||
auto zfile = zipOpen(zip_out, APPEND_STATUS_CREATE);
|
||||
zlib_filefunc64_def file_func;
|
||||
mz::FileFuncStdio(&file_func);
|
||||
|
||||
auto zfile = zipOpen2_64(zip_out, APPEND_STATUS_CREATE, nullptr, &file_func);
|
||||
R_UNLESS(zfile, 0x1);
|
||||
ON_SCOPE_EXIT(zipClose(zfile, "sphaira v" APP_VERSION_HASH));
|
||||
|
||||
@@ -1854,6 +1857,13 @@ Menu::~Menu() {
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
MenuBase::Update(controller, touch);
|
||||
view->Update(controller, touch);
|
||||
}
|
||||
|
||||
@@ -998,6 +998,11 @@ void Menu::Update(Controller* controller, TouchInfo* touch) {
|
||||
void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
||||
MenuBase::Draw(vg, theme);
|
||||
|
||||
if (m_entries.empty()) {
|
||||
gfx::drawTextArgs(vg, GetX() + GetW() / 2.f, GetY() + GetH() / 2.f, 36.f, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE, theme->GetColour(ThemeEntryID_TEXT_INFO), "Empty..."_i18n.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// max images per frame, in order to not hit io / gpu too hard.
|
||||
const int image_load_max = 2;
|
||||
int image_load_count = 0;
|
||||
@@ -1096,7 +1101,7 @@ void Menu::ScanHomebrew() {
|
||||
u64 unk_x11;// = e.unk_x11;
|
||||
memcpy(&unk_x0a, e.unk_x0a, sizeof(e.unk_x0a));
|
||||
memcpy(&unk_x11, e.unk_x11, sizeof(e.unk_x11));
|
||||
log_write("ID: %016lx got type: %u unk_x09: %u unk_x0a: %zu unk_x10: %u unk_x11: %zu\n", e.application_id, e.type,
|
||||
log_write("ID: %016lx got type: %u unk_x09: %u unk_x0a: %zu unk_x10: %u unk_x11: %zu\n", e.app_id, e.type,
|
||||
unk_x09,
|
||||
unk_x0a,
|
||||
unk_x10,
|
||||
|
||||
@@ -529,7 +529,7 @@ Result Menu::GcMount() {
|
||||
// the fs, same as mounting storage.
|
||||
for (u32 i = 0; i < REMOUNT_ATTEMPT_MAX; i++) {
|
||||
R_TRY(fsDeviceOperatorGetGameCardHandle(std::addressof(m_dev_op), std::addressof(m_handle)));
|
||||
m_fs = std::make_unique<fs::FsNativeGameCard>(std::addressof(m_handle), FsGameCardPartition_Secure, false);
|
||||
m_fs = std::make_unique<fs::FsNativeGameCard>(std::addressof(m_handle), FsGameCardPartition_Secure);
|
||||
if (R_SUCCEEDED(m_fs->GetFsOpenResult())) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "ui/menus/ftp_menu.hpp"
|
||||
#include "ui/menus/gc_menu.hpp"
|
||||
#include "ui/menus/game_menu.hpp"
|
||||
#include "ui/menus/save_menu.hpp"
|
||||
#include "ui/menus/appstore.hpp"
|
||||
|
||||
#include "app.hpp"
|
||||
@@ -49,6 +50,7 @@ const MiscMenuEntry MISC_MENU_ENTRIES[] = {
|
||||
{ .name = "Appstore", .title = "Appstore", .func = MiscMenuFuncGenerator<ui::menu::appstore::Menu>, .flag = MiscMenuFlag_Shortcut },
|
||||
{ .name = "Games", .title = "Games", .func = MiscMenuFuncGenerator<ui::menu::game::Menu>, .flag = MiscMenuFlag_Shortcut },
|
||||
{ .name = "FileBrowser", .title = "FileBrowser", .func = MiscMenuFuncGenerator<ui::menu::filebrowser::Menu>, .flag = MiscMenuFlag_Shortcut },
|
||||
{ .name = "Saves", .title = "Saves", .func = MiscMenuFuncGenerator<ui::menu::save::Menu>, .flag = MiscMenuFlag_Shortcut },
|
||||
{ .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut },
|
||||
{ .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut },
|
||||
{ .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install },
|
||||
|
||||
1274
sphaira/source/ui/menus/save_menu.cpp
Normal file
1274
sphaira/source/ui/menus/save_menu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -88,6 +88,7 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||
m_last_offset = m_offset;
|
||||
}
|
||||
|
||||
const auto action = m_action;
|
||||
const auto title = m_title;
|
||||
const auto transfer = m_transfer;
|
||||
const auto size = m_size;
|
||||
@@ -166,7 +167,7 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||
gfx::drawTextArgs(vg, center_x, prog_bar.y + prog_bar.h + 30, 18, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "%s (%s)", time_str, speed_str);
|
||||
}
|
||||
|
||||
gfx::drawTextArgs(vg, center_x, m_pos.y + 40, 24, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), m_action.c_str());
|
||||
gfx::drawTextArgs(vg, center_x, m_pos.y + 40, 24, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), action.c_str());
|
||||
|
||||
const auto draw_text = [&](ScrollingText& scroll, const std::string& txt, float y, float size, float pad, ThemeEntryID id){
|
||||
float bounds[4];
|
||||
@@ -187,6 +188,14 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void {
|
||||
nvgRestore(vg);
|
||||
}
|
||||
|
||||
auto ProgressBox::SetActionName(const std::string& action) -> ProgressBox& {
|
||||
mutexLock(&m_mutex);
|
||||
m_action = action;
|
||||
mutexUnlock(&m_mutex);
|
||||
Yield();
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto ProgressBox::SetTitle(const std::string& title) -> ProgressBox& {
|
||||
mutexLock(&m_mutex);
|
||||
m_title = title;
|
||||
|
||||
Reference in New Issue
Block a user