diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index dc68bb8..272cfcb 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,8 @@ "/opt/devkitpro/portlibs/3ds/include/**" ], "cStandard": "c17", - "cppStandard": "c++20" + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-x64" } ], "version": 4 diff --git a/Makefile b/Makefile index 40922a8..5538d97 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +99,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++20 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lstdc++ -lm -lcitro2d -lcitro3d -lctru +LIBS := -lstdc++ -lcurl -lmbedtls -lmbedx509 -lmbedcrypto -lz -lm -lcitro2d -lcitro3d -lctru #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/RenderD7 b/RenderD7 index a0923ac..6d7781b 160000 --- a/RenderD7 +++ b/RenderD7 @@ -1 +1 @@ -Subproject commit a0923acec7237b821c55c47714718c221e796f40 +Subproject commit 6d7781b20992c2192bae62c68a24201510ff2a95 diff --git a/romfs/lang/de/app.json b/romfs/lang/de/app.json index 75fb862..c51c8df 100644 --- a/romfs/lang/de/app.json +++ b/romfs/lang/de/app.json @@ -9,7 +9,7 @@ "NDSP_STATUS": "NdspFirmStatus: ", "HEAD_MAINMENU": "BCSTM-Player -> Hauptmenü", "HEAD_SETTINGS": "BCSTM-Player -> Einstellungen", - "HEAD_TITLES": "BCSTM-Palyer -> Titles", + "HEAD_TITLES": "BCSTM-Player -> Titles", "BGB": "Drücke \uE001 um zurückzugehen!", "TPWMR": "Dieses Projekt wurde mit RenderD7 erstellt.", "BROWSE": "Durchsuchen", @@ -48,6 +48,10 @@ "SHOWSECONDS": "Zeige Sekunden", "APPEARANCE": "Darstellung: ", "DEVELOPER": "Entwickler: ", - "SHOWTITLEOPT": "Zeige Titelverwaltung" + "SHOWTITLEOPT": "Zeige Titelverwaltung", + "UPDATER": "Updater: ", + "AUTOSEARCHUPDATE": "Suche Automatisch nach Updates", + "USENIGHTLY": "Nutze Nightly Version", + "CHECK": "Überprüfen" } } \ No newline at end of file diff --git a/romfs/lang/en/app.json b/romfs/lang/en/app.json index 1afc4dd..4fc6556 100644 --- a/romfs/lang/en/app.json +++ b/romfs/lang/en/app.json @@ -9,7 +9,7 @@ "NDSP_STATUS": "NdspFirmStatus: ", "HEAD_MAINMENU": "BCSTM-Player -> Main Menu", "HEAD_SETTINGS": "BCSTM-Player -> Settings", - "HEAD_TITLES": "BCSTM-Palyer -> Titles", + "HEAD_TITLES": "BCSTM-Player -> Titles", "BGB": "Press \uE001 to go back!", "TPWMR": "This Project was made with RenderD7.", "BROWSE": "Browse", @@ -48,6 +48,10 @@ "SHOWSECONDS": "Show Seconds", "APPEARANCE": "Appearance: ", "DEVELOPER": "Developer: ", - "SHOWTITLEOPT": "Show Titlemanager" + "SHOWTITLEOPT": "Show Titlemanager", + "UPDATER": "Updater: ", + "AUTOSEARCHUPDATE": "Auto Check for Update", + "USENIGHTLY": "Use Nightly Version", + "CHECK": "Check" } } \ No newline at end of file diff --git a/source/common.cpp b/source/common.cpp index ce04caa..cfdce8e 100644 --- a/source/common.cpp +++ b/source/common.cpp @@ -7,6 +7,10 @@ bool playing = false; std::string now_playing = ""; bool romfs_is_mount = false; Config config; +Update update_info; +bool checking_for_update = false; +std::string thiz_path; +bool hb_mode; std::string Clock() { const time_t ut = time(0); bool h24 = config.GetBool("24h"); @@ -27,4 +31,44 @@ std::string Clock() { } return std::format("{}:{:02}:{:02}", ts->tm_hour, ts->tm_min, ts->tm_sec); } +void CheckForUpdate(bool is_auto) { + RenderD7::Tasks::Create([&]() { + if (checking_for_update) return; + checking_for_update = true; + update_info = Update(); + update_info.nightly = config.GetBool("use_nightly"); + std::string url; + if (update_info.nightly) { + url = "https://api.github.com/repos/NPI-D7/BCSTM-Player/commits"; + } else { + url = "https://api.github.com/repos/NPI-D7/BCSTM-Player/releases/latest"; + } + nlohmann::json js; + auto ret = RD7::Net::JsonApiRequest(url, js); + if (ret) { + update_info = Update(); + checking_for_update = false; + return; + } + if (update_info.nightly) { + update_info.version = + js[0]["sha"].get_ref().substr(0, 7); + update_info.text = js[0]["commit"]["message"]; + update_info.valid = true; + checking_for_update = false; + return; + } else { + update_info.version = js["tag_name"]; + if (update_info.version[0] != 'v') { + update_info = Update(); + checking_for_update = false; + return; + } + update_info.text = js["body"]; + update_info.valid = true; + checking_for_update = false; + return; + } + }); +} } // namespace BP \ No newline at end of file diff --git a/source/common.hpp b/source/common.hpp index 50152b6..47b585f 100644 --- a/source/common.hpp +++ b/source/common.hpp @@ -7,11 +7,29 @@ #include #include +#ifndef N_STRING +#define N_STRING "unknown" +#endif + +#ifndef V_STRING +#define V_STRING "unknown" +#endif + namespace BP { +struct Update { + std::string version = ""; + bool nightly = false; + std::string text = ""; + bool valid = false; +}; +extern Update update_info; extern D7::BCSTM player; extern bool playing; extern std::string now_playing; extern bool romfs_is_mount; extern Config config; +extern std::string thiz_path; +extern bool hb_mode; std::string Clock(); +void CheckForUpdate(bool is_auto = false); } // namespace BP \ No newline at end of file diff --git a/source/config.cpp b/source/config.cpp index ac1293f..b3834d8 100644 --- a/source/config.cpp +++ b/source/config.cpp @@ -38,5 +38,7 @@ void BP::Config::make_new() { config["24h"] = false; config["disp_seconds"] = true; config["romfs_browse"] = false; + config["search_updates"] = true; + config["use_nightly"] = false; Save(); } \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 0186a9b..67b9ad4 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -9,21 +9,22 @@ void Bcstm_Loop() { BP::player.Stop(); } -int main() { +int main(int argc, char* argv[]) { rd7_do_splash = true; d7mc_load_icons = false; RD7::Init::Main("BCSTM-Player"); + BP::thiz_path = argc == 0 ? "sdmc:/3ds/BCSTM-Player.3dsx" : argv[0]; + BP::hb_mode = argc != 0; RD7::Init::NdspFirm(); BP::config.Load(); if (BP::config.GetBool("fade")) RD7::FadeIn(); - std::filesystem::create_directories( - std::filesystem::path("sdmc:/BCSTM-Player/cache/")); RD7::Lang::Load(BP::config.GetString("lang")); if (BP::config.GetBool("rd7tf_theme")) RD7::ThemeLoad("romfs:/themes/rd7tf.theme"); aptSetSleepAllowed(false); - RD7::Tasks::create((ThreadFunc)Bcstm_Loop); + RD7::Tasks::Create(Bcstm_Loop); + if (BP::config.GetBool("search_updates")) BP::CheckForUpdate(true); BP::player.Stop(); // for ui RD7::Scene::Load(std::make_unique()); diff --git a/source/scenes/Settings.cpp b/source/scenes/Settings.cpp index 90a6a43..c3eb20e 100644 --- a/source/scenes/Settings.cpp +++ b/source/scenes/Settings.cpp @@ -1,13 +1,6 @@ #include // #define RELEASE -#ifndef N_STRING -#define N_STRING "unknown" -#endif - -#ifndef V_STRING -#define V_STRING "unknown" -#endif namespace BP { Settings::Settings() { @@ -28,6 +21,8 @@ Settings::Settings() { h24 = config.GetBool("24h"); dps = config.GetBool("disp_seconds"); romfsb = config.GetBool("romfs_browse"); + search_updates = config.GetBool("search_updates"); + use_nightly = config.GetBool("use_nightly"); } void Settings::Draw(void) const { @@ -79,7 +74,65 @@ void Settings::Draw(void) const { UI7::Checkbox(RD7::Lang::Get("CLOCK"), dispc); UI7::Checkbox(RD7::Lang::Get("24HRS"), h24); UI7::Checkbox(RD7::Lang::Get("SHOWSECONDS"), dps); + UI7::Label(RD7::Lang::Get("UPDATER")); + UI7::Checkbox(RD7::Lang::Get("AUTOSEARCHUPDATE"), search_updates); + UI7::Checkbox(RD7::Lang::Get("USENIGHTLY"), use_nightly); + if (UI7::Button(RD7::Lang::Get("CHECK"))) { + BP::CheckForUpdate(true); + } + if (update_info.valid) { + if (!update_info.nightly && + update_info.version.substr(1).compare(V_STRING) < 0) { + UI7::Label("Already Up to date!"); + } else { + UI7::Label("Update: " + update_info.version); + UI7::Label("Info/Changelog: \n" + update_info.text); + if (UI7::Button("Download")) { + RenderD7::Tasks::Create([&]() { + downloading = true; + std::string fname = "BCSTM-Player."; + fname += hb_mode ? "3dsx" : "cia"; + if (update_info.nightly) { + auto ret = RD7::Net::Download2File( + "https://raw.githubusercontent.com/NPI-D7/nightlys/master/" + "builds/BCSTM-Player/" + + fname, + hb_mode ? thiz_path : "sdmc:/BCSTM-Player.cia"); + if (ret) { + RD7::PushMessage(RD7::Lang::Get("UPDATER"), + "Update Failed!\n" + + std::to_string(RD7::Net::ErrorCode(ret)) + + "/" + + std::to_string(RD7::Net::StatusCode(ret))); + } + } else { + auto ret = RD7::Net::GitDownloadRelease( + "https://github.com/NPI-D7/BCSTM-Player", fname, + hb_mode ? thiz_path : "sdmc:/BCSTM-Player.cia"); + if (ret) { + RD7::PushMessage(RD7::Lang::Get("UPDATER"), + "Update Failed!\n" + + std::to_string(RD7::Net::ErrorCode(ret)) + + "/" + + std::to_string(RD7::Net::StatusCode(ret))); + } + } + RD7::PushMessage(RD7::Lang::Get("UPDATER"), + "Done, Restart to\nApply Changes!"); + downloading = false; + }); + } + } + } + if (downloading) { + UI7::Label( + "Download: " + RD7::FormatBytes(RD7::Net::GetProgressCurrent()) + + "/" + RD7::FormatBytes(RD7::Net::GetProgressTotal())); + UI7::Progressbar((float)RD7::Net::GetProgressCurrent() / + (float)RD7::Net::GetProgressTotal()); + } UI7::Label(RD7::Lang::Get("DEVELOPER")); + UI7::Label("Exec Mode: " + std::string(hb_mode ? "3dsx" : "cia")); UI7::Checkbox(RD7::Lang::Get("SHOWTITLEOPT"), romfsb); if (UI7::Button("RenderD7")) { RD7::LoadSettings(); @@ -104,6 +157,12 @@ void Settings::Logic() { if (romfsb != config.GetBool("romfs_browse")) { config.Set("romfs_browse", romfsb); } + if (use_nightly != config.GetBool("use_nightly")) { + config.Set("use_nightly", use_nightly); + } + if (search_updates != config.GetBool("search_updates")) { + config.Set("search_updates", search_updates); + } if (rd7tf_theme != config.GetBool("rd7tf_theme")) { config.Set("rd7tf_theme", rd7tf_theme); if (rd7tf_theme == true) { diff --git a/source/scenes/Settings.hpp b/source/scenes/Settings.hpp index fd27a21..f2adbbe 100644 --- a/source/scenes/Settings.hpp +++ b/source/scenes/Settings.hpp @@ -19,5 +19,8 @@ class Settings : public RD7::Scene { mutable bool h24 = false; mutable bool dps = false; mutable bool romfsb = false; + mutable bool downloading = false; + mutable bool use_nightly = false; + mutable bool search_updates = false; }; } // namespace BP \ No newline at end of file diff --git a/source/scenes/Titles.cpp b/source/scenes/Titles.cpp index 7fb11fb..b2934c0 100644 --- a/source/scenes/Titles.cpp +++ b/source/scenes/Titles.cpp @@ -2,7 +2,8 @@ namespace BP { Titles::Titles() { - D7MC::TitleManager::ScanSD("sdmc:/BCSTM-Player/"); + std::filesystem::create_directories(RenderD7::GetAppDirectory() + "/cache"); + D7MC::TitleManager::ScanSD(RenderD7::GetAppDirectory() + "/"); maxtitles = (int)D7MC::TitleManager::sdtitles.size(); for (const auto &it : D7MC::TitleManager::sdtitles) namelist.push_back(it->name());