enable warning flags, fix all warning, default init all vars, bump stb libs used in nanovg
fixes #98
This commit is contained in:
@@ -81,12 +81,54 @@ target_compile_definitions(sphaira PRIVATE
|
|||||||
-DAPP_VERSION_HASH="${sphaira_VERSION_HASH}"
|
-DAPP_VERSION_HASH="${sphaira_VERSION_HASH}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_compile_options(sphaira PRIVATE
|
||||||
|
-Wall
|
||||||
|
-Wextra
|
||||||
|
|
||||||
|
# unsure if it's a good idea to enable these by default as
|
||||||
|
# it may cause breakage upon compiler updates.
|
||||||
|
# -Werror
|
||||||
|
# -Wfatal-errors
|
||||||
|
|
||||||
|
# disabled as nx uses s64 for size and offset, however stl uses size_t instead, thus
|
||||||
|
# there being a lot of warnings.
|
||||||
|
-Wno-sign-compare
|
||||||
|
# disabled as many overriden methods don't use the params.
|
||||||
|
-Wno-unused-parameter
|
||||||
|
# pedantic warning, missing fields are set to 0.
|
||||||
|
-Wno-missing-field-initializers
|
||||||
|
# disabled as it warns for strcat 2 paths together, but it will never
|
||||||
|
# overflow due to fs enforcing a max path len anyway.
|
||||||
|
-Wno-format-truncation
|
||||||
|
|
||||||
|
# the below are taken from my gba emulator, they've served me well ;)
|
||||||
|
-Wformat-overflow=2
|
||||||
|
-Wundef
|
||||||
|
-Wmissing-include-dirs
|
||||||
|
-fstrict-aliasing
|
||||||
|
-Wstrict-overflow=2
|
||||||
|
-Walloca
|
||||||
|
-Wduplicated-cond
|
||||||
|
-Wwrite-strings
|
||||||
|
-Wdate-time
|
||||||
|
-Wlogical-op
|
||||||
|
-Wpacked
|
||||||
|
-Wcast-qual
|
||||||
|
-Wcast-align
|
||||||
|
-Wimplicit-fallthrough=5
|
||||||
|
-Wsuggest-final-types
|
||||||
|
-Wuninitialized
|
||||||
|
-fimplicit-constexpr
|
||||||
|
-Wmissing-requires
|
||||||
|
)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
set(FETCHCONTENT_QUIET FALSE)
|
set(FETCHCONTENT_QUIET FALSE)
|
||||||
|
|
||||||
FetchContent_Declare(ftpsrv
|
FetchContent_Declare(ftpsrv
|
||||||
GIT_REPOSITORY https://github.com/ITotalJustice/ftpsrv.git
|
GIT_REPOSITORY https://github.com/ITotalJustice/ftpsrv.git
|
||||||
GIT_TAG 1.2.1
|
GIT_TAG 1.2.1
|
||||||
|
SOURCE_SUBDIR NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_Declare(libhaze
|
FetchContent_Declare(libhaze
|
||||||
@@ -101,7 +143,7 @@ FetchContent_Declare(libpulsar
|
|||||||
|
|
||||||
FetchContent_Declare(nanovg
|
FetchContent_Declare(nanovg
|
||||||
GIT_REPOSITORY https://github.com/ITotalJustice/nanovg-deko3d.git
|
GIT_REPOSITORY https://github.com/ITotalJustice/nanovg-deko3d.git
|
||||||
GIT_TAG 1902b38
|
GIT_TAG 845c9fc
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_Declare(stb
|
FetchContent_Declare(stb
|
||||||
@@ -136,8 +178,6 @@ set(NANOVG_NO_GIF ON)
|
|||||||
set(NANOVG_NO_HDR ON)
|
set(NANOVG_NO_HDR ON)
|
||||||
set(NANOVG_NO_PIC ON)
|
set(NANOVG_NO_PIC ON)
|
||||||
set(NANOVG_NO_PNM ON)
|
set(NANOVG_NO_PNM ON)
|
||||||
set(NANOVG_STBI_STATIC OFF)
|
|
||||||
set(NANOVG_STBTT_STATIC ON)
|
|
||||||
|
|
||||||
set(YYJSON_DISABLE_READER OFF)
|
set(YYJSON_DISABLE_READER OFF)
|
||||||
set(YYJSON_DISABLE_WRITER OFF)
|
set(YYJSON_DISABLE_WRITER OFF)
|
||||||
@@ -148,7 +188,7 @@ set(YYJSON_DISABLE_UTF8_VALIDATION ON)
|
|||||||
set(YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS OFF)
|
set(YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS OFF)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(
|
FetchContent_MakeAvailable(
|
||||||
# ftpsrv
|
ftpsrv
|
||||||
libhaze
|
libhaze
|
||||||
libpulsar
|
libpulsar
|
||||||
nanovg
|
nanovg
|
||||||
@@ -157,11 +197,6 @@ FetchContent_MakeAvailable(
|
|||||||
yyjson
|
yyjson
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_GetProperties(ftpsrv)
|
|
||||||
if (NOT ftpsrv_POPULATED)
|
|
||||||
FetchContent_Populate(ftpsrv)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(FTPSRV_LIB_BUILD TRUE)
|
set(FTPSRV_LIB_BUILD TRUE)
|
||||||
set(FTPSRV_LIB_SOCK_UNISTD TRUE)
|
set(FTPSRV_LIB_SOCK_UNISTD TRUE)
|
||||||
set(FTPSRV_LIB_VFS_CUSTOM ${ftpsrv_SOURCE_DIR}/src/platform/nx/vfs_nx.h)
|
set(FTPSRV_LIB_VFS_CUSTOM ${ftpsrv_SOURCE_DIR}/src/platform/nx/vfs_nx.h)
|
||||||
@@ -178,6 +213,7 @@ set(FTPSRV_LIB_CUSTOM_DEFINES
|
|||||||
USE_VFS_SAVE=$<BOOL:TRUE>
|
USE_VFS_SAVE=$<BOOL:TRUE>
|
||||||
USE_VFS_STORAGE=$<BOOL:TRUE>
|
USE_VFS_STORAGE=$<BOOL:TRUE>
|
||||||
USE_VFS_GC=$<BOOL:${USE_VFS_GC}>
|
USE_VFS_GC=$<BOOL:${USE_VFS_GC}>
|
||||||
|
USE_VFS_USBHSFS=$<BOOL:FALSE>
|
||||||
VFS_NX_BUFFER_IO=$<BOOL:TRUE>
|
VFS_NX_BUFFER_IO=$<BOOL:TRUE>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ public:
|
|||||||
// todo: move this into it's own menu
|
// todo: move this into it's own menu
|
||||||
option::OptionLong m_text_scroll_speed{"accessibility", "text_scroll_speed", 1}; // normal
|
option::OptionLong m_text_scroll_speed{"accessibility", "text_scroll_speed", 1}; // normal
|
||||||
|
|
||||||
PLSR_BFSAR m_qlaunch_bfsar{};
|
|
||||||
PLSR_PlayerSoundId m_sound_ids[SoundEffect_MAX]{};
|
PLSR_PlayerSoundId m_sound_ids[SoundEffect_MAX]{};
|
||||||
|
|
||||||
private: // from nanovg decko3d example by adubbz
|
private: // from nanovg decko3d example by adubbz
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ public:
|
|||||||
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
auto Draw(NVGcontext* vg, Theme* theme) -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result m_code;
|
Result m_code{};
|
||||||
std::string m_message;
|
std::string m_message{};
|
||||||
std::string m_module_str;
|
std::string m_module_str{};
|
||||||
std::string m_description_str;
|
std::string m_description_str{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ private:
|
|||||||
const s64 m_row;
|
const s64 m_row;
|
||||||
const s64 m_page;
|
const s64 m_page;
|
||||||
|
|
||||||
Vec4 m_v;
|
Vec4 m_v{};
|
||||||
Vec2 m_pad;
|
Vec2 m_pad{};
|
||||||
|
|
||||||
Vec4 m_scrollbar{};
|
Vec4 m_scrollbar{};
|
||||||
|
|
||||||
|
|||||||
@@ -42,26 +42,26 @@ enum class EntryStatus {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
std::string category; // todo: lable
|
std::string category{}; // todo: lable
|
||||||
std::string binary; // optional, only valid for .nro
|
std::string binary{}; // optional, only valid for .nro
|
||||||
std::string updated; // date of update
|
std::string updated{}; // date of update
|
||||||
std::string name;
|
std::string name{};
|
||||||
std::string license; // optional
|
std::string license{}; // optional
|
||||||
std::string title; // same as name but with spaces
|
std::string title{}; // same as name but with spaces
|
||||||
std::string url; // url of repo (optional?)
|
std::string url{}; // url of repo (optional?)
|
||||||
std::string description;
|
std::string description{};
|
||||||
std::string author;
|
std::string author{};
|
||||||
std::string changelog; // optional
|
std::string changelog{}; // optional
|
||||||
u64 screens; // number of screenshots
|
u64 screens{}; // number of screenshots
|
||||||
u64 extracted; // extracted size in KiB
|
u64 extracted{}; // extracted size in KiB
|
||||||
std::string version;
|
std::string version{};
|
||||||
u64 filesize; // compressed size in KiB
|
u64 filesize{}; // compressed size in KiB
|
||||||
std::string details;
|
std::string details{};
|
||||||
u64 app_dls;
|
u64 app_dls{};
|
||||||
std::string md5; // md5 of the zip
|
std::string md5{}; // md5 of the zip
|
||||||
|
|
||||||
LazyImage image;
|
LazyImage image{};
|
||||||
u32 updated_num;
|
u32 updated_num{};
|
||||||
EntryStatus status{EntryStatus::Get};
|
EntryStatus status{EntryStatus::Get};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,13 +99,13 @@ private:
|
|||||||
Menu& m_menu;
|
Menu& m_menu;
|
||||||
|
|
||||||
s64 m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
std::vector<Option> m_options;
|
std::vector<Option> m_options{};
|
||||||
LazyImage m_banner;
|
LazyImage m_banner{};
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
|
|
||||||
std::shared_ptr<ScrollableText> m_details;
|
std::shared_ptr<ScrollableText> m_details{};
|
||||||
std::shared_ptr<ScrollableText> m_changelog;
|
std::shared_ptr<ScrollableText> m_changelog{};
|
||||||
std::shared_ptr<ScrollableText> m_detail_changelog;
|
std::shared_ptr<ScrollableText> m_detail_changelog{};
|
||||||
|
|
||||||
bool m_show_changlog{};
|
bool m_show_changlog{};
|
||||||
};
|
};
|
||||||
@@ -134,34 +134,6 @@ enum OrderType {
|
|||||||
OrderType_Ascending,
|
OrderType_Ascending,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FeedbackEntry {
|
|
||||||
u32 id;
|
|
||||||
u64 time;
|
|
||||||
std::string package; // name of package
|
|
||||||
std::string content; // the feedback message that was sent
|
|
||||||
std::string reply; // the reply, "" if no reply yet :)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FeedbackMenu final : MenuBase {
|
|
||||||
FeedbackMenu(const std::vector<Entry>& package_entries, LazyImage& default_image);
|
|
||||||
~FeedbackMenu();
|
|
||||||
|
|
||||||
void Update(Controller* controller, TouchInfo* touch) override;
|
|
||||||
void Draw(NVGcontext* vg, Theme* theme) override;
|
|
||||||
void OnFocusGained() override;
|
|
||||||
|
|
||||||
void SetIndex(s64 index);
|
|
||||||
void ScanHomebrew();
|
|
||||||
void Sort();
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::vector<Entry>& m_package_entries;
|
|
||||||
LazyImage& m_default_image;
|
|
||||||
std::vector<FeedbackEntry> m_entries;
|
|
||||||
s64 m_index{}; // where i am in the array
|
|
||||||
ImageDownloadState m_repo_download_state{ImageDownloadState::None};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Menu final : MenuBase {
|
struct Menu final : MenuBase {
|
||||||
Menu(const std::vector<NroEntry>& nro_entries);
|
Menu(const std::vector<NroEntry>& nro_entries);
|
||||||
~Menu();
|
~Menu();
|
||||||
@@ -191,27 +163,27 @@ struct Menu final : MenuBase {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<NroEntry>& m_nro_entries;
|
const std::vector<NroEntry>& m_nro_entries;
|
||||||
std::vector<Entry> m_entries;
|
std::vector<Entry> m_entries{};
|
||||||
std::vector<EntryMini> m_entries_index[Filter_MAX];
|
std::vector<EntryMini> m_entries_index[Filter_MAX]{};
|
||||||
std::vector<EntryMini> m_entries_index_author;
|
std::vector<EntryMini> m_entries_index_author{};
|
||||||
std::vector<EntryMini> m_entries_index_search;
|
std::vector<EntryMini> m_entries_index_search{};
|
||||||
std::span<EntryMini> m_entries_current;
|
std::span<EntryMini> m_entries_current{};
|
||||||
|
|
||||||
Filter m_filter{Filter::Filter_All};
|
Filter m_filter{Filter::Filter_All};
|
||||||
SortType m_sort{SortType::SortType_Updated};
|
SortType m_sort{SortType::SortType_Updated};
|
||||||
OrderType m_order{OrderType::OrderType_Descending};
|
OrderType m_order{OrderType::OrderType_Descending};
|
||||||
|
|
||||||
s64 m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
LazyImage m_default_image;
|
LazyImage m_default_image{};
|
||||||
LazyImage m_update;
|
LazyImage m_update{};
|
||||||
LazyImage m_get;
|
LazyImage m_get{};
|
||||||
LazyImage m_local;
|
LazyImage m_local{};
|
||||||
LazyImage m_installed;
|
LazyImage m_installed{};
|
||||||
ImageDownloadState m_repo_download_state{ImageDownloadState::None};
|
ImageDownloadState m_repo_download_state{ImageDownloadState::None};
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
|
|
||||||
std::string m_search_term;
|
std::string m_search_term{};
|
||||||
std::string m_author_term;
|
std::string m_author_term{};
|
||||||
s64 m_entry_search_jump_back{};
|
s64 m_entry_search_jump_back{};
|
||||||
s64 m_entry_author_jump_back{};
|
s64 m_entry_author_jump_back{};
|
||||||
bool m_is_search{};
|
bool m_is_search{};
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ struct Menu final : MenuBase {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const fs::FsPath m_path;
|
const fs::FsPath m_path;
|
||||||
fs::FsNativeSd m_fs;
|
fs::FsNativeSd m_fs{};
|
||||||
FsFile m_file;
|
FsFile m_file{};
|
||||||
s64 m_file_size{};
|
s64 m_file_size{};
|
||||||
s64 m_file_offset{};
|
s64 m_file_offset{};
|
||||||
|
|
||||||
std::unique_ptr<ScrollableText> m_scroll_text;
|
std::unique_ptr<ScrollableText> m_scroll_text{};
|
||||||
|
|
||||||
s64 m_start{};
|
s64 m_start{};
|
||||||
s64 m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
|
|||||||
@@ -86,23 +86,23 @@ struct FileEntry : FsDirectoryEntry {
|
|||||||
|
|
||||||
struct FileAssocEntry {
|
struct FileAssocEntry {
|
||||||
fs::FsPath path{}; // ini name
|
fs::FsPath path{}; // ini name
|
||||||
std::string name; // ini name
|
std::string name{}; // ini name
|
||||||
std::vector<std::string> ext; // list of ext
|
std::vector<std::string> ext{}; // list of ext
|
||||||
std::vector<std::string> database; // list of systems
|
std::vector<std::string> database{}; // list of systems
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LastFile {
|
struct LastFile {
|
||||||
fs::FsPath name;
|
fs::FsPath name{};
|
||||||
s64 index;
|
s64 index{};
|
||||||
float offset;
|
float offset{};
|
||||||
s64 entries_count;
|
s64 entries_count{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FsDirCollection {
|
struct FsDirCollection {
|
||||||
fs::FsPath path;
|
fs::FsPath path{};
|
||||||
fs::FsPath parent_name;
|
fs::FsPath parent_name{};
|
||||||
std::vector<FsDirectoryEntry> files;
|
std::vector<FsDirectoryEntry> files{};
|
||||||
std::vector<FsDirectoryEntry> dirs;
|
std::vector<FsDirectoryEntry> dirs{};
|
||||||
};
|
};
|
||||||
|
|
||||||
using FsDirCollections = std::vector<FsDirCollection>;
|
using FsDirCollections = std::vector<FsDirCollection>;
|
||||||
@@ -231,32 +231,32 @@ private:
|
|||||||
static constexpr inline const char* INI_SECTION = "filebrowser";
|
static constexpr inline const char* INI_SECTION = "filebrowser";
|
||||||
|
|
||||||
const std::vector<NroEntry>& m_nro_entries;
|
const std::vector<NroEntry>& m_nro_entries;
|
||||||
std::unique_ptr<fs::FsNative> m_fs;
|
std::unique_ptr<fs::FsNative> m_fs{};
|
||||||
FsType m_fs_type;
|
FsType m_fs_type{};
|
||||||
fs::FsPath m_path;
|
fs::FsPath m_path{};
|
||||||
std::vector<FileEntry> m_entries;
|
std::vector<FileEntry> m_entries{};
|
||||||
std::vector<u32> m_entries_index; // files not including hidden
|
std::vector<u32> m_entries_index{}; // files not including hidden
|
||||||
std::vector<u32> m_entries_index_hidden; // includes hidden files
|
std::vector<u32> m_entries_index_hidden{}; // includes hidden files
|
||||||
std::vector<u32> m_entries_index_search; // files found via search
|
std::vector<u32> m_entries_index_search{}; // files found via search
|
||||||
std::span<u32> m_entries_current;
|
std::span<u32> m_entries_current{};
|
||||||
|
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
std::optional<fs::FsPath> m_daybreak_path;
|
std::optional<fs::FsPath> m_daybreak_path{};
|
||||||
|
|
||||||
// search options
|
// search options
|
||||||
// show files [X]
|
// show files [X]
|
||||||
// show folders [X]
|
// show folders [X]
|
||||||
// recursive (slow) [ ]
|
// recursive (slow) [ ]
|
||||||
|
|
||||||
std::vector<FileAssocEntry> m_assoc_entries;
|
std::vector<FileAssocEntry> m_assoc_entries{};
|
||||||
std::vector<FileEntry> m_selected_files;
|
std::vector<FileEntry> m_selected_files{};
|
||||||
|
|
||||||
// this keeps track of the highlighted file before opening a folder
|
// this keeps track of the highlighted file before opening a folder
|
||||||
// if the user presses B to go back to the previous dir
|
// if the user presses B to go back to the previous dir
|
||||||
// this vector is popped, then, that entry is checked if it still exists
|
// this vector is popped, then, that entry is checked if it still exists
|
||||||
// if it does, the index becomes that file.
|
// if it does, the index becomes that file.
|
||||||
std::vector<LastFile> m_previous_highlighted_file;
|
std::vector<LastFile> m_previous_highlighted_file{};
|
||||||
fs::FsPath m_selected_path;
|
fs::FsPath m_selected_path{};
|
||||||
s64 m_index{};
|
s64 m_index{};
|
||||||
s64 m_selected_count{};
|
s64 m_selected_count{};
|
||||||
SelectedType m_selected_type{SelectedType::None};
|
SelectedType m_selected_type{SelectedType::None};
|
||||||
|
|||||||
@@ -10,35 +10,35 @@
|
|||||||
namespace sphaira::ui::menu::gh {
|
namespace sphaira::ui::menu::gh {
|
||||||
|
|
||||||
struct AssetEntry {
|
struct AssetEntry {
|
||||||
std::string name;
|
std::string name{};
|
||||||
std::string path;
|
std::string path{};
|
||||||
std::string pre_install_message;
|
std::string pre_install_message{};
|
||||||
std::string post_install_message;
|
std::string post_install_message{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
fs::FsPath json_path;
|
fs::FsPath json_path{};
|
||||||
std::string url;
|
std::string url{};
|
||||||
std::string owner;
|
std::string owner{};
|
||||||
std::string repo;
|
std::string repo{};
|
||||||
std::string tag;
|
std::string tag{};
|
||||||
std::string pre_install_message;
|
std::string pre_install_message{};
|
||||||
std::string post_install_message;
|
std::string post_install_message{};
|
||||||
std::vector<AssetEntry> assets;
|
std::vector<AssetEntry> assets{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GhApiAsset {
|
struct GhApiAsset {
|
||||||
std::string name;
|
std::string name{};
|
||||||
std::string content_type;
|
std::string content_type{};
|
||||||
u64 size;
|
u64 size{};
|
||||||
u64 download_count;
|
u64 download_count{};
|
||||||
std::string browser_download_url;
|
std::string browser_download_url{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GhApiEntry {
|
struct GhApiEntry {
|
||||||
std::string tag_name;
|
std::string tag_name{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
std::vector<GhApiAsset> assets;
|
std::vector<GhApiAsset> assets{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Menu final : MenuBase {
|
struct Menu final : MenuBase {
|
||||||
@@ -66,9 +66,9 @@ private:
|
|||||||
void UpdateSubheading();
|
void UpdateSubheading();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Entry> m_entries;
|
std::vector<Entry> m_entries{};
|
||||||
s64 m_index{};
|
s64 m_index{};
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui::menu::gh
|
} // namespace sphaira::ui::menu::gh
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ struct Menu final : MenuBase {
|
|||||||
private:
|
private:
|
||||||
static constexpr inline const char* INI_SECTION = "homebrew";
|
static constexpr inline const char* INI_SECTION = "homebrew";
|
||||||
|
|
||||||
std::vector<NroEntry> m_entries;
|
std::vector<NroEntry> m_entries{};
|
||||||
s64 m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
|
|
||||||
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_AlphabeticalStar};
|
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_AlphabeticalStar};
|
||||||
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending};
|
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending};
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ private:
|
|||||||
void UpdateVars();
|
void UpdateVars();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_title;
|
std::string m_title{};
|
||||||
std::string m_title_sub_heading;
|
std::string m_title_sub_heading{};
|
||||||
std::string m_sub_heading;
|
std::string m_sub_heading{};
|
||||||
|
|
||||||
struct tm m_tm{};
|
struct tm m_tm{};
|
||||||
TimeStamp m_poll_timestamp{};
|
TimeStamp m_poll_timestamp{};
|
||||||
|
|||||||
@@ -42,79 +42,50 @@ enum class PageLoadState {
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
// all commented out entries are those that we don't query for.
|
|
||||||
// this saves time not only processing the json, but also the download
|
|
||||||
// of said json.
|
|
||||||
// by reducing the fields to only what we need, the size is 4-5x smaller.
|
|
||||||
|
|
||||||
struct Creator {
|
struct Creator {
|
||||||
std::string id;
|
std::string id{};
|
||||||
std::string display_name;
|
std::string display_name{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Details {
|
struct Details {
|
||||||
std::string name;
|
std::string name{};
|
||||||
// std::string description;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Preview {
|
struct Preview {
|
||||||
// std::string original;
|
std::string thumb{};
|
||||||
std::string thumb;
|
LazyImage lazy_image{};
|
||||||
LazyImage lazy_image;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DownloadPack {
|
struct DownloadPack {
|
||||||
std::string filename;
|
std::string filename{};
|
||||||
std::string url;
|
std::string url{};
|
||||||
std::string mimetype;
|
std::string mimetype{};
|
||||||
};
|
};
|
||||||
|
|
||||||
using DownloadTheme = DownloadPack;
|
using DownloadTheme = DownloadPack;
|
||||||
|
|
||||||
struct ThemeEntry {
|
struct ThemeEntry {
|
||||||
std::string id;
|
std::string id{};
|
||||||
// Creator creator;
|
Preview preview{};
|
||||||
// Details details;
|
|
||||||
// std::string last_updated;
|
|
||||||
// u64 dl_count;
|
|
||||||
// u64 like_count;
|
|
||||||
// std::vector<std::string> categories;
|
|
||||||
// std::string target;
|
|
||||||
Preview preview;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// struct Pack {
|
|
||||||
// std::string id;
|
|
||||||
// Creator creator;
|
|
||||||
// Details details;
|
|
||||||
// std::string last_updated;
|
|
||||||
// std::vector<std::string> categories;
|
|
||||||
// u64 dl_count;
|
|
||||||
// u64 like_count;
|
|
||||||
// std::vector<ThemeEntry> themes;
|
|
||||||
// };
|
|
||||||
|
|
||||||
struct PackListEntry {
|
struct PackListEntry {
|
||||||
std::string id;
|
std::string id{};
|
||||||
Creator creator;
|
Creator creator{};
|
||||||
Details details;
|
Details details{};
|
||||||
// std::string last_updated;
|
std::vector<ThemeEntry> themes{};
|
||||||
// std::vector<std::string> categories;
|
|
||||||
// u64 dl_count;
|
|
||||||
// u64 like_count;
|
|
||||||
std::vector<ThemeEntry> themes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Pagination {
|
struct Pagination {
|
||||||
u64 page;
|
u64 page{};
|
||||||
u64 limit;
|
u64 limit{};
|
||||||
u64 page_count;
|
u64 page_count{};
|
||||||
u64 item_count;
|
u64 item_count{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PackList {
|
struct PackList {
|
||||||
std::vector<PackListEntry> packList;
|
std::vector<PackListEntry> packList{};
|
||||||
Pagination pagination;
|
Pagination pagination{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
@@ -123,10 +94,10 @@ struct Config {
|
|||||||
u32 sort_index{};
|
u32 sort_index{};
|
||||||
u32 order_index{};
|
u32 order_index{};
|
||||||
// search query, if empty, its not used
|
// search query, if empty, its not used
|
||||||
std::string query;
|
std::string query{};
|
||||||
// this is actually an array of creator ids, but we don't support that feature
|
// this is actually an array of creator ids, but we don't support that feature
|
||||||
// if empty, its not used
|
// if empty, its not used
|
||||||
std::string creator;
|
std::string creator{};
|
||||||
// defaults
|
// defaults
|
||||||
u32 page{1};
|
u32 page{1};
|
||||||
u32 limit{18};
|
u32 limit{18};
|
||||||
@@ -152,7 +123,7 @@ struct Config {
|
|||||||
struct Menu; // fwd
|
struct Menu; // fwd
|
||||||
|
|
||||||
struct PageEntry {
|
struct PageEntry {
|
||||||
std::vector<PackListEntry> m_packList;
|
std::vector<PackListEntry> m_packList{};
|
||||||
Pagination m_pagination{};
|
Pagination m_pagination{};
|
||||||
PageLoadState m_ready{PageLoadState::None};
|
PageLoadState m_ready{PageLoadState::None};
|
||||||
};
|
};
|
||||||
@@ -172,9 +143,6 @@ struct Menu final : MenuBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// void SetSearch(const std::string& term);
|
|
||||||
// void SetAuthor();
|
|
||||||
|
|
||||||
void InvalidateAllPages();
|
void InvalidateAllPages();
|
||||||
void PackListDownload();
|
void PackListDownload();
|
||||||
void OnPackListDownload();
|
void OnPackListDownload();
|
||||||
@@ -183,14 +151,14 @@ private:
|
|||||||
static constexpr inline const char* INI_SECTION = "themezer";
|
static constexpr inline const char* INI_SECTION = "themezer";
|
||||||
static constexpr inline u32 MAX_ON_PAGE = 16; // same as website
|
static constexpr inline u32 MAX_ON_PAGE = 16; // same as website
|
||||||
|
|
||||||
std::vector<PageEntry> m_pages;
|
std::vector<PageEntry> m_pages{};
|
||||||
s64 m_page_index{};
|
s64 m_page_index{};
|
||||||
s64 m_page_index_max{1};
|
s64 m_page_index_max{1};
|
||||||
|
|
||||||
std::string m_search{};
|
std::string m_search{};
|
||||||
|
|
||||||
s64 m_index{}; // where i am in the array
|
s64 m_index{}; // where i am in the array
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
|
|
||||||
// options
|
// options
|
||||||
option::OptionLong m_sort{INI_SECTION, "sort", 0};
|
option::OptionLong m_sort{INI_SECTION, "sort", 0};
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ private:
|
|||||||
void Draw(NVGcontext* vg, Theme* theme) override;
|
void Draw(NVGcontext* vg, Theme* theme) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_text;
|
std::string m_text{};
|
||||||
std::size_t m_count{180}; // count down to zero
|
std::size_t m_count{180}; // count down to zero
|
||||||
Side m_side;
|
Side m_side{};
|
||||||
bool m_bounds_measured{};
|
bool m_bounds_measured{};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,8 +47,8 @@ private:
|
|||||||
void Draw(NVGcontext* vg, Theme* theme, Entries& entries);
|
void Draw(NVGcontext* vg, Theme* theme, Entries& entries);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Entries m_entries_left;
|
Entries m_entries_left{};
|
||||||
Entries m_entries_right;
|
Entries m_entries_right{};
|
||||||
Mutex m_mutex{};
|
Mutex m_mutex{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_text;
|
std::string m_text{};
|
||||||
Vec2 m_text_pos{};
|
Vec2 m_text_pos{};
|
||||||
bool m_selected{false};
|
bool m_selected{false};
|
||||||
};
|
};
|
||||||
@@ -48,13 +48,13 @@ private:
|
|||||||
void SetIndex(s64 index);
|
void SetIndex(s64 index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_message;
|
std::string m_message{};
|
||||||
Callback m_callback;
|
Callback m_callback{};
|
||||||
|
|
||||||
Vec4 m_spacer_line{};
|
Vec4 m_spacer_line{};
|
||||||
|
|
||||||
s64 m_index{};
|
s64 m_index{};
|
||||||
std::vector<OptionBoxEntry> m_entries;
|
std::vector<OptionBoxEntry> m_entries{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ private:
|
|||||||
static constexpr float m_text_xoffset{15.f};
|
static constexpr float m_text_xoffset{15.f};
|
||||||
static constexpr float m_line_width{1220.f};
|
static constexpr float m_line_width{1220.f};
|
||||||
|
|
||||||
std::string m_title;
|
std::string m_title{};
|
||||||
Items m_items;
|
Items m_items{};
|
||||||
Callback m_callback;
|
Callback m_callback{};
|
||||||
s64 m_index; // index in list array
|
s64 m_index{}; // index in list array
|
||||||
|
|
||||||
std::unique_ptr<List> m_list;
|
std::unique_ptr<List> m_list{};
|
||||||
|
|
||||||
float m_yoff{};
|
float m_yoff{};
|
||||||
float m_line_top{};
|
float m_line_top{};
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ struct ProgressBox final : Widget {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
struct ThreadData {
|
struct ThreadData {
|
||||||
ProgressBox* pbox;
|
ProgressBox* pbox{};
|
||||||
ProgressBoxCallback callback;
|
ProgressBoxCallback callback{};
|
||||||
bool result;
|
bool result{};
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -14,15 +14,15 @@ struct ScrollableText final : Widget {
|
|||||||
// float m_y_off = m_y_off_base;
|
// float m_y_off = m_y_off_base;
|
||||||
// static constexpr float m_clip_y = 250.0F;
|
// static constexpr float m_clip_y = 250.0F;
|
||||||
|
|
||||||
|
static constexpr inline float m_step = 30;
|
||||||
|
const float m_font_size;
|
||||||
const float m_y_off_base;
|
const float m_y_off_base;
|
||||||
float m_y_off;
|
|
||||||
const float m_clip_y;
|
const float m_clip_y;
|
||||||
const float m_end_w;
|
const float m_end_w;
|
||||||
static constexpr float m_step = 30;
|
|
||||||
|
|
||||||
int m_index = 0;
|
float m_y_off{};
|
||||||
const float m_font_size;
|
int m_index{};
|
||||||
float m_bounds[4];
|
float m_bounds[4]{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui
|
} // namespace sphaira::ui
|
||||||
|
|||||||
@@ -323,37 +323,36 @@ inline ActionType operator|(ActionType a, ActionType b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Action final {
|
struct Action final {
|
||||||
|
using CallbackEmpty = std::function<void()>;
|
||||||
|
using CallbackWithBool = std::function<void(bool)>;
|
||||||
using Callback = std::variant<
|
using Callback = std::variant<
|
||||||
std::function<void()>,
|
CallbackEmpty,
|
||||||
std::function<void(bool)>
|
CallbackWithBool
|
||||||
>;
|
>;
|
||||||
|
|
||||||
Action(Callback cb) : m_type{ActionType::DOWN}, m_hint{""}, m_callback{cb}, m_hidden{true} {}
|
Action(Callback cb) : Action{ActionType::DOWN, "", cb} {}
|
||||||
Action(std::string hint, Callback cb) : m_type{ActionType::DOWN}, m_hint{hint}, m_callback{cb} {}
|
Action(std::string hint, Callback cb) : Action{ActionType::DOWN, hint, cb} {}
|
||||||
Action(u8 type, Callback cb) : m_type{type}, m_hint{""}, m_callback{cb}, m_hidden{true} {}
|
Action(u8 type, Callback cb) : Action{type, "", cb} {}
|
||||||
Action(u8 type, std::string hint, Callback cb) : m_type{type}, m_hint{hint}, m_callback{cb} {}
|
Action(u8 type, std::string hint, Callback cb) : m_type{type}, m_callback{cb}, m_hint{hint} {}
|
||||||
|
|
||||||
auto IsHidden() const noexcept { return m_hidden; }
|
auto IsHidden() const noexcept { return m_hint.empty(); }
|
||||||
|
|
||||||
auto Invoke(bool down) const {
|
auto Invoke(bool down) const {
|
||||||
// todo: make this a visit
|
std::visit([down](auto&& arg){
|
||||||
switch (m_callback.index()) {
|
using T = std::decay_t<decltype(arg)>;
|
||||||
case 0:
|
if constexpr(std::is_same_v<T, CallbackEmpty>) {
|
||||||
std::get<0>(m_callback)();
|
arg();
|
||||||
break;
|
} else if constexpr(std::is_same_v<T, CallbackWithBool>) {
|
||||||
case 1:
|
arg(down);
|
||||||
std::get<1>(m_callback)(down);
|
} else {
|
||||||
break;
|
static_assert(false, "non-exhaustive visitor!");
|
||||||
}
|
}
|
||||||
// std::visit([down, this](auto& cb){
|
}, m_callback);
|
||||||
// cb(down);
|
|
||||||
// }), m_callback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 m_type;
|
u8 m_type{};
|
||||||
std::string m_hint; // todo: make optional
|
Callback m_callback{};
|
||||||
Callback m_callback;
|
std::string m_hint{};
|
||||||
bool m_hidden{false}; // replace this optional text
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ struct Widget : public Object {
|
|||||||
|
|
||||||
auto GetUiButtons() const -> uiButtons;
|
auto GetUiButtons() const -> uiButtons;
|
||||||
|
|
||||||
Actions m_actions;
|
Actions m_actions{};
|
||||||
Vec2 m_button_pos{1220, 675};
|
Vec2 m_button_pos{1220, 675};
|
||||||
bool m_focus{false};
|
bool m_focus{false};
|
||||||
bool m_pop{false};
|
bool m_pop{false};
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ void LoadThemeInternal(ThemeMeta meta, ThemeData& theme_data, int inherit_level
|
|||||||
if (!ini_browse(cb, &theme_data, meta.ini_path)) {
|
if (!ini_browse(cb, &theme_data, meta.ini_path)) {
|
||||||
log_write("failed to open ini: %s\n", meta.ini_path.s);
|
log_write("failed to open ini: %s\n", meta.ini_path.s);
|
||||||
} else {
|
} else {
|
||||||
log_write("opened ini: %s\n", meta.ini_path);
|
log_write("opened ini: %s\n", meta.ini_path.s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -666,7 +666,7 @@ void App::SetReplaceHbmenuEnable(bool enable) {
|
|||||||
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
if (std::strcmp(sphaira_nacp.display_version, hbmenu_nacp.display_version) < 0) {
|
if (std::strcmp(sphaira_nacp.display_version, hbmenu_nacp.display_version) < 0) {
|
||||||
if (R_FAILED(rc = fs.copy_entire_file(sphaira_path, "/hbmenu.nro"))) {
|
if (R_FAILED(rc = fs.copy_entire_file(sphaira_path, "/hbmenu.nro"))) {
|
||||||
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path.s, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
} else {
|
} else {
|
||||||
log_write("success with updating hbmenu!\n");
|
log_write("success with updating hbmenu!\n");
|
||||||
}
|
}
|
||||||
@@ -872,23 +872,26 @@ void App::Poll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto gesture = gestures[i];
|
auto gesture = gestures[i];
|
||||||
if (gesture_count && gesture.type == HidGestureType_Swipe) {
|
if (gesture_count && gesture.type == HidGestureType_Touch) {
|
||||||
log_write("[SWIPE] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number);
|
log_write("[TOUCH] got gesture attr: %u direction: %u sampling_number: %zu context_number: %zu\n", gesture.attributes, gesture.direction, gesture.sampling_number, gesture.context_number);
|
||||||
|
}
|
||||||
|
else if (gesture_count && gesture.type == HidGestureType_Swipe) {
|
||||||
|
log_write("[SWIPE] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
|
||||||
}
|
}
|
||||||
else if (gesture_count && gesture.type == HidGestureType_Tap) {
|
else if (gesture_count && gesture.type == HidGestureType_Tap) {
|
||||||
log_write("[TAP] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number);
|
log_write("[TAP] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
|
||||||
}
|
}
|
||||||
else if (gesture_count && gesture.type == HidGestureType_Press) {
|
else if (gesture_count && gesture.type == HidGestureType_Press) {
|
||||||
log_write("[PRESS] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number);
|
log_write("[PRESS] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
|
||||||
}
|
}
|
||||||
else if (gesture_count && gesture.type == HidGestureType_Cancel) {
|
else if (gesture_count && gesture.type == HidGestureType_Cancel) {
|
||||||
log_write("[CANCEL] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number);
|
log_write("[CANCEL] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
|
||||||
}
|
}
|
||||||
else if (gesture_count && gesture.type == HidGestureType_Complete) {
|
else if (gesture_count && gesture.type == HidGestureType_Complete) {
|
||||||
log_write("[COMPLETE] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number);
|
log_write("[COMPLETE] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
|
||||||
}
|
}
|
||||||
else if (gesture_count && gesture.type == HidGestureType_Pan) {
|
else if (gesture_count && gesture.type == HidGestureType_Pan) {
|
||||||
log_write("[PAN] got gesture sampling_number: %d context_number: %d x: %d y: %d dx: %d dy: %d vx: %.2f vy: %.2f count: %d\n", gesture.sampling_number, gesture.context_number, gesture.x, gesture.y, gesture.delta_x, gesture.delta_y, gesture.velocity_x, gesture.velocity_y, gesture.point_count);
|
log_write("[PAN] got gesture direction: %u sampling_number: %zu context_number: %zu x: %d y: %d dx: %d dy: %d vx: %.2f vy: %.2f count: %d\n", gesture.direction, gesture.sampling_number, gesture.context_number, gesture.x, gesture.y, gesture.delta_x, gesture.delta_y, gesture.velocity_x, gesture.velocity_y, gesture.point_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1265,19 +1268,21 @@ App::App(const char* argv0) {
|
|||||||
if (R_SUCCEEDED(romfsMountDataStorageFromProgram(0x0100000000001000, "qlaunch"))) {
|
if (R_SUCCEEDED(romfsMountDataStorageFromProgram(0x0100000000001000, "qlaunch"))) {
|
||||||
ON_SCOPE_EXIT(romfsUnmount("qlaunch"));
|
ON_SCOPE_EXIT(romfsUnmount("qlaunch"));
|
||||||
plsrPlayerInit();
|
plsrPlayerInit();
|
||||||
plsrBFSAROpen("qlaunch:/sound/qlaunch.bfsar", &m_qlaunch_bfsar);
|
PLSR_BFSAR qlaunch_bfsar;
|
||||||
ON_SCOPE_EXIT(plsrBFSARClose(&m_qlaunch_bfsar));
|
if (R_SUCCEEDED(plsrBFSAROpen("qlaunch:/sound/qlaunch.bfsar", &qlaunch_bfsar))) {
|
||||||
|
ON_SCOPE_EXIT(plsrBFSARClose(&qlaunch_bfsar));
|
||||||
|
|
||||||
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconFocus", &m_sound_ids[SoundEffect_Focus]);
|
plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconFocus", &m_sound_ids[SoundEffect_Focus]);
|
||||||
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconScroll", &m_sound_ids[SoundEffect_Scroll]);
|
plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconScroll", &m_sound_ids[SoundEffect_Scroll]);
|
||||||
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconLimit", &m_sound_ids[SoundEffect_Limit]);
|
plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconLimit", &m_sound_ids[SoundEffect_Limit]);
|
||||||
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeStartupMenu_game", &m_sound_ids[SoundEffect_Startup]);
|
plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeStartupMenu_game", &m_sound_ids[SoundEffect_Startup]);
|
||||||
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconAdd", &m_sound_ids[SoundEffect_Install]);
|
plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconAdd", &m_sound_ids[SoundEffect_Install]);
|
||||||
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeInsertError", &m_sound_ids[SoundEffect_Error]);
|
plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeInsertError", &m_sound_ids[SoundEffect_Error]);
|
||||||
|
|
||||||
plsrPlayerSetVolume(m_sound_ids[SoundEffect_Limit], 2.0f);
|
plsrPlayerSetVolume(m_sound_ids[SoundEffect_Limit], 2.0f);
|
||||||
plsrPlayerSetVolume(m_sound_ids[SoundEffect_Focus], 0.5f);
|
plsrPlayerSetVolume(m_sound_ids[SoundEffect_Focus], 0.5f);
|
||||||
PlaySoundEffect(SoundEffect_Startup);
|
PlaySoundEffect(SoundEffect_Startup);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log_write("failed to mount romfs 0x0100000000001000\n");
|
log_write("failed to mount romfs 0x0100000000001000\n");
|
||||||
}
|
}
|
||||||
@@ -1335,7 +1340,7 @@ App::App(const char* argv0) {
|
|||||||
log_write("launching from sphaira created forwarder\n");
|
log_write("launching from sphaira created forwarder\n");
|
||||||
m_is_launched_via_sphaira_forwader = true;
|
m_is_launched_via_sphaira_forwader = true;
|
||||||
} else {
|
} else {
|
||||||
log_write("launching from unknown forwader: %.*s size: %zu\n", loader_info_size, envGetLoaderInfo(), loader_info_size);
|
log_write("launching from unknown forwader: %.*s size: %zu\n", (int)loader_info_size, envGetLoaderInfo(), loader_info_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_write("not launching from forwarder\n");
|
log_write("not launching from forwarder\n");
|
||||||
@@ -1409,11 +1414,8 @@ App::~App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the archive
|
|
||||||
plsrBFSARClose(&m_qlaunch_bfsar);
|
|
||||||
|
|
||||||
// De-initialize our player
|
// De-initialize our player
|
||||||
plsrPlayerExit();
|
plsrPlayerExit();
|
||||||
|
|
||||||
this->destroyFramebufferResources();
|
this->destroyFramebufferResources();
|
||||||
nvgDeleteDk(this->vg);
|
nvgDeleteDk(this->vg);
|
||||||
@@ -1435,7 +1437,7 @@ App::~App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath()))) {
|
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath()))) {
|
||||||
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath(), rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath().s, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
} else {
|
} else {
|
||||||
log_write("success with copying over root file!\n");
|
log_write("success with copying over root file!\n");
|
||||||
}
|
}
|
||||||
@@ -1460,7 +1462,7 @@ App::~App() {
|
|||||||
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
if (std::strcmp(hbmenu_nacp.display_version, sphaira_nacp.display_version) < 0) {
|
if (std::strcmp(hbmenu_nacp.display_version, sphaira_nacp.display_version) < 0) {
|
||||||
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path))) {
|
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path))) {
|
||||||
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path.s, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
} else {
|
} else {
|
||||||
log_write("success with updating hbmenu!\n");
|
log_write("success with updating hbmenu!\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -462,12 +462,12 @@ auto DownloadInternal(CURL* curl, const Api& e) -> ApiResult {
|
|||||||
fs.CreateDirectoryRecursivelyWithPath(tmp_buf);
|
fs.CreateDirectoryRecursivelyWithPath(tmp_buf);
|
||||||
|
|
||||||
if (auto rc = fs.CreateFile(tmp_buf, 0, 0); R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
|
if (auto rc = fs.CreateFile(tmp_buf, 0, 0); R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create file: %s\n", tmp_buf);
|
log_write("failed to create file: %s\n", tmp_buf.s);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(fs.OpenFile(tmp_buf, FsOpenMode_Write|FsOpenMode_Append, &chunk.f))) {
|
if (R_FAILED(fs.OpenFile(tmp_buf, FsOpenMode_Write|FsOpenMode_Append, &chunk.f))) {
|
||||||
log_write("failed to open file: %s\n", tmp_buf);
|
log_write("failed to open file: %s\n", tmp_buf.s);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +553,7 @@ auto DownloadInternal(CURL* curl, const Api& e) -> ApiResult {
|
|||||||
if (http_code == 304) {
|
if (http_code == 304) {
|
||||||
log_write("cached download: %s\n", e.GetUrl().c_str());
|
log_write("cached download: %s\n", e.GetUrl().c_str());
|
||||||
} else {
|
} else {
|
||||||
log_write("un-cached download: %s code: %u\n", e.GetUrl().c_str(), http_code);
|
log_write("un-cached download: %s code: %lu\n", e.GetUrl().c_str(), http_code);
|
||||||
if (e.GetFlags() & Flag_Cache) {
|
if (e.GetFlags() & Flag_Cache) {
|
||||||
g_cache.set(e.GetPath(), header_out);
|
g_cache.set(e.GetPath(), header_out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ Result CreateDirectoryRecursively(FsFileSystem* fs, const FsPath& _path, bool ig
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create folder: %s\n", path);
|
log_write("failed to create folder: %s\n", path.s);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ Result CreateDirectoryRecursivelyWithPath(FsFileSystem* fs, const FsPath& _path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create folder recursively: %s\n", path);
|
log_write("failed to create folder recursively: %s\n", path.s);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ bool init(long index) {
|
|||||||
case SetLanguage_PT: lang_name = "pt"; break;
|
case SetLanguage_PT: lang_name = "pt"; break;
|
||||||
case SetLanguage_RU: lang_name = "ru"; break;
|
case SetLanguage_RU: lang_name = "ru"; break;
|
||||||
case SetLanguage_ZHTW: lang_name = "zh"; break;
|
case SetLanguage_ZHTW: lang_name = "zh"; break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fs::FsPath sdmc_path = "/config/sphaira/i18n/" + lang_name + ".json";
|
const fs::FsPath sdmc_path = "/config/sphaira/i18n/" + lang_name + ".json";
|
||||||
|
|||||||
@@ -4,14 +4,19 @@
|
|||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
#pragma GCC diagnostic ignored "-Warray-bounds="
|
#pragma GCC diagnostic ignored "-Warray-bounds="
|
||||||
#include "nanovg/stb_image.h"
|
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||||
|
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include <stb_image.h>
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#define STB_IMAGE_WRITE_STATIC
|
#define STB_IMAGE_WRITE_STATIC
|
||||||
#define STBI_WRITE_NO_STDIO
|
#define STBI_WRITE_NO_STDIO
|
||||||
#include "stb_image_write.h"
|
#include <stb_image_write.h>
|
||||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||||
#define STB_IMAGE_RESIZE_STATIC
|
#define STB_IMAGE_RESIZE_STATIC
|
||||||
#include "stb_image_resize2.h"
|
#include <stb_image_resize2.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ auto nro_scan_internal(const fs::FsPath& path, std::vector<NroEntry>& nros, bool
|
|||||||
if (e.type == FsDirEntryType_Dir) {
|
if (e.type == FsDirEntryType_Dir) {
|
||||||
// assert(!root && "dir should only be scanned on non-root!");
|
// assert(!root && "dir should only be scanned on non-root!");
|
||||||
fs::FsPath fullpath;
|
fs::FsPath fullpath;
|
||||||
std::snprintf(fullpath, sizeof(fullpath), "%s/%s/%s.nro", path, e.name, e.name);
|
std::snprintf(fullpath, sizeof(fullpath), "%s/%s/%s.nro", path.s, e.name, e.name);
|
||||||
|
|
||||||
// fast path for detecting an nro in a folder
|
// fast path for detecting an nro in a folder
|
||||||
NroEntry entry;
|
NroEntry entry;
|
||||||
@@ -133,12 +133,12 @@ auto nro_scan_internal(const fs::FsPath& path, std::vector<NroEntry>& nros, bool
|
|||||||
nros.emplace_back(entry);
|
nros.emplace_back(entry);
|
||||||
} else {
|
} else {
|
||||||
// slow path...
|
// slow path...
|
||||||
std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path, e.name);
|
std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path.s, e.name);
|
||||||
nro_scan_internal(fullpath, nros, hide_sphaira, nested, scan_all_dir, false);
|
nro_scan_internal(fullpath, nros, hide_sphaira, nested, scan_all_dir, false);
|
||||||
}
|
}
|
||||||
} else if (e.type == FsDirEntryType_File && std::string_view{e.name}.ends_with(".nro")) {
|
} else if (e.type == FsDirEntryType_File && std::string_view{e.name}.ends_with(".nro")) {
|
||||||
fs::FsPath fullpath;
|
fs::FsPath fullpath;
|
||||||
std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path, e.name);
|
std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path.s, e.name);
|
||||||
|
|
||||||
NroEntry entry;
|
NroEntry entry;
|
||||||
if (R_SUCCEEDED(nro_parse_internal(fs, fullpath, entry))) {
|
if (R_SUCCEEDED(nro_parse_internal(fs, fullpath, entry))) {
|
||||||
@@ -148,7 +148,7 @@ auto nro_scan_internal(const fs::FsPath& path, std::vector<NroEntry>& nros, bool
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_write("error when trying to parse %s\n", fullpath);
|
log_write("error when trying to parse %s\n", fullpath.s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ void loop(void* args) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_write("got name: %s\n", name);
|
log_write("got name: %s\n", name.s);
|
||||||
|
|
||||||
u32 filesize{};
|
u32 filesize{};
|
||||||
if (!recvall(connfd, &filesize, sizeof(filesize))) {
|
if (!recvall(connfd, &filesize, sizeof(filesize))) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <yyjson.h>
|
#include <yyjson.h>
|
||||||
#include <nanovg/stb_image.h>
|
#include <stb_image.h>
|
||||||
#include <minizip/unzip.h>
|
#include <minizip/unzip.h>
|
||||||
#include <mbedtls/md5.h>
|
#include <mbedtls/md5.h>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
@@ -65,60 +65,27 @@ auto BuildIconUrl(const Entry& e) -> std::string {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
auto BuildInfoUrl(const Entry& e) -> std::string {
|
|
||||||
char out[0x100];
|
|
||||||
std::snprintf(out, sizeof(out), "%s/packages/%s/info.json", URL_BASE, e.name.c_str());
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto BuildBannerUrl(const Entry& e) -> std::string {
|
auto BuildBannerUrl(const Entry& e) -> std::string {
|
||||||
char out[0x100];
|
char out[0x100];
|
||||||
std::snprintf(out, sizeof(out), "%s/packages/%s/screen.png", URL_BASE, e.name.c_str());
|
std::snprintf(out, sizeof(out), "%s/packages/%s/screen.png", URL_BASE, e.name.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
auto BuildScreensUrl(const Entry& e, u8 num) -> std::string {
|
|
||||||
char out[0x100];
|
|
||||||
std::snprintf(out, sizeof(out), "%s/packages/%s/screen%u.png", URL_BASE, e.name.c_str(), num+1);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto BuildMainifestUrl(const Entry& e) -> std::string {
|
|
||||||
char out[0x100];
|
|
||||||
std::snprintf(out, sizeof(out), "%s/packages/%s/manifest.install", URL_BASE, e.name.c_str());
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto BuildZipUrl(const Entry& e) -> std::string {
|
auto BuildZipUrl(const Entry& e) -> std::string {
|
||||||
char out[0x100];
|
char out[0x100];
|
||||||
std::snprintf(out, sizeof(out), "%s/zips/%s.zip", URL_BASE, e.name.c_str());
|
std::snprintf(out, sizeof(out), "%s/zips/%s.zip", URL_BASE, e.name.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BuildFeedbackUrl(std::span<u32> ids) -> std::string {
|
|
||||||
std::string out{"https://wiiubru.com/feedback/messages?ids="};
|
|
||||||
for (u32 i = 0; i < ids.size(); i++) {
|
|
||||||
if (i != 0) {
|
|
||||||
out.push_back(',');
|
|
||||||
}
|
|
||||||
out += std::to_string(ids[i]);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto BuildIconCachePath(const Entry& e) -> fs::FsPath {
|
auto BuildIconCachePath(const Entry& e) -> fs::FsPath {
|
||||||
fs::FsPath out;
|
fs::FsPath out;
|
||||||
std::snprintf(out, sizeof(out), "%s/icons/%s.png", CACHE_PATH, e.name.c_str());
|
std::snprintf(out, sizeof(out), "%s/icons/%s.png", CACHE_PATH.s, e.name.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BuildBannerCachePath(const Entry& e) -> fs::FsPath {
|
auto BuildBannerCachePath(const Entry& e) -> fs::FsPath {
|
||||||
fs::FsPath out;
|
fs::FsPath out;
|
||||||
std::snprintf(out, sizeof(out), "%s/banners/%s.png", CACHE_PATH, e.name.c_str());
|
std::snprintf(out, sizeof(out), "%s/banners/%s.png", CACHE_PATH.s, e.name.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +269,6 @@ auto AppDlToStr(u32 value) -> std::string {
|
|||||||
|
|
||||||
void ReadFromInfoJson(Entry& e) {
|
void ReadFromInfoJson(Entry& e) {
|
||||||
const auto info_path = BuildInfoCachePath(e);
|
const auto info_path = BuildInfoCachePath(e);
|
||||||
const auto manifest_path = BuildManifestCachePath(e);
|
|
||||||
|
|
||||||
yyjson_read_err err;
|
yyjson_read_err err;
|
||||||
auto doc = yyjson_read_file(info_path, YYJSON_READ_NOFLAG, nullptr, &err);
|
auto doc = yyjson_read_file(info_path, YYJSON_READ_NOFLAG, nullptr, &err);
|
||||||
@@ -340,9 +306,9 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
const auto safe_buf = fs::AppendPath("/", e.path);
|
const auto safe_buf = fs::AppendPath("/", e.path);
|
||||||
// this will handle read only files, ie, hbmenu.nro
|
// this will handle read only files, ie, hbmenu.nro
|
||||||
if (R_FAILED(fs.DeleteFile(safe_buf))) {
|
if (R_FAILED(fs.DeleteFile(safe_buf))) {
|
||||||
log_write("failed to delete file: %s\n", safe_buf);
|
log_write("failed to delete file: %s\n", safe_buf.s);
|
||||||
} else {
|
} else {
|
||||||
log_write("deleted file: %s\n", safe_buf);
|
log_write("deleted file: %s\n", safe_buf.s);
|
||||||
// todo: delete empty directories!
|
// todo: delete empty directories!
|
||||||
// fs::delete_directory(safe_buf);
|
// fs::delete_directory(safe_buf);
|
||||||
}
|
}
|
||||||
@@ -353,9 +319,9 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
const auto dir = BuildPackageCachePath(entry);
|
const auto dir = BuildPackageCachePath(entry);
|
||||||
pbox->NewTransfer("Removing "_i18n + dir);
|
pbox->NewTransfer("Removing "_i18n + dir);
|
||||||
if (R_FAILED(fs.DeleteDirectoryRecursively(dir))) {
|
if (R_FAILED(fs.DeleteDirectoryRecursively(dir))) {
|
||||||
log_write("failed to delete folder: %s\n", dir);
|
log_write("failed to delete folder: %s\n", dir.s);
|
||||||
} else {
|
} else {
|
||||||
log_write("deleted: %s\n", dir);
|
log_write("deleted: %s\n", dir.s);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -458,7 +424,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
if (!pbox->ShouldExit()) {
|
if (!pbox->ShouldExit()) {
|
||||||
auto zfile = unzOpen64(zip_out);
|
auto zfile = unzOpen64(zip_out);
|
||||||
if (!zfile) {
|
if (!zfile) {
|
||||||
log_write("failed to open zip: %s\n", zip_out);
|
log_write("failed to open zip: %s\n", zip_out.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(unzClose(zfile));
|
ON_SCOPE_EXIT(unzClose(zfile));
|
||||||
@@ -501,7 +467,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
pbox->NewTransfer(inzip);
|
pbox->NewTransfer(inzip);
|
||||||
|
|
||||||
if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) {
|
if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) {
|
||||||
log_write("failed to find %s\n", inzip);
|
log_write("failed to find %s\n", inzip.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,19 +492,19 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
|
|
||||||
Result rc;
|
Result rc;
|
||||||
if (R_FAILED(rc = fs.CreateFile(output, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateFile(output, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create file: %s 0x%04X\n", output, rc);
|
log_write("failed to create file: %s 0x%04X\n", output.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (R_FAILED(rc = fs.OpenFile(output, FsOpenMode_Write, &f))) {
|
if (R_FAILED(rc = fs.OpenFile(output, FsOpenMode_Write, &f))) {
|
||||||
log_write("failed to open file: %s 0x%04X\n", output, rc);
|
log_write("failed to open file: %s 0x%04X\n", output.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(fsFileClose(&f));
|
ON_SCOPE_EXIT(fsFileClose(&f));
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
||||||
log_write("failed to set file size: %s 0x%04X\n", output, rc);
|
log_write("failed to set file size: %s 0x%04X\n", output.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,12 +517,12 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
|
|
||||||
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
log_write("failed to read zip file: %s\n", inzip);
|
log_write("failed to read zip file: %s\n", inzip.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
||||||
log_write("failed to write file: %s 0x%04X\n", output, rc);
|
log_write("failed to write file: %s 0x%04X\n", output.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,9 +581,9 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
|
|||||||
const auto safe_buf = fs::AppendPath("/", old_entry.path);
|
const auto safe_buf = fs::AppendPath("/", old_entry.path);
|
||||||
// std::strcat(safe_buf, old_entry.path);
|
// std::strcat(safe_buf, old_entry.path);
|
||||||
if (R_FAILED(fs.DeleteFile(safe_buf))) {
|
if (R_FAILED(fs.DeleteFile(safe_buf))) {
|
||||||
log_write("failed to delete: %s\n", safe_buf);
|
log_write("failed to delete: %s\n", safe_buf.s);
|
||||||
} else {
|
} else {
|
||||||
log_write("deleted file: %s\n", safe_buf);
|
log_write("deleted file: %s\n", safe_buf.s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -761,13 +727,9 @@ void EntryMenu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "app_dls: %s"_i18n.c_str(), AppDlToStr(m_entry.app_dls).c_str());
|
gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "app_dls: %s"_i18n.c_str(), AppDlToStr(m_entry.app_dls).c_str());
|
||||||
text_start_y += text_inc_y;
|
text_start_y += text_inc_y;
|
||||||
|
|
||||||
// for (const auto& option : m_options) {
|
|
||||||
const auto& text_col = theme->GetColour(ThemeEntryID_TEXT);
|
|
||||||
|
|
||||||
// todo: rewrite this mess and use list
|
// todo: rewrite this mess and use list
|
||||||
constexpr float mm = 0;//20;
|
constexpr float mm = 0;//20;
|
||||||
constexpr Vec4 block{968.f + mm, 110.f, 256.f - mm*2, 60.f};
|
constexpr Vec4 block{968.f + mm, 110.f, 256.f - mm*2, 60.f};
|
||||||
constexpr float text_xoffset{15.f};
|
|
||||||
const float x = block.x;
|
const float x = block.x;
|
||||||
float y = 1.f + text_start_y + (text_inc_y * 3) ;
|
float y = 1.f + text_start_y + (text_inc_y * 3) ;
|
||||||
const float h = block.h;
|
const float h = block.h;
|
||||||
@@ -781,7 +743,7 @@ void EntryMenu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
gfx::drawRectOutline(vg, theme, 4.f, Vec4{x, y, w, h});
|
gfx::drawRectOutline(vg, theme, 4.f, Vec4{x, y, w, h});
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::drawTextArgs(vg, x + w / 2, y + h / 2, 22, NVG_ALIGN_MIDDLE | NVG_ALIGN_CENTER, theme->GetColour(ThemeEntryID_TEXT), option.display_text.c_str());
|
gfx::drawTextArgs(vg, x + w / 2, y + h / 2, 22, NVG_ALIGN_MIDDLE | NVG_ALIGN_CENTER, theme->GetColour(text_id), option.display_text.c_str());
|
||||||
y -= block.h + 18;
|
y -= block.h + 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ auto GetRomDatabaseFromPath(std::string_view path) -> int {
|
|||||||
if ((
|
if ((
|
||||||
p.folder.length() == db_name.length() && !strncasecmp(p.folder.data(), db_name.data(), p.folder.length())) ||
|
p.folder.length() == db_name.length() && !strncasecmp(p.folder.data(), db_name.data(), p.folder.length())) ||
|
||||||
(p.database.length() == db_name.length() && !strncasecmp(p.database.data(), db_name.data(), p.database.length()))) {
|
(p.database.length() == db_name.length() && !strncasecmp(p.database.data(), db_name.data(), p.database.length()))) {
|
||||||
log_write("found it :) %.*s\n", p.database.length(), p.database.data());
|
log_write("found it :) %.*s\n", (int)p.database.length(), p.database.data());
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ auto GetRomDatabaseFromPath(std::string_view path) -> int {
|
|||||||
if ((
|
if ((
|
||||||
p.folder.length() == db_name2.length() && !strcasecmp(p.folder.data(), db_name2.data())) ||
|
p.folder.length() == db_name2.length() && !strcasecmp(p.folder.data(), db_name2.data())) ||
|
||||||
(p.database.length() == db_name2.length() && !strcasecmp(p.database.data(), db_name2.data()))) {
|
(p.database.length() == db_name2.length() && !strcasecmp(p.database.data(), db_name2.data()))) {
|
||||||
log_write("found it :) %.*s\n", p.database.length(), p.database.data());
|
log_write("found it :) %.*s\n", (int)p.database.length(), p.database.data());
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,9 +452,8 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
Scan(m_path);
|
Scan(m_path);
|
||||||
} else {
|
} else {
|
||||||
char msg[FS_MAX_PATH];
|
const auto msg = std::string("Failed to rename file: ") + entry.name;
|
||||||
std::snprintf(msg, sizeof(msg), "Failed to rename file: %s", entry.name);
|
App::Push(std::make_shared<ErrorBox>(rc, msg.c_str()));
|
||||||
App::Push(std::make_shared<ErrorBox>(rc, msg));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -478,10 +477,10 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
|
|
||||||
m_fs->CreateDirectoryRecursivelyWithPath(full_path);
|
m_fs->CreateDirectoryRecursivelyWithPath(full_path);
|
||||||
if (R_SUCCEEDED(m_fs->CreateFile(full_path, 0, 0))) {
|
if (R_SUCCEEDED(m_fs->CreateFile(full_path, 0, 0))) {
|
||||||
log_write("created file: %s\n", full_path);
|
log_write("created file: %s\n", full_path.s);
|
||||||
Scan(m_path);
|
Scan(m_path);
|
||||||
} else {
|
} else {
|
||||||
log_write("failed to create file: %s\n", full_path);
|
log_write("failed to create file: %s\n", full_path.s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -499,10 +498,10 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_SUCCEEDED(m_fs->CreateDirectoryRecursively(full_path))) {
|
if (R_SUCCEEDED(m_fs->CreateDirectoryRecursively(full_path))) {
|
||||||
log_write("created dir: %s\n", full_path);
|
log_write("created dir: %s\n", full_path.s);
|
||||||
Scan(m_path);
|
Scan(m_path);
|
||||||
} else {
|
} else {
|
||||||
log_write("failed to create dir: %s\n", full_path);
|
log_write("failed to create dir: %s\n", full_path.s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -777,7 +776,7 @@ void Menu::InstallForwarder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result {
|
auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result {
|
||||||
log_write("new scan path: %s\n", new_path);
|
log_write("new scan path: %s\n", new_path.s);
|
||||||
if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) {
|
if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) {
|
||||||
const LastFile f(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size());
|
const LastFile f(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size());
|
||||||
m_previous_highlighted_file.emplace_back(f);
|
m_previous_highlighted_file.emplace_back(f);
|
||||||
@@ -868,7 +867,7 @@ auto Menu::FindFileAssocFor() -> std::vector<FileAssocEntry> {
|
|||||||
if (assoc_db == PATHS[db_idx].folder || assoc_db == PATHS[db_idx].database) {
|
if (assoc_db == PATHS[db_idx].folder || assoc_db == PATHS[db_idx].database) {
|
||||||
for (const auto& assoc_ext : assoc.ext) {
|
for (const auto& assoc_ext : assoc.ext) {
|
||||||
if (assoc_ext == extension) {
|
if (assoc_ext == extension) {
|
||||||
log_write("found ext: %s assoc_ext: %s assoc.ext: %s\n", assoc.path, assoc_ext.c_str(), extension.c_str());
|
log_write("found ext: %s assoc_ext: %s assoc.ext: %s\n", assoc.path.s, assoc_ext.c_str(), extension.c_str());
|
||||||
out_entries.emplace_back(assoc);
|
out_entries.emplace_back(assoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -886,7 +885,7 @@ auto Menu::FindFileAssocFor() -> std::vector<FileAssocEntry> {
|
|||||||
if (assoc.database.empty()) {
|
if (assoc.database.empty()) {
|
||||||
for (const auto& assoc_ext : assoc.ext) {
|
for (const auto& assoc_ext : assoc.ext) {
|
||||||
if (assoc_ext == extension) {
|
if (assoc_ext == extension) {
|
||||||
log_write("found ext: %s\n", assoc.path);
|
log_write("found ext: %s\n", assoc.path.s);
|
||||||
out_entries.emplace_back(assoc);
|
out_entries.emplace_back(assoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1099,7 +1098,6 @@ void Menu::SetIndexFromLastFile(const LastFile& last_file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetIndex(index);
|
SetIndex(index);
|
||||||
log_write("\nnew index: %zu %zu mod: %zu\n", m_index, index % 8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1148,7 +1146,7 @@ void Menu::OnDeleteCallback() {
|
|||||||
if (p.IsDir()) {
|
if (p.IsDir()) {
|
||||||
pbox->NewTransfer("Scanning "_i18n + full_path);
|
pbox->NewTransfer("Scanning "_i18n + full_path);
|
||||||
if (R_FAILED(get_collections(full_path, p.name, collections))) {
|
if (R_FAILED(get_collections(full_path, p.name, collections))) {
|
||||||
log_write("failed to get dir collection: %s\n", full_path);
|
log_write("failed to get dir collection: %s\n", full_path.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1166,10 +1164,10 @@ void Menu::OnDeleteCallback() {
|
|||||||
const auto full_path = GetNewPath(c.path, p.name);
|
const auto full_path = GetNewPath(c.path, p.name);
|
||||||
pbox->NewTransfer("Deleting "_i18n + full_path);
|
pbox->NewTransfer("Deleting "_i18n + full_path);
|
||||||
if (p.type == FsDirEntryType_Dir) {
|
if (p.type == FsDirEntryType_Dir) {
|
||||||
log_write("deleting dir: %s\n", full_path);
|
log_write("deleting dir: %s\n", full_path.s);
|
||||||
m_fs->DeleteDirectory(full_path);
|
m_fs->DeleteDirectory(full_path);
|
||||||
} else {
|
} else {
|
||||||
log_write("deleting file: %s\n", full_path);
|
log_write("deleting file: %s\n", full_path.s);
|
||||||
m_fs->DeleteFile(full_path);
|
m_fs->DeleteFile(full_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1194,10 +1192,10 @@ void Menu::OnDeleteCallback() {
|
|||||||
pbox->NewTransfer("Deleting "_i18n + full_path);
|
pbox->NewTransfer("Deleting "_i18n + full_path);
|
||||||
|
|
||||||
if (p.IsDir()) {
|
if (p.IsDir()) {
|
||||||
log_write("deleting dir: %s\n", full_path);
|
log_write("deleting dir: %s\n", full_path.s);
|
||||||
m_fs->DeleteDirectory(full_path);
|
m_fs->DeleteDirectory(full_path);
|
||||||
} else {
|
} else {
|
||||||
log_write("deleting file: %s\n", full_path);
|
log_write("deleting file: %s\n", full_path.s);
|
||||||
m_fs->DeleteFile(full_path);
|
m_fs->DeleteFile(full_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1212,8 +1210,6 @@ void Menu::OnDeleteCallback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Menu::OnPasteCallback() {
|
void Menu::OnPasteCallback() {
|
||||||
bool use_progress_box{true};
|
|
||||||
|
|
||||||
// check if we only have 1 file / folder and is cut (rename)
|
// check if we only have 1 file / folder and is cut (rename)
|
||||||
if (m_selected_files.size() == 1 && m_selected_type == SelectedType::Cut) {
|
if (m_selected_files.size() == 1 && m_selected_type == SelectedType::Cut) {
|
||||||
const auto& entry = m_selected_files[0];
|
const auto& entry = m_selected_files[0];
|
||||||
@@ -1263,7 +1259,7 @@ void Menu::OnPasteCallback() {
|
|||||||
if (p.IsDir()) {
|
if (p.IsDir()) {
|
||||||
pbox->NewTransfer("Scanning "_i18n + full_path);
|
pbox->NewTransfer("Scanning "_i18n + full_path);
|
||||||
if (R_FAILED(get_collections(full_path, p.name, collections))) {
|
if (R_FAILED(get_collections(full_path, p.name, collections))) {
|
||||||
log_write("failed to get dir collection: %s\n", full_path);
|
log_write("failed to get dir collection: %s\n", full_path.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1300,7 +1296,7 @@ void Menu::OnPasteCallback() {
|
|||||||
const auto src_path = GetNewPath(c.path, p.name);
|
const auto src_path = GetNewPath(c.path, p.name);
|
||||||
const auto dst_path = GetNewPath(base_dst_path, p.name);
|
const auto dst_path = GetNewPath(base_dst_path, p.name);
|
||||||
|
|
||||||
log_write("creating: %s to %s\n", src_path, dst_path);
|
log_write("creating: %s to %s\n", src_path.s, dst_path.s);
|
||||||
pbox->NewTransfer("Creating "_i18n + dst_path);
|
pbox->NewTransfer("Creating "_i18n + dst_path);
|
||||||
m_fs->CreateDirectory(dst_path);
|
m_fs->CreateDirectory(dst_path);
|
||||||
}
|
}
|
||||||
@@ -1315,7 +1311,7 @@ void Menu::OnPasteCallback() {
|
|||||||
const auto dst_path = GetNewPath(base_dst_path, p.name);
|
const auto dst_path = GetNewPath(base_dst_path, p.name);
|
||||||
|
|
||||||
pbox->NewTransfer("Copying "_i18n + src_path);
|
pbox->NewTransfer("Copying "_i18n + src_path);
|
||||||
log_write("copying: %s to %s\n", src_path, dst_path);
|
log_write("copying: %s to %s\n", src_path.s, dst_path.s);
|
||||||
R_TRY_RESULT(pbox->CopyFile(src_path, dst_path), false);
|
R_TRY_RESULT(pbox->CopyFile(src_path, dst_path), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1415,7 +1411,7 @@ auto Menu::get_collections(const fs::FsPath& path, const fs::FsPath& parent_name
|
|||||||
// get a list of all the files / dirs
|
// get a list of all the files / dirs
|
||||||
FsDirCollection collection;
|
FsDirCollection collection;
|
||||||
R_TRY(get_collection(path, parent_name, collection, true, true, false));
|
R_TRY(get_collection(path, parent_name, collection, true, true, false));
|
||||||
log_write("got collection: %s parent_name: %s files: %zu dirs: %zu\n", path, parent_name, collection.files.size(), collection.dirs.size());
|
log_write("got collection: %s parent_name: %s files: %zu dirs: %zu\n", path.s, parent_name.s, collection.files.size(), collection.dirs.size());
|
||||||
out.emplace_back(collection);
|
out.emplace_back(collection);
|
||||||
|
|
||||||
// for (size_t i = 0; i < collection.dirs.size(); i++) {
|
// for (size_t i = 0; i < collection.dirs.size(); i++) {
|
||||||
@@ -1423,7 +1419,7 @@ auto Menu::get_collections(const fs::FsPath& path, const fs::FsPath& parent_name
|
|||||||
// use heap as to not explode the stack
|
// use heap as to not explode the stack
|
||||||
const auto new_path = std::make_unique<fs::FsPath>(Menu::GetNewPath(path, p.name));
|
const auto new_path = std::make_unique<fs::FsPath>(Menu::GetNewPath(path, p.name));
|
||||||
const auto new_parent_name = std::make_unique<fs::FsPath>(Menu::GetNewPath(parent_name, p.name));
|
const auto new_parent_name = std::make_unique<fs::FsPath>(Menu::GetNewPath(parent_name, p.name));
|
||||||
log_write("trying to get nested collection: %s parent_name: %s\n", *new_path, *new_parent_name);
|
log_write("trying to get nested collection: %s parent_name: %s\n", new_path->s, new_parent_name->s);
|
||||||
R_TRY(get_collections(*new_path, *new_parent_name, out));
|
R_TRY(get_collections(*new_path, *new_parent_name, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry
|
|||||||
log_write("found zip\n");
|
log_write("found zip\n");
|
||||||
auto zfile = unzOpen64(temp_file);
|
auto zfile = unzOpen64(temp_file);
|
||||||
if (!zfile) {
|
if (!zfile) {
|
||||||
log_write("failed to open zip: %s\n", temp_file);
|
log_write("failed to open zip: %s\n", temp_file.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(unzClose(zfile));
|
ON_SCOPE_EXIT(unzClose(zfile));
|
||||||
@@ -155,29 +155,29 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry
|
|||||||
Result rc;
|
Result rc;
|
||||||
if (file_path[strlen(file_path) -1] == '/') {
|
if (file_path[strlen(file_path) -1] == '/') {
|
||||||
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create folder: %s 0x%04X\n", file_path, rc);
|
log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (R_FAILED(rc = fs.CreateDirectoryRecursivelyWithPath(file_path)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateDirectoryRecursivelyWithPath(file_path)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create folder: %s 0x%04X\n", file_path, rc);
|
log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to create file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
||||||
log_write("failed to open file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to open file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(fsFileClose(&f));
|
ON_SCOPE_EXIT(fsFileClose(&f));
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
||||||
log_write("failed to set file size: %s 0x%04X\n", file_path, rc);
|
log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace {
|
|||||||
auto GenerateStarPath(const fs::FsPath& nro_path) -> fs::FsPath {
|
auto GenerateStarPath(const fs::FsPath& nro_path) -> fs::FsPath {
|
||||||
fs::FsPath out{};
|
fs::FsPath out{};
|
||||||
const auto dilem = std::strrchr(nro_path.s, '/');
|
const auto dilem = std::strrchr(nro_path.s, '/');
|
||||||
std::snprintf(out, sizeof(out), "%.*s.%s.star", dilem - nro_path.s + 1, nro_path.s, dilem + 1);
|
std::snprintf(out, sizeof(out), "%.*s.%s.star", int(dilem - nro_path.s + 1), nro_path.s, dilem + 1);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,8 +237,6 @@ void Menu::SetIndex(s64 index) {
|
|||||||
m_list->SetYoff(0);
|
m_list->SetYoff(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& e = m_entries[m_index];
|
|
||||||
|
|
||||||
if (IsStarEnabled()) {
|
if (IsStarEnabled()) {
|
||||||
const auto star_path = GenerateStarPath(m_entries[m_index].path);
|
const auto star_path = GenerateStarPath(m_entries[m_index].path);
|
||||||
if (fs::FsNativeSd().FileExists(star_path)) {
|
if (fs::FsNativeSd().FileExists(star_path)) {
|
||||||
@@ -279,8 +277,8 @@ void Menu::ScanHomebrew() {
|
|||||||
|
|
||||||
struct IniUser {
|
struct IniUser {
|
||||||
std::vector<NroEntry>& entires;
|
std::vector<NroEntry>& entires;
|
||||||
Hbini* ini;
|
Hbini* ini{};
|
||||||
std::string last_section;
|
std::string last_section{};
|
||||||
} ini_user{ m_entries };
|
} ini_user{ m_entries };
|
||||||
|
|
||||||
ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int {
|
ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int {
|
||||||
@@ -331,9 +329,9 @@ void Menu::Sort() {
|
|||||||
const auto name_cmp = [order](const NroEntry& lhs, const NroEntry& rhs) -> bool {
|
const auto name_cmp = [order](const NroEntry& lhs, const NroEntry& rhs) -> bool {
|
||||||
auto r = strcasecmp(lhs.GetName(), rhs.GetName());
|
auto r = strcasecmp(lhs.GetName(), rhs.GetName());
|
||||||
if (!r) {
|
if (!r) {
|
||||||
auto r = strcasecmp(lhs.GetAuthor(), rhs.GetAuthor());
|
r = strcasecmp(lhs.GetAuthor(), rhs.GetAuthor());
|
||||||
if (!r) {
|
if (!r) {
|
||||||
auto r = strcasecmp(lhs.path, rhs.path);
|
r = strcasecmp(lhs.path, rhs.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,6 +349,7 @@ void Menu::Sort() {
|
|||||||
} else if (!lhs.has_star.value() && rhs.has_star.value()) {
|
} else if (!lhs.has_star.value() && rhs.has_star.value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
[[fallthrough]];
|
||||||
case SortType_Updated: {
|
case SortType_Updated: {
|
||||||
auto lhs_timestamp = lhs.hbini.timestamp;
|
auto lhs_timestamp = lhs.hbini.timestamp;
|
||||||
auto rhs_timestamp = rhs.hbini.timestamp;
|
auto rhs_timestamp = rhs.hbini.timestamp;
|
||||||
@@ -376,6 +375,7 @@ void Menu::Sort() {
|
|||||||
} else if (!lhs.has_star.value() && rhs.has_star.value()) {
|
} else if (!lhs.has_star.value() && rhs.has_star.value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
[[fallthrough]];
|
||||||
case SortType_Size: {
|
case SortType_Size: {
|
||||||
if (lhs.size == rhs.size) {
|
if (lhs.size == rhs.size) {
|
||||||
return name_cmp(lhs, rhs);
|
return name_cmp(lhs, rhs);
|
||||||
@@ -392,6 +392,7 @@ void Menu::Sort() {
|
|||||||
} else if (!lhs.has_star.value() && rhs.has_star.value()) {
|
} else if (!lhs.has_star.value() && rhs.has_star.value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
[[fallthrough]];
|
||||||
case SortType_Alphabetical: {
|
case SortType_Alphabetical: {
|
||||||
return name_cmp(lhs, rhs);
|
return name_cmp(lhs, rhs);
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -258,8 +258,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
const auto scale = std::min(scale_x, scale_y);
|
const auto scale = std::min(scale_x, scale_y);
|
||||||
w = m_irs_width * scale;
|
w = m_irs_width * scale;
|
||||||
h = m_irs_height * scale;
|
h = m_irs_height * scale;
|
||||||
cx = (m_pos.x + m_pos.w / 2.0) - w / 2.0;
|
cx = (m_pos.x + m_pos.w / 2.F) - w / 2.F;
|
||||||
cy = (m_pos.y + m_pos.h / 2.0) - h / 2.0;
|
cy = (m_pos.y + m_pos.h / 2.F) - h / 2.F;
|
||||||
angle = 0;
|
angle = 0;
|
||||||
} break;
|
} break;
|
||||||
case Rotation_90: {
|
case Rotation_90: {
|
||||||
@@ -268,8 +268,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
const auto scale = std::min(scale_x, scale_y);
|
const auto scale = std::min(scale_x, scale_y);
|
||||||
w = m_irs_width * scale;
|
w = m_irs_width * scale;
|
||||||
h = m_irs_height * scale;
|
h = m_irs_height * scale;
|
||||||
cx = (m_pos.x + m_pos.w / 2.0) + h / 2.0;
|
cx = (m_pos.x + m_pos.w / 2.F) + h / 2.F;
|
||||||
cy = (m_pos.y + m_pos.h / 2.0) - w / 2.0;
|
cy = (m_pos.y + m_pos.h / 2.F) - w / 2.F;
|
||||||
angle = 90;
|
angle = 90;
|
||||||
} break;
|
} break;
|
||||||
case Rotation_180: {
|
case Rotation_180: {
|
||||||
@@ -278,8 +278,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
const auto scale = std::min(scale_x, scale_y);
|
const auto scale = std::min(scale_x, scale_y);
|
||||||
w = m_irs_width * scale;
|
w = m_irs_width * scale;
|
||||||
h = m_irs_height * scale;
|
h = m_irs_height * scale;
|
||||||
cx = (m_pos.x + m_pos.w / 2.0) + w / 2.0;
|
cx = (m_pos.x + m_pos.w / 2.F) + w / 2.F;
|
||||||
cy = (m_pos.y + m_pos.h / 2.0) + h / 2.0;
|
cy = (m_pos.y + m_pos.h / 2.F) + h / 2.F;
|
||||||
angle = 180;
|
angle = 180;
|
||||||
} break;
|
} break;
|
||||||
case Rotation_270: {
|
case Rotation_270: {
|
||||||
@@ -288,8 +288,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
const auto scale = std::min(scale_x, scale_y);
|
const auto scale = std::min(scale_x, scale_y);
|
||||||
w = m_irs_width * scale;
|
w = m_irs_width * scale;
|
||||||
h = m_irs_height * scale;
|
h = m_irs_height * scale;
|
||||||
cx = (m_pos.x + m_pos.w / 2.0) - h / 2.0;
|
cx = (m_pos.x + m_pos.w / 2.F) - h / 2.F;
|
||||||
cy = (m_pos.y + m_pos.h / 2.0) + w / 2.0;
|
cy = (m_pos.y + m_pos.h / 2.F) + w / 2.F;
|
||||||
angle = 270;
|
angle = 270;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -382,7 +382,7 @@ void Menu::LoadDefaultConfig() {
|
|||||||
irsGetClusteringProcessorDefaultConfig(&m_clustering_config);
|
irsGetClusteringProcessorDefaultConfig(&m_clustering_config);
|
||||||
irsGetIrLedProcessorDefaultConfig(&m_led_config);
|
irsGetIrLedProcessorDefaultConfig(&m_led_config);
|
||||||
|
|
||||||
m_tera_config;
|
m_tera_config = {};
|
||||||
m_adaptive_config = {};
|
m_adaptive_config = {};
|
||||||
m_hand_config = {};
|
m_hand_config = {};
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
|
|||||||
if (!pbox->ShouldExit()) {
|
if (!pbox->ShouldExit()) {
|
||||||
auto zfile = unzOpen64(zip_out);
|
auto zfile = unzOpen64(zip_out);
|
||||||
if (!zfile) {
|
if (!zfile) {
|
||||||
log_write("failed to open zip: %s\n", zip_out);
|
log_write("failed to open zip: %s\n", zip_out.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(unzClose(zfile));
|
ON_SCOPE_EXIT(unzClose(zfile));
|
||||||
@@ -96,25 +96,25 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
|
|||||||
Result rc;
|
Result rc;
|
||||||
if (file_path[strlen(file_path) -1] == '/') {
|
if (file_path[strlen(file_path) -1] == '/') {
|
||||||
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create folder: %s 0x%04X\n", file_path, rc);
|
log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Result rc;
|
Result rc;
|
||||||
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to create file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
||||||
log_write("failed to open file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to open file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(fsFileClose(&f));
|
ON_SCOPE_EXIT(fsFileClose(&f));
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
||||||
log_write("failed to set file size: %s 0x%04X\n", file_path, rc);
|
log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
||||||
log_write("failed to write file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to write file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "i18n.hpp"
|
#include "i18n.hpp"
|
||||||
|
|
||||||
#include <minIni.h>
|
#include <minIni.h>
|
||||||
#include <nanovg/stb_image.h>
|
#include <stb_image.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <minizip/unzip.h>
|
#include <minizip/unzip.h>
|
||||||
#include <yyjson.h>
|
#include <yyjson.h>
|
||||||
@@ -102,32 +102,10 @@ auto apiBuildUrlDownloadInternal(const std::string& id, bool is_pack) -> std::st
|
|||||||
// https://api.themezer.net/?query=query{downloadPack(id:"11"){filename,url,mimetype}}
|
// https://api.themezer.net/?query=query{downloadPack(id:"11"){filename,url,mimetype}}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto apiBuildUrlDownloadTheme(const ThemeEntry& e) -> std::string {
|
|
||||||
return apiBuildUrlDownloadInternal(e.id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto apiBuildUrlDownloadPack(const PackListEntry& e) -> std::string {
|
auto apiBuildUrlDownloadPack(const PackListEntry& e) -> std::string {
|
||||||
return apiBuildUrlDownloadInternal(e.id, true);
|
return apiBuildUrlDownloadInternal(e.id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto apiBuildFilePack(const PackListEntry& e) -> fs::FsPath {
|
|
||||||
fs::FsPath path;
|
|
||||||
std::snprintf(path, sizeof(path), "%s/%s By %s/", THEME_FOLDER, e.details.name.c_str(), e.creator.display_name.c_str());
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
auto apiBuildUrlPack(const PackListEntry& e) -> std::string {
|
|
||||||
char url[2048];
|
|
||||||
std::snprintf(url, sizeof(url), "https://api.themezer.net/?query=query($id:String!){pack(id:$id){id,creator{display_name},details{name,description},last_updated,categories,dl_count,like_count,themes{id,details{name},layout{id,details{name}},categories,target,preview{original,thumb},last_updated,dl_count,like_count}}}&variables={\"id\":\"%s\"}", e.id.c_str());
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto apiBuildUrlThemeList(const Config& e) -> std::string {
|
|
||||||
return apiBuildUrlListInternal(e, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto apiBuildUrlListPacks(const Config& e) -> std::string {
|
auto apiBuildUrlListPacks(const Config& e) -> std::string {
|
||||||
return apiBuildUrlListInternal(e, true);
|
return apiBuildUrlListInternal(e, true);
|
||||||
}
|
}
|
||||||
@@ -171,7 +149,6 @@ auto loadThemeImage(ThemeEntry& e) -> bool {
|
|||||||
|
|
||||||
if (!image.image) {
|
if (!image.image) {
|
||||||
log_write("failed to load image from file: %s\n", path.s);
|
log_write("failed to load image from file: %s\n", path.s);
|
||||||
log_write("failed to load image from file: %s\n", path);
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// log_write("loaded image from file: %s\n", path);
|
// log_write("loaded image from file: %s\n", path);
|
||||||
@@ -189,35 +166,18 @@ void from_json(yyjson_val* json, Creator& e) {
|
|||||||
void from_json(yyjson_val* json, Details& e) {
|
void from_json(yyjson_val* json, Details& e) {
|
||||||
JSON_OBJ_ITR(
|
JSON_OBJ_ITR(
|
||||||
JSON_SET_STR(name);
|
JSON_SET_STR(name);
|
||||||
// JSON_SET_STR(description);
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_json(yyjson_val* json, Preview& e) {
|
void from_json(yyjson_val* json, Preview& e) {
|
||||||
JSON_OBJ_ITR(
|
JSON_OBJ_ITR(
|
||||||
// JSON_SET_STR(original);
|
|
||||||
JSON_SET_STR(thumb);
|
JSON_SET_STR(thumb);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_json(yyjson_val* json, DownloadPack& e) {
|
|
||||||
JSON_OBJ_ITR(
|
|
||||||
JSON_SET_STR(filename);
|
|
||||||
JSON_SET_STR(url);
|
|
||||||
JSON_SET_STR(mimetype);
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void from_json(yyjson_val* json, ThemeEntry& e) {
|
void from_json(yyjson_val* json, ThemeEntry& e) {
|
||||||
JSON_OBJ_ITR(
|
JSON_OBJ_ITR(
|
||||||
JSON_SET_STR(id);
|
JSON_SET_STR(id);
|
||||||
// JSON_SET_OBJ(creator);
|
|
||||||
// JSON_SET_OBJ(details);
|
|
||||||
// JSON_SET_STR(last_updated);
|
|
||||||
// JSON_SET_UINT(dl_count);
|
|
||||||
// JSON_SET_UINT(like_count);
|
|
||||||
// JSON_SET_ARR_STR(categories);
|
|
||||||
// JSON_SET_STR(target);
|
|
||||||
JSON_SET_OBJ(preview);
|
JSON_SET_OBJ(preview);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -227,10 +187,6 @@ void from_json(yyjson_val* json, PackListEntry& e) {
|
|||||||
JSON_SET_STR(id);
|
JSON_SET_STR(id);
|
||||||
JSON_SET_OBJ(creator);
|
JSON_SET_OBJ(creator);
|
||||||
JSON_SET_OBJ(details);
|
JSON_SET_OBJ(details);
|
||||||
// JSON_SET_STR(last_updated);
|
|
||||||
// JSON_SET_ARR_STR(categories);
|
|
||||||
// JSON_SET_UINT(dl_count);
|
|
||||||
// JSON_SET_UINT(like_count);
|
|
||||||
JSON_SET_ARR_OBJ(themes);
|
JSON_SET_ARR_OBJ(themes);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -246,7 +202,6 @@ void from_json(yyjson_val* json, Pagination& e) {
|
|||||||
|
|
||||||
void from_json(const std::vector<u8>& data, DownloadPack& e) {
|
void from_json(const std::vector<u8>& data, DownloadPack& e) {
|
||||||
JSON_INIT_VEC(data, "data");
|
JSON_INIT_VEC(data, "data");
|
||||||
// JSON_GET_OBJ("downloadTheme");
|
|
||||||
JSON_GET_OBJ("downloadPack");
|
JSON_GET_OBJ("downloadPack");
|
||||||
JSON_OBJ_ITR(
|
JSON_OBJ_ITR(
|
||||||
JSON_SET_STR(filename);
|
JSON_SET_STR(filename);
|
||||||
@@ -310,14 +265,14 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
|
|||||||
|
|
||||||
// create directories
|
// create directories
|
||||||
fs::FsPath dir_path;
|
fs::FsPath dir_path;
|
||||||
std::snprintf(dir_path, sizeof(dir_path), "%s/%s - By %s", THEME_FOLDER, entry.details.name.c_str(), entry.creator.display_name.c_str());
|
std::snprintf(dir_path, sizeof(dir_path), "%s/%s - By %s", THEME_FOLDER.s, entry.details.name.c_str(), entry.creator.display_name.c_str());
|
||||||
fs.CreateDirectoryRecursively(dir_path);
|
fs.CreateDirectoryRecursively(dir_path);
|
||||||
|
|
||||||
// 3. extract the zip
|
// 3. extract the zip
|
||||||
if (!pbox->ShouldExit()) {
|
if (!pbox->ShouldExit()) {
|
||||||
auto zfile = unzOpen64(zip_out);
|
auto zfile = unzOpen64(zip_out);
|
||||||
if (!zfile) {
|
if (!zfile) {
|
||||||
log_write("failed to open zip: %s\n", zip_out);
|
log_write("failed to open zip: %s\n", zip_out.s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(unzClose(zfile));
|
ON_SCOPE_EXIT(unzClose(zfile));
|
||||||
@@ -352,19 +307,19 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
|
|||||||
|
|
||||||
Result rc;
|
Result rc;
|
||||||
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
|
||||||
log_write("failed to create file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to create file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
||||||
log_write("failed to open file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to open file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT(fsFileClose(&f));
|
ON_SCOPE_EXIT(fsFileClose(&f));
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
||||||
log_write("failed to set file size: %s 0x%04X\n", file_path, rc);
|
log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +337,7 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
||||||
log_write("failed to write file: %s 0x%04X\n", file_path, rc);
|
log_write("failed to write file: %s 0x%04X\n", file_path.s, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +573,6 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const float xoff = (350 - 320) / 2;
|
const float xoff = (350 - 320) / 2;
|
||||||
const float yoff = (350 - 320) / 2;
|
|
||||||
|
|
||||||
// lazy load image
|
// lazy load image
|
||||||
if (e.themes.size()) {
|
if (e.themes.size()) {
|
||||||
@@ -638,7 +592,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
switch (image.state) {
|
switch (image.state) {
|
||||||
case ImageDownloadState::None: {
|
case ImageDownloadState::None: {
|
||||||
const auto path = apiBuildIconCache(theme);
|
const auto path = apiBuildIconCache(theme);
|
||||||
log_write("downloading theme!: %s\n", path);
|
log_write("downloading theme!: %s\n", path.s);
|
||||||
|
|
||||||
const auto url = theme.preview.thumb;
|
const auto url = theme.preview.thumb;
|
||||||
log_write("downloading url: %s\n", url.c_str());
|
log_write("downloading url: %s\n", url.c_str());
|
||||||
@@ -759,8 +713,8 @@ void Menu::PackListDownload() {
|
|||||||
std::snprintf(subheading, sizeof(subheading), "Page %zu / %zu"_i18n.c_str(), m_page_index+1, m_page_index_max);
|
std::snprintf(subheading, sizeof(subheading), "Page %zu / %zu"_i18n.c_str(), m_page_index+1, m_page_index_max);
|
||||||
SetSubHeading(subheading);
|
SetSubHeading(subheading);
|
||||||
|
|
||||||
log_write("a.pagination.page: %u\n", a.pagination.page);
|
log_write("a.pagination.page: %zu\n", a.pagination.page);
|
||||||
log_write("a.pagination.page_count: %u\n", a.pagination.page_count);
|
log_write("a.pagination.page_count: %zu\n", a.pagination.page_count);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
namespace sphaira::ui::gfx {
|
namespace sphaira::ui::gfx {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static constexpr std::array buttons = {
|
constexpr std::array buttons = {
|
||||||
std::pair{Button::A, "\uE0E0"},
|
std::pair{Button::A, "\uE0E0"},
|
||||||
std::pair{Button::B, "\uE0E1"},
|
std::pair{Button::B, "\uE0E1"},
|
||||||
std::pair{Button::X, "\uE0E2"},
|
std::pair{Button::X, "\uE0E2"},
|
||||||
@@ -60,18 +60,18 @@ void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, con
|
|||||||
float gradientX, gradientY, color;
|
float gradientX, gradientY, color;
|
||||||
getHighlightAnimation(&gradientX, &gradientY, &color);
|
getHighlightAnimation(&gradientX, &gradientY, &color);
|
||||||
|
|
||||||
const auto strokeWidth = 5.0;
|
const auto strokeWidth = 5.F;
|
||||||
auto v2 = v;
|
auto v2 = v;
|
||||||
v2.x -= strokeWidth / 2.0;
|
v2.x -= strokeWidth / 2.F;
|
||||||
v2.y -= strokeWidth / 2.0;
|
v2.y -= strokeWidth / 2.F;
|
||||||
v2.w += strokeWidth;
|
v2.w += strokeWidth;
|
||||||
v2.h += strokeWidth;
|
v2.h += strokeWidth;
|
||||||
const auto corner_radius = 0.5;
|
const auto corner_radius = 0.5F;
|
||||||
|
|
||||||
const auto shadow_width = 2.0f;
|
const auto shadow_width = 2.F;
|
||||||
const auto shadow_offset = 10.0f;
|
const auto shadow_offset = 10.F;
|
||||||
const auto shadow_feather = 10.0f;
|
const auto shadow_feather = 10.F;
|
||||||
const auto shadow_opacity = 128.0f;
|
const auto shadow_opacity = 128.F;
|
||||||
|
|
||||||
// Shadow
|
// Shadow
|
||||||
NVGpaint shadowPaint = nvgBoxGradient(vg,
|
NVGpaint shadowPaint = nvgBoxGradient(vg,
|
||||||
@@ -136,15 +136,6 @@ void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, con
|
|||||||
nvgFill(vg);
|
nvgFill(vg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, const Vec4& v, const NVGpaint& p) {
|
|
||||||
const auto corner_radius = 0.5;
|
|
||||||
drawRectOutlineInternal(vg, theme, size, v);
|
|
||||||
nvgBeginPath(vg);
|
|
||||||
nvgRoundedRect(vg, v.x, v.y, v.w, v.h, corner_radius);
|
|
||||||
nvgFillPaint(vg, p);
|
|
||||||
nvgFill(vg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawTextIntenal(NVGcontext* vg, const Vec2& v, float size, const char* str, const char* end, int align, const NVGcolor& c) {
|
void drawTextIntenal(NVGcontext* vg, const Vec2& v, float size, const char* str, const char* end, int align, const NVGcolor& c) {
|
||||||
nvgBeginPath(vg);
|
nvgBeginPath(vg);
|
||||||
nvgFontSize(vg, size);
|
nvgFontSize(vg, size);
|
||||||
@@ -173,20 +164,6 @@ void drawTextArgs(NVGcontext* vg, float x, float y, float size, int align, const
|
|||||||
drawText(vg, x, y, size, buffer, nullptr, align, c);
|
drawText(vg, x, y, size, buffer, nullptr, align, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawImageInternal(NVGcontext* vg, const Vec4& v, int texture, int rounded = 0) {
|
|
||||||
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f);
|
|
||||||
// drawRect(vg, x, y, w, h, paint);
|
|
||||||
nvgBeginPath(vg);
|
|
||||||
// nvgRect(vg, x, y, w, h);
|
|
||||||
if (rounded == 0) {
|
|
||||||
nvgRect(vg, v.x, v.y, v.w, v.h);
|
|
||||||
} else {
|
|
||||||
nvgRoundedRect(vg, v.x, v.y, v.w, v.h, rounded);
|
|
||||||
}
|
|
||||||
nvgFillPaint(vg, paint);
|
|
||||||
nvgFill(vg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawImage(NVGcontext* vg, const Vec4& v, int texture) {
|
void drawImage(NVGcontext* vg, const Vec4& v, int texture) {
|
||||||
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f);
|
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f);
|
||||||
drawRect(vg, v, paint, false);
|
drawRect(vg, v, paint, false);
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ ProgressBox::ProgressBox(const std::string& title, ProgressBoxCallback callback,
|
|||||||
m_pos.h = 430.f;
|
m_pos.h = 430.f;
|
||||||
m_pos.x = 255;
|
m_pos.x = 255;
|
||||||
m_pos.y = 145;
|
m_pos.y = 145;
|
||||||
145 + 430; // 575, 200, 420
|
|
||||||
|
|
||||||
m_pos.w = 770.f;
|
m_pos.w = 770.f;
|
||||||
m_pos.h = 295.f;
|
m_pos.h = 295.f;
|
||||||
@@ -99,7 +98,7 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void {
|
|||||||
|
|
||||||
gfx::drawTextArgs(vg, center_x, m_pos.y + 60, 25, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), title.c_str());
|
gfx::drawTextArgs(vg, center_x, m_pos.y + 60, 25, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), title.c_str());
|
||||||
if (!transfer.empty()) {
|
if (!transfer.empty()) {
|
||||||
gfx::drawTextArgs(vg, center_x, prog_bar.y - 15 - 20 * 1.5, 20, NVG_ALIGN_CENTER, theme->GetColour(ThemeEntryID_TEXT), "%s", transfer.c_str());
|
gfx::drawTextArgs(vg, center_x, prog_bar.y - 15 - 20 * 1.5F, 20, NVG_ALIGN_CENTER, theme->GetColour(ThemeEntryID_TEXT), "%s", transfer.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ namespace sphaira::ui {
|
|||||||
ScrollableText::ScrollableText(const std::string& text, float x, float y, float y_clip, float w, float font_size)
|
ScrollableText::ScrollableText(const std::string& text, float x, float y, float y_clip, float w, float font_size)
|
||||||
: m_font_size{font_size}
|
: m_font_size{font_size}
|
||||||
, m_y_off_base{y}
|
, m_y_off_base{y}
|
||||||
, m_y_off{y}
|
|
||||||
, m_clip_y{y_clip}
|
, m_clip_y{y_clip}
|
||||||
, m_end_w{w}
|
, m_end_w{w}
|
||||||
|
, m_y_off{y}
|
||||||
{
|
{
|
||||||
SetActions(
|
SetActions(
|
||||||
std::make_pair(Button::LS_DOWN, Action{[this](){
|
std::make_pair(Button::LS_DOWN, Action{[this](){
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ auto Sidebar::Draw(NVGcontext* vg, Theme* theme) -> void {
|
|||||||
gfx::drawRect(vg, m_pos, theme->GetColour(ThemeEntryID_SIDEBAR));
|
gfx::drawRect(vg, m_pos, theme->GetColour(ThemeEntryID_SIDEBAR));
|
||||||
gfx::drawText(vg, m_title_pos, m_title_size, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str());
|
gfx::drawText(vg, m_title_pos, m_title_size, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str());
|
||||||
if (!m_sub.empty()) {
|
if (!m_sub.empty()) {
|
||||||
gfx::drawTextArgs(vg, m_pos.x + m_pos.w - 30.f, m_title_pos.y + 10.f, 18, NVG_ALIGN_TOP | NVG_ALIGN_RIGHT, theme->GetColour(ThemeEntryID_TEXT), m_sub.c_str());
|
gfx::drawTextArgs(vg, m_pos.x + m_pos.w - 30.f, m_title_pos.y + 10.f, 16, NVG_ALIGN_TOP | NVG_ALIGN_RIGHT, theme->GetColour(ThemeEntryID_TEXT_INFO), m_sub.c_str());
|
||||||
}
|
}
|
||||||
gfx::drawRect(vg, m_top_bar, theme->GetColour(ThemeEntryID_LINE));
|
gfx::drawRect(vg, m_top_bar, theme->GetColour(ThemeEntryID_LINE));
|
||||||
gfx::drawRect(vg, m_bottom_bar, theme->GetColour(ThemeEntryID_LINE));
|
gfx::drawRect(vg, m_bottom_bar, theme->GetColour(ThemeEntryID_LINE));
|
||||||
@@ -328,7 +328,7 @@ void Sidebar::SetupButtons() {
|
|||||||
RemoveActions();
|
RemoveActions();
|
||||||
|
|
||||||
// add entry actions
|
// add entry actions
|
||||||
for (const auto& [button, action] : m_items[m_index]->GetActions()) {
|
for (const auto& [button, action] : m_items[m_index]->GetActions()) {
|
||||||
SetAction(button, action);
|
SetAction(button, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user