diff --git a/vita3k/compat/src/compat.cpp b/vita3k/compat/src/compat.cpp index 8c22a7a3bc..ab8c05269c 100644 --- a/vita3k/compat/src/compat.cpp +++ b/vita3k/compat/src/compat.cpp @@ -157,8 +157,10 @@ bool load_app_compat_db(GuiState &gui, EmuEnvState &emuenv) { } // Update compatibility status of all user apps - for (auto &app : gui.app_selector.user_apps) - app.compat = gui.compat.app_compat_db.contains(app.title_id) ? gui.compat.app_compat_db[app.title_id].state : CompatibilityState::UNKNOWN; + for (auto &apps : gui.app_selector.vita_apps) { + for (auto &app : apps.second) + app.compat = gui.compat.app_compat_db.contains(app.title_id) ? gui.compat.app_compat_db[app.title_id].state : CompatibilityState::UNKNOWN; + } return !gui.compat.app_compat_db.empty(); } diff --git a/vita3k/config/include/config/state.h b/vita3k/config/include/config/state.h index 4ce3e4c10f..9e71cbd008 100644 --- a/vita3k/config/include/config/state.h +++ b/vita3k/config/include/config/state.h @@ -84,6 +84,7 @@ struct Config : YamlLoader { fullscreen = rhs.fullscreen; console = rhs.console; app_args = rhs.app_args; + app_device = rhs.app_device; load_app_list = rhs.load_app_list; self_path = rhs.self_path; } @@ -101,6 +102,7 @@ struct Config : YamlLoader { // Setting not present in the YAML file fs::path config_path = {}; std::string app_args; + std::string app_device; std::string self_path; bool overwrite_config = true; bool load_config = false; diff --git a/vita3k/config/src/config.cpp b/vita3k/config/src/config.cpp index 8b006e648e..91b1166866 100644 --- a/vita3k/config/src/config.cpp +++ b/vita3k/config/src/config.cpp @@ -145,12 +145,14 @@ ExitCode init_config(Config &cfg, int argc, char **argv, const Root &root_paths) ->default_val(false)->group("Input"); input->add_option("--app-args,-Z", command_line.app_args, "Argument for app, use ', ' to separate arguments.") ->default_str("")->group("Input"); + input->add_option("--app-device,-D", command_line.app_device, "App device") + ->default_val("ux0")->group("Input"); input->add_option("--load-app-list,-a", command_line.load_app_list, "Starts the emulator with load app list.") ->default_val(false)->group("Input"); input->add_option("--self,-S", command_line.self_path, "Path to the self to run inside Title ID") ->default_str("eboot.bin")->group("Input"); input->add_option("--installed-path,-r", command_line.run_app_path, "Path to the installed app to run") - ->default_str({})->check(CLI::IsMember(get_file_set(cfg.get_pref_path() / "ux0/app")))->group("Input"); + ->default_str({})->group("Input"); input->add_option("--recompile-shader,-s", command_line.recompile_shader_path, "Recompile the given PS Vita shader (GXP format) to SPIR_V / GLSL and quit") ->default_str({})->group("Input"); input->add_option("--deleted-id,-d", command_line.delete_title_id, "Title ID of installed app to delete") @@ -208,7 +210,20 @@ ExitCode init_config(Config &cfg, int argc, char **argv, const Root &root_paths) std::cout << window_title << std::endl; return QuitRequested; } - + if (command_line.run_app_path.has_value()) { + const std::string app_path = command_line.run_app_path.value(); + std::set exist_apps = get_file_set(fs::path(cfg.pref_path) / command_line.app_device / "app"); + if (exist_apps.find(app_path) == exist_apps.end()) { + std::cout << "--installed-path: " << app_path << " no in {"; + for (auto &app : exist_apps) { + std::cout << app; + if (app != *exist_apps.rbegin()) + std::cout << ", "; + } + std::cout << "}" << std::endl; + return InitConfigFailed; + } + } if (command_line.recompile_shader_path.has_value()) { cfg.recompile_shader_path = std::move(command_line.recompile_shader_path); return QuitRequested; diff --git a/vita3k/emuenv/include/emuenv/state.h b/vita3k/emuenv/include/emuenv/state.h index 5378ec304d..7b86edaec0 100644 --- a/vita3k/emuenv/include/emuenv/state.h +++ b/vita3k/emuenv/include/emuenv/state.h @@ -120,6 +120,7 @@ struct EmuEnvState { fs::path static_assets_path{}; fs::path shared_path{}; bool load_exec{}; + std::string load_app_device{}; std::string load_app_path{}; std::string load_exec_argv{}; std::string load_exec_path{}; diff --git a/vita3k/gui/include/gui/functions.h b/vita3k/gui/include/gui/functions.h index 4c2dd832d9..3db2007bca 100644 --- a/vita3k/gui/include/gui/functions.h +++ b/vita3k/gui/include/gui/functions.h @@ -41,7 +41,7 @@ void browse_live_area_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32 void browse_pages_manual(GuiState &gui, EmuEnvState &emuenv, const uint32_t button); void browse_save_data_dialog(GuiState &gui, EmuEnvState &emuenv, const uint32_t button); void browse_users_management(GuiState &gui, EmuEnvState &emuenv, const uint32_t button); -void close_and_run_new_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); +void close_and_run_new_app(EmuEnvState &emuenv, const std::string &app_path); void close_live_area_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); void close_system_app(GuiState &gui, EmuEnvState &emuenv); void delete_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); @@ -69,12 +69,13 @@ std::string get_sys_lang_name(uint32_t lang_id); void init(GuiState &gui, EmuEnvState &emuenv); void init_app_background(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); void init_app_icon(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); -void init_apps_icon(GuiState &gui, EmuEnvState &emuenv, const std::vector &app_list); +void init_apps_icon(GuiState &gui, EmuEnvState &emuenv, const std::vector &apps_list); bool init_bgm(EmuEnvState &emuenv, const std::pair path_bgm); void init_bgm_player(const float vol); void init_config(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); void init_content_manager(GuiState &gui, EmuEnvState &emuenv); vfs::FileBuffer init_default_icon(GuiState &gui, EmuEnvState &emuenv); +void init_fw_apps(GuiState &gui, EmuEnvState &emuenv); void init_home(GuiState &gui, EmuEnvState &emuenv); void init_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); bool init_manual(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); @@ -85,11 +86,11 @@ void init_last_time_apps(GuiState &gui, EmuEnvState &emuenv); void init_trophy_collection(GuiState &gui, EmuEnvState &emuenv); void init_user(GuiState &gui, EmuEnvState &emuenv, const std::string &user_id); void init_user_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); -void init_user_apps(GuiState &gui, EmuEnvState &emuenv); bool init_user_background(GuiState &gui, EmuEnvState &emuenv, const std::string &background_path); bool init_user_backgrounds(GuiState &gui, EmuEnvState &emuenv); void init_user_management(GuiState &gui, EmuEnvState &emuenv); bool init_user_start_background(GuiState &gui, const std::string &image_path); +void init_vita_apps(GuiState &gui, EmuEnvState &emuenv); void load_and_update_compat_user_apps(GuiState &gui, EmuEnvState &emuenv); void open_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); void open_manual(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path); diff --git a/vita3k/gui/include/gui/state.h b/vita3k/gui/include/gui/state.h index 8cad431e45..5f422f18e2 100644 --- a/vita3k/gui/include/gui/state.h +++ b/vita3k/gui/include/gui/state.h @@ -99,13 +99,13 @@ struct IconAsyncLoader { }; struct AppsSelector { - std::vector sys_apps; - std::vector user_apps; + std::vector emu_apps; + std::map> vita_apps; uint32_t apps_cache_lang; AppInfo app_info; std::optional icon_async_loader; - std::map sys_apps_icon; - std::map user_apps_icon; + std::map emu_apps_icon; + std::map vita_apps_icon; bool is_app_list_sorted{ false }; std::map app_list_sorted; }; diff --git a/vita3k/gui/src/app_context_menu.cpp b/vita3k/gui/src/app_context_menu.cpp index 68c6e4e8d2..65a185a125 100644 --- a/vita3k/gui/src/app_context_menu.cpp +++ b/vita3k/gui/src/app_context_menu.cpp @@ -19,11 +19,16 @@ #include #include + #include #include + #include #include + +#include #include + #include #include @@ -97,7 +102,7 @@ static bool get_update_history(GuiState &gui, EmuEnvState &emuenv, const std::st std::vector::iterator get_time_app_index(GuiState &gui, EmuEnvState &emuenv, const std::string &app) { const auto time_app_index = std::find_if(gui.time_apps[emuenv.io.user_id].begin(), gui.time_apps[emuenv.io.user_id].end(), [&](const TimeApp &t) { - return t.app == app; + return t.app == fs::path(app).stem().string(); }); return time_app_index; @@ -205,7 +210,7 @@ void update_last_time_app_used(GuiState &gui, EmuEnvState &emuenv, const std::st if (time_app_index != gui.time_apps[emuenv.io.user_id].end()) time_app_index->last_time_used = std::time(nullptr); else - gui.time_apps[emuenv.io.user_id].push_back({ app, std::time(nullptr), 0 }); + gui.time_apps[emuenv.io.user_id].push_back({ fs::path(app).stem().string(), std::time(nullptr), 0 }); get_app_index(gui, app)->last_time = std::time(nullptr); if (gui.users[emuenv.io.user_id].sort_apps_type == LAST_TIME) @@ -216,11 +221,12 @@ void update_last_time_app_used(GuiState &gui, EmuEnvState &emuenv, const std::st void delete_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { const auto APP_INDEX = get_app_index(gui, app_path); + const auto &APP = fs::path(app_path).stem().string(); const auto &title_id = APP_INDEX->title_id; try { - fs::remove_all(emuenv.pref_path / "ux0/app" / app_path); + fs::remove_all(emuenv.pref_path / "ux0/app" / APP); - const auto CUSTOM_CONFIG_PATH{ emuenv.config_path / "config" / fmt::format("config_{}.xml", app_path) }; + const auto CUSTOM_CONFIG_PATH{ emuenv.config_path / "config" / fmt::format("config_{}.xml", APP) }; if (fs::exists(CUSTOM_CONFIG_PATH)) fs::remove_all(CUSTOM_CONFIG_PATH); const auto ADDCONT_PATH{ emuenv.pref_path / "ux0/addcont" / APP_INDEX->addcont }; @@ -251,9 +257,9 @@ void delete_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) if (fs::exists(IMPORT_TEXTURES_PATH)) fs::remove_all(IMPORT_TEXTURES_PATH); - if (gui.app_selector.user_apps_icon.contains(app_path)) { - gui.app_selector.user_apps_icon[app_path] = {}; - gui.app_selector.user_apps_icon.erase(app_path); + if (gui.app_selector.vita_apps_icon.contains(app_path)) { + gui.app_selector.vita_apps_icon[app_path] = {}; + gui.app_selector.vita_apps_icon.erase(app_path); } const auto time_app_index = get_time_app_index(gui, emuenv, app_path); @@ -267,7 +273,7 @@ void delete_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) LOG_INFO("Application successfully deleted '{} [{}]'.", title_id, APP_INDEX->title); - gui.app_selector.user_apps.erase(gui.app_selector.user_apps.begin() + (APP_INDEX - &gui.app_selector.user_apps[0])); + gui.app_selector.vita_apps["ux0"].erase(gui.app_selector.vita_apps["ux0"].begin() + (APP_INDEX - gui.app_selector.vita_apps["ux0"].data())); save_apps_cache(gui, emuenv); } catch (std::exception &e) { @@ -299,7 +305,7 @@ void draw_app_context_menu(GuiState &gui, EmuEnvState &emuenv, const std::string const auto APP_INDEX = get_app_index(gui, app_path); const auto &title_id = APP_INDEX->title_id; - const auto APP_PATH{ emuenv.pref_path / "ux0/app" / app_path }; + const auto APP_PATH{ emuenv.pref_path / convert_path(app_path) }; const auto CUSTOM_CONFIG_PATH{ emuenv.config_path / "config" / fmt::format("config_{}.xml", app_path) }; const auto ADDCONT_PATH{ emuenv.pref_path / "ux0/addcont" / APP_INDEX->addcont }; const auto LICENSE_PATH{ emuenv.pref_path / "ux0/license" / title_id }; @@ -571,11 +577,11 @@ void draw_app_context_menu(GuiState &gui, EmuEnvState &emuenv, const std::string } else { // Delete Data const auto ICON_MARGIN = 24.f * SCALE.y; - if (gui.app_selector.user_apps_icon.contains(title_id)) { + if (gui.app_selector.vita_apps_icon.contains(title_id)) { ImGui::SetCursorPos(ImVec2((WINDOW_SIZE.x / 2.f) - (PUPOP_ICON_SIZE.x / 2.f), ICON_MARGIN)); const auto POS_MIN = ImGui::GetCursorScreenPos(); const ImVec2 POS_MAX(POS_MIN.x + PUPOP_ICON_SIZE.x, POS_MIN.y + PUPOP_ICON_SIZE.y); - ImGui::GetWindowDrawList()->AddImageRounded(gui.app_selector.user_apps_icon[title_id], POS_MIN, POS_MAX, ImVec2(0, 0), ImVec2(1, 1), IM_COL32_WHITE, PUPOP_ICON_SIZE.x * SCALE.x, ImDrawFlags_RoundCornersAll); + ImGui::GetWindowDrawList()->AddImageRounded(gui.app_selector.vita_apps_icon[title_id], POS_MIN, POS_MAX, ImVec2(0, 0), ImVec2(1, 1), IM_COL32_WHITE, PUPOP_ICON_SIZE.x * SCALE.x, ImDrawFlags_RoundCornersAll); } ImGui::SetWindowFontScale(1.6f * RES_SCALE.x); ImGui::SetCursorPos(ImVec2((WINDOW_SIZE.x / 2.f) - (ImGui::CalcTextSize(APP_INDEX->stitle.c_str()).x / 2.f), ICON_MARGIN + PUPOP_ICON_SIZE.y + (4.f * SCALE.y))); diff --git a/vita3k/gui/src/compile_shaders.cpp b/vita3k/gui/src/compile_shaders.cpp index 6d591bd12f..60e15f744c 100644 --- a/vita3k/gui/src/compile_shaders.cpp +++ b/vita3k/gui/src/compile_shaders.cpp @@ -42,7 +42,7 @@ void draw_pre_compiling_shaders_progress(GuiState &gui, EmuEnvState &emuenv, con ImGui::SetWindowFontScale(1.1f * RES_SCALE.x); // Check if icon exist - if (gui.app_selector.user_apps_icon.contains(emuenv.io.app_path)) { + if (gui.app_selector.vita_apps_icon.contains(emuenv.io.app_path)) { ImGui::SetCursorPos(ImVec2(54.f * SCALE.x, 32.f * SCALE.y)); ImGui::Image(get_app_icon(gui, emuenv.io.app_path)->second, ICON_SIZE_SCALE); } diff --git a/vita3k/gui/src/content_manager.cpp b/vita3k/gui/src/content_manager.cpp index 1ce82d7d44..be93305ec1 100644 --- a/vita3k/gui/src/content_manager.cpp +++ b/vita3k/gui/src/content_manager.cpp @@ -47,7 +47,7 @@ auto get_recursive_directory_size(const T &path) { } // namespace void get_app_info(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { - const auto APP_PATH{ emuenv.pref_path / "ux0/app" / app_path }; + const auto APP_PATH{ emuenv.pref_path / convert_path(app_path) }; gui.app_selector.app_info = {}; if (fs::exists(APP_PATH) && !fs::is_empty(APP_PATH)) { @@ -60,7 +60,7 @@ void get_app_info(GuiState &gui, EmuEnvState &emuenv, const std::string &app_pat } size_t get_app_size(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { - const auto APP_PATH{ emuenv.pref_path / "ux0/app" / app_path }; + const auto APP_PATH{ emuenv.pref_path / convert_path(app_path) }; boost::uintmax_t app_size = 0; if (fs::exists(APP_PATH) && !fs::is_empty(APP_PATH)) { app_size += get_recursive_directory_size(APP_PATH); @@ -129,7 +129,7 @@ void init_content_manager(GuiState &gui, EmuEnvState &emuenv) { space["free"] = get_unit_size(free_size); const auto query_app = [&gui, &emuenv] { - const auto &directory_list = gui.app_selector.user_apps; + const auto &directory_list = gui.app_selector.vita_apps["ux0"]; const auto pred = [&](const auto acc, const auto &app) { apps_size[app.path] = get_app_size(gui, emuenv, app.path); return acc + apps_size[app.path]; @@ -194,13 +194,14 @@ struct AddCont { static std::map addcont_info; static void get_content_info(GuiState &gui, EmuEnvState &emuenv) { - const auto APP_PATH{ emuenv.pref_path / "ux0/app" / app_selected }; + const auto &APP = fs::path(app_selected).stem().string(); + const auto APP_PATH{ emuenv.pref_path / "ux0/app" / APP }; if (fs::exists(APP_PATH) && !fs::is_empty(APP_PATH)) { gui.app_selector.app_info.size = get_recursive_directory_size(APP_PATH); } addcont_info.clear(); - const auto ADDCONT_PATH{ emuenv.pref_path / "ux0/addcont" / app_selected }; + const auto ADDCONT_PATH{ emuenv.pref_path / "ux0/addcont" / APP }; if (fs::exists(ADDCONT_PATH) && !fs::is_empty(ADDCONT_PATH)) { for (const auto &addcont : fs::directory_iterator(ADDCONT_PATH)) { const auto content_id = addcont.path().stem().string(); @@ -211,7 +212,7 @@ static void get_content_info(GuiState &gui, EmuEnvState &emuenv) { const auto addcont_size = get_recursive_directory_size(addcont); addcont_info[content_id].size = get_unit_size(addcont_size); - const auto content_path{ fs::path("addcont") / app_selected / content_id }; + const auto content_path{ fs::path("addcont") / APP / content_id }; vfs::FileBuffer params; if (vfs::read_file(VitaIoDevice::ux0, params, emuenv.pref_path, content_path / "sce_sys/param.sfo")) { SfoFile sfo_handle; @@ -249,7 +250,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { const auto POPUP_SIZE = ImVec2(756.0f * SCALE.x, 436.0f * SCALE.y); - const auto has_background = gui.apps_background.contains("NPXS10026"); + const auto BG_PATH = "vs0:app/NPXS10026"; const auto is_12_hour_format = emuenv.cfg.sys_time_format == SCE_SYSTEM_PARAM_TIME_FORMAT_12HOUR; ImGui::SetNextWindowPos(WINDOW_POS, ImGuiCond_Always); @@ -262,8 +263,8 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { const auto draw_list = ImGui::GetBackgroundDrawList(); const ImVec2 VIEWPORT_POS_MAX(VIEWPORT_POS.x + VIEWPORT_SIZE.x, VIEWPORT_POS.y + VIEWPORT_SIZE.y); - if (has_background) - draw_list->AddImage(gui.apps_background["NPXS10026"], VIEWPORT_POS, VIEWPORT_POS_MAX); + if (gui.apps_background.contains(BG_PATH)) + draw_list->AddImage(gui.apps_background[BG_PATH], VIEWPORT_POS, VIEWPORT_POS_MAX); else draw_list->AddRectFilled(VIEWPORT_POS, VIEWPORT_POS_MAX, IM_COL32(53.f, 54.f, 70.f, 255.f), 0.f, ImDrawFlags_RoundCornersAll); @@ -277,7 +278,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { if (menu == "info") { ImGui::SetCursorPos(ImVec2(90.f * SCALE.x, 10.f * SCALE.y)); - ImGui::Image(gui.app_selector.user_apps_icon[app_selected], SIZE_ICON_DETAIL); + ImGui::Image(gui.app_selector.vita_apps_icon[app_selected], SIZE_ICON_DETAIL); const auto CALC_NAME = ImGui::CalcTextSize(get_app_index(gui, app_selected)->title.c_str(), nullptr, false, SIZE_INFO.x - SIZE_ICON_DETAIL.x).y / 2.f; ImGui::SetCursorPos(ImVec2((110.f * SCALE.x) + SIZE_ICON_DETAIL.x, (SIZE_ICON_DETAIL.y / 2.f) - CALC_NAME + (10.f * SCALE.y))); ImGui::PushTextWrapPos(SIZE_INFO.x); @@ -290,7 +291,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { ImGui::TextColored(GUI_COLOR_TEXT, "%s", title.c_str()); ImGui::PopTextWrapPos(); if (!menu.empty()) { - if (((menu == "app") && !gui.app_selector.user_apps.empty()) || ((menu == "save") && !save_data_list.empty())) { + if (((menu == "app") && !gui.app_selector.vita_apps["ux0"].empty()) || ((menu == "save") && !save_data_list.empty())) { // Search Bar ImGui::SetCursorPos(ImVec2(VIEWPORT_POS.x + (10.f * SCALE.x), VIEWPORT_POS.y + (32.f * SCALE.y) - (ImGui::CalcTextSize(common["search"].c_str()).y / 2.f))); ImGui::TextColored(GUI_COLOR_TEXT, "%s", common["search"].c_str()); @@ -338,7 +339,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { ImGui::Separator(); ImGui::SetWindowFontScale(1.2f); if (ImGui::Selectable(lang.main["theme"].c_str(), false, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0.f, SIZE_SELECT))) - pre_run_app(gui, emuenv, "NPXS10015"); + pre_run_app(gui, emuenv, "vs0:app/NPXS10015"); ImGui::NextColumn(); ImGui::SetWindowFontScale(0.8f); ImGui::Selectable(space["themes"].c_str(), false, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0.f, SIZE_SELECT)); @@ -361,13 +362,14 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { if (content_delete) { for (const auto &content : contents_selected) { if (content.second) { + const auto &APP = fs::path(content.first).stem().string(); if (menu == "app") { - fs::remove_all(emuenv.pref_path / "ux0/app" / content.first); - fs::remove_all(emuenv.pref_path / "ux0/addcont" / content.first); - gui.app_selector.user_apps.erase(gui.app_selector.user_apps.begin() + (get_app_index(gui, content.first) - &gui.app_selector.user_apps[0])); - gui.app_selector.user_apps_icon.erase(content.first); + fs::remove_all(emuenv.pref_path / "ux0/app" / APP); + fs::remove_all(emuenv.pref_path / "ux0/addcont" / APP); + gui.app_selector.vita_apps["ux0"].erase(gui.app_selector.vita_apps["ux0"].begin() + (get_app_index(gui, content.first) - gui.app_selector.vita_apps["ux0"].data())); + gui.app_selector.vita_apps_icon.erase(content.first); } - const auto SAVE_PATH{ emuenv.pref_path / "ux0/user" / emuenv.io.user_id / "savedata" / content.first }; + const auto SAVE_PATH{ emuenv.pref_path / "ux0/user" / emuenv.io.user_id / "savedata" / APP }; fs::remove_all(SAVE_PATH); } } @@ -408,7 +410,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { // Apps Menu if (menu == "app") { title = application["title"]; - if (gui.app_selector.user_apps.empty()) { + if (gui.app_selector.vita_apps["ux0"].empty()) { ImGui::SetWindowFontScale(1.2f); auto no_item_str = application["no_item"].c_str(); const auto calc_text = ImGui::CalcTextSize(no_item_str); @@ -425,7 +427,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { ImGui::SetColumnWidth(0, 60 * SCALE.x); ImGui::SetColumnWidth(1, 75 * SCALE.x); ImGui::SetColumnWidth(2, 580.f * SCALE.x); - for (const auto &app : gui.app_selector.user_apps) { + for (const auto &app : gui.app_selector.vita_apps["ux0"]) { if (!search_bar.PassFilter(app.title.c_str()) && !search_bar.PassFilter(app.stitle.c_str()) && !search_bar.PassFilter(app.title_id.c_str())) continue; ImGui::PushID(app.path.c_str()); @@ -434,7 +436,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { ImGui::Checkbox("##selected", &contents_selected[app.path]); ImGui::NextColumn(); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (8.f * SCALE.y)); - ImGui::Image(gui.app_selector.user_apps_icon[app.path], SIZE_ICON_LIST); + ImGui::Image(gui.app_selector.vita_apps_icon[app.path], SIZE_ICON_LIST); ImGui::NextColumn(); const auto Title_POS = ImGui::GetCursorPosY(); ImGui::SetWindowFontScale(1.1f); @@ -483,7 +485,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { ImGui::Checkbox("##selected", &contents_selected[save.title_id]); ImGui::NextColumn(); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (8.f * SCALE.y)); - ImGui::Image(gui.app_selector.user_apps_icon[save.title_id], SIZE_ICON_LIST); + ImGui::Image(gui.app_selector.vita_apps_icon[save.title_id], SIZE_ICON_LIST); ImGui::NextColumn(); const auto Title_POS = ImGui::GetCursorPosY(); ImGui::SetWindowFontScale(1.1f); @@ -561,7 +563,7 @@ void draw_content_manager(GuiState &gui, EmuEnvState &emuenv) { ImGui::SetWindowFontScale(1.2f * RES_SCALE.x); ImGui::SetCursorPos(ImVec2(10.f * SCALE.x, WINDOW_SIZE.y - (56.f * SCALE.y))); - const auto is_empty = ((menu == "app") && gui.app_selector.user_apps.empty()) || ((menu == "save") && save_data_list.empty()); + const auto is_empty = ((menu == "app") && gui.app_selector.vita_apps["ux0"].empty()) || ((menu == "save") && save_data_list.empty()); if (menu.empty() || (menu == "info") || is_empty) { // Back if (ImGui::Button("Back", ImVec2(64.f * SCALE.x, 40.f * SCALE.y)) || ImGui::IsKeyPressed(static_cast(emuenv.cfg.keyboard_button_circle))) { diff --git a/vita3k/gui/src/firmware_install_dialog.cpp b/vita3k/gui/src/firmware_install_dialog.cpp index ebe7a799f0..27f72d5a5c 100644 --- a/vita3k/gui/src/firmware_install_dialog.cpp +++ b/vita3k/gui/src/firmware_install_dialog.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,8 @@ static void get_firmware_version(EmuEnvState &emuenv) { if (versionFile.is_open()) { std::getline(versionFile, fw_version); versionFile.close(); + if (fs::file_size(emuenv.pref_path / "PUP_DEC/PUP_dec/pd0.img") > 0) + decrypt_install_nonpdrm(emuenv, emuenv.pref_path / "pd0/app/NPXS10007/sce_sys/package/work.bin", emuenv.pref_path / "pd0/app/NPXS10007"); } else LOG_WARN("Firmware Version file not found!"); diff --git a/vita3k/gui/src/gui.cpp b/vita3k/gui/src/gui.cpp index 70132a7b33..834a021b61 100644 --- a/vita3k/gui/src/gui.cpp +++ b/vita3k/gui/src/gui.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -320,7 +322,7 @@ static IconData load_app_icon(GuiState &gui, EmuEnvState &emuenv, const std::str void init_app_icon(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { IconData data = load_app_icon(gui, emuenv, app_path); if (data.data) { - gui.app_selector.user_apps_icon[app_path].init(gui.imgui_state.get(), data.data.get(), data.width, data.height); + gui.app_selector.vita_apps_icon[app_path].init(gui.imgui_state.get(), data.data.get(), data.width, data.height); } } @@ -332,7 +334,7 @@ void IconAsyncLoader::commit(GuiState &gui) { for (const auto &pair : icon_data) { if (pair.second.data) { - gui.app_selector.user_apps_icon[pair.first].init(gui.imgui_state.get(), pair.second.data.get(), pair.second.width, pair.second.height); + gui.app_selector.vita_apps_icon[pair.first].init(gui.imgui_state.get(), pair.second.data.get(), pair.second.width, pair.second.height); } } @@ -372,8 +374,8 @@ IconAsyncLoader::~IconAsyncLoader() { thread.join(); } -void init_apps_icon(GuiState &gui, EmuEnvState &emuenv, const std::vector &app_list) { - gui.app_selector.icon_async_loader.emplace(gui, emuenv, app_list); +void init_apps_icon(GuiState &gui, EmuEnvState &emuenv, const std::vector &apps_list) { + gui.app_selector.icon_async_loader.emplace(gui, emuenv, apps_list); } void init_app_background(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { @@ -385,16 +387,12 @@ void init_app_background(GuiState &gui, EmuEnvState &emuenv, const std::string & int32_t height = 0; vfs::FileBuffer buffer; - const auto is_sys = app_path.starts_with("NPXS") && (app_path != "NPXS10007"); - if (is_sys) - vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, "app/" + app_path + "/sce_sys/pic0.png"); - else - vfs::read_app_file(buffer, emuenv.pref_path, app_path, "sce_sys/pic0.png"); + vfs::read_app_file(buffer, emuenv.pref_path, app_path, "sce_sys/pic0.png"); const auto &title = APP_INDEX ? APP_INDEX->title : app_path; if (buffer.empty()) { - LOG_WARN("Background not found for application {} [{}].", title, app_path); + LOG_WARN("Background not found for application {} in path [{}].", title, app_path); return; } @@ -419,15 +417,14 @@ static bool get_user_apps(GuiState &gui, EmuEnvState &emuenv) { const auto apps_cache_path{ emuenv.pref_path / "ux0/temp/apps.dat" }; fs::ifstream apps_cache(apps_cache_path, std::ios::in | std::ios::binary); if (apps_cache.is_open()) { - gui.app_selector.user_apps.clear(); // Read size of apps list - size_t size; + uint32_t size; apps_cache.read((char *)&size, sizeof(size)); // Check version of cache uint32_t versionInFile; apps_cache.read((char *)&versionInFile, sizeof(uint32_t)); - if (versionInFile != 1) { + if (versionInFile != 2) { LOG_WARN("Current version of cache: {}, is outdated, recreate it.", versionInFile); return false; } @@ -465,14 +462,14 @@ static bool get_user_apps(GuiState &gui, EmuEnvState &emuenv) { app.title_id = read(); app.path = read(); - gui.app_selector.user_apps.push_back(app); + gui.app_selector.vita_apps["ux0"].push_back(app); } - init_apps_icon(gui, emuenv, gui.app_selector.user_apps); + init_apps_icon(gui, emuenv, gui.app_selector.vita_apps["ux0"]); load_and_update_compat_user_apps(gui, emuenv); } - return !gui.app_selector.user_apps.empty(); + return !gui.app_selector.vita_apps["ux0"].empty(); } void save_apps_cache(GuiState &gui, EmuEnvState &emuenv) { @@ -482,11 +479,11 @@ void save_apps_cache(GuiState &gui, EmuEnvState &emuenv) { fs::ofstream apps_cache(temp_path / "apps.dat", std::ios::out | std::ios::binary); if (apps_cache.is_open()) { // Write Size of apps list - const auto size = gui.app_selector.user_apps.size(); + const uint32_t size = gui.app_selector.vita_apps["ux0"].size(); apps_cache.write((char *)&size, sizeof(size)); // Write version of cache - const uint32_t versionInFile = 1; + const uint32_t versionInFile = 2; apps_cache.write((const char *)&versionInFile, sizeof(uint32_t)); // Write language of cache @@ -494,7 +491,7 @@ void save_apps_cache(GuiState &gui, EmuEnvState &emuenv) { apps_cache.write((char *)&gui.app_selector.apps_cache_lang, sizeof(uint32_t)); // Write Apps list - for (const App &app : gui.app_selector.user_apps) { + for (const App &app : gui.app_selector.vita_apps["ux0"]) { auto write = [&apps_cache](const std::string &i) { const auto size = i.length(); @@ -517,13 +514,25 @@ void save_apps_cache(GuiState &gui, EmuEnvState &emuenv) { } } +void init_fw_apps(GuiState &gui, EmuEnvState &emuenv) { + // Add preinstalled apps working here + static std::vector preinst_apps_paths = { + "pd0:app/NPXS10007", + }; + + for (const auto &app_path : preinst_apps_paths) { + if (fs::exists(emuenv.pref_path / convert_path(app_path) / "eboot.bin")) + init_user_app(gui, emuenv, app_path); + } +} + void init_home(GuiState &gui, EmuEnvState &emuenv) { - if (gui.app_selector.user_apps.empty() && (emuenv.cfg.load_app_list || !emuenv.cfg.run_app_path)) { + init_fw_apps(gui, emuenv); + if (gui.app_selector.vita_apps["ux0"].empty() && (emuenv.cfg.load_app_list || !emuenv.cfg.run_app_path)) { if (!get_user_apps(gui, emuenv)) - init_user_apps(gui, emuenv); + init_vita_apps(gui, emuenv); } - - init_app_background(gui, emuenv, "NPXS10015"); + init_app_background(gui, emuenv, "vs0:app/NPXS10015"); regmgr::init_regmgr(emuenv.regmgr, emuenv.pref_path); @@ -539,13 +548,14 @@ void init_home(GuiState &gui, EmuEnvState &emuenv) { } void init_user_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { - auto &user_apps = gui.app_selector.user_apps; + const auto device = device::get_device(app_path)._to_string(); + auto &user_apps = gui.app_selector.vita_apps[device]; auto it = std::find_if(user_apps.begin(), user_apps.end(), [&](const App &a) { return a.path == app_path; }); if (it != user_apps.end()) { user_apps.erase(it); - gui.app_selector.user_apps_icon.erase(app_path); + gui.app_selector.vita_apps_icon.erase(app_path); } get_app_param(gui, emuenv, app_path); @@ -559,7 +569,7 @@ void init_user_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_pa } std::map::const_iterator get_app_icon(GuiState &gui, const std::string &app_path) { - const auto &app_type = app_path.starts_with("NPXS") && (app_path != "NPXS10007") ? gui.app_selector.sys_apps_icon : gui.app_selector.user_apps_icon; + const auto &app_type = app_path.starts_with("emu") ? gui.app_selector.emu_apps_icon : gui.app_selector.vita_apps_icon; const auto app_icon = std::find_if(app_type.begin(), app_type.end(), [&](const auto &i) { return i.first == app_path; }); @@ -568,7 +578,8 @@ std::map::const_iterator get_app_icon(GuiState &gui, } App *get_app_index(GuiState &gui, const std::string &app_path) { - auto &app_type = app_path.starts_with("NPXS") && (app_path != "NPXS10007") ? gui.app_selector.sys_apps : gui.app_selector.user_apps; + const auto device = device::get_device(app_path)._to_string(); + auto &app_type = app_path.starts_with("emu") ? gui.app_selector.emu_apps : gui.app_selector.vita_apps[device]; const auto app_index = std::find_if(app_type.begin(), app_type.end(), [&](const App &a) { return a.path == app_path; }); @@ -585,20 +596,20 @@ void get_app_param(GuiState &gui, EmuEnvState &emuenv, const std::string &app_pa emuenv.app_info.app_addcont = emuenv.app_info.app_savedata = emuenv.app_info.app_short_title = emuenv.app_info.app_title = emuenv.app_info.app_title_id = emuenv.app_path; // Use app path as TitleID, addcont, Savedata, Short title and Title emuenv.app_info.app_version = emuenv.app_info.app_category = emuenv.app_info.app_parental_level = "N/A"; } - gui.app_selector.user_apps.push_back({ emuenv.app_info.app_version, emuenv.app_info.app_category, emuenv.app_info.app_content_id, emuenv.app_info.app_addcont, emuenv.app_info.app_savedata, emuenv.app_info.app_parental_level, emuenv.app_info.app_short_title, emuenv.app_info.app_title, emuenv.app_info.app_title_id, emuenv.app_path }); + const auto device = device::get_device(app_path)._to_string(); + gui.app_selector.vita_apps[device].push_back({ emuenv.app_info.app_version, emuenv.app_info.app_category, emuenv.app_info.app_content_id, emuenv.app_info.app_addcont, emuenv.app_info.app_savedata, emuenv.app_info.app_parental_level, emuenv.app_info.app_short_title, emuenv.app_info.app_title, emuenv.app_info.app_title_id, emuenv.app_path }); } void get_user_apps_title(GuiState &gui, EmuEnvState &emuenv) { - const fs::path app_path{ emuenv.pref_path / "ux0/app" }; - if (!fs::exists(app_path)) + const fs::path apps_path{ emuenv.pref_path / "ux0/app" }; + if (!fs::exists(apps_path)) return; - gui.app_selector.user_apps.clear(); - for (const auto &app : fs::directory_iterator(app_path)) { + for (const auto &app : fs::directory_iterator(apps_path)) { if (!app.path().empty() && fs::is_directory(app.path()) && !app.path().filename_is_dot() && !app.path().filename_is_dot_dot()) { const auto app_path = app.path().stem().generic_string(); - get_app_param(gui, emuenv, app_path); + get_app_param(gui, emuenv, "ux0:app/" + app_path); } } @@ -606,9 +617,10 @@ void get_user_apps_title(GuiState &gui, EmuEnvState &emuenv) { } void get_sys_apps_title(GuiState &gui, EmuEnvState &emuenv) { - gui.app_selector.sys_apps.clear(); - constexpr std::array sys_apps_list = { "NPXS10003", "NPXS10008", "NPXS10015", "NPXS10026" }; + gui.app_selector.emu_apps.clear(); + constexpr std::array sys_apps_list = { "NPXS10003", "NPXS10008", "NPXS10015", "NPXS10026" }; for (const auto &app : sys_apps_list) { + emuenv.app_path = fmt::format("emu:app/{}", app); vfs::FileBuffer params; if (vfs::read_file(VitaIoDevice::vs0, params, emuenv.pref_path, fmt::format("app/{}/sce_sys/param.sfo", app))) { SfoFile sfo_handle; @@ -637,10 +649,10 @@ void get_sys_apps_title(GuiState &gui, EmuEnvState &emuenv) { else emuenv.app_info.app_short_title = emuenv.app_info.app_title = lang["content_manager"]; } - gui.app_selector.sys_apps.push_back({ emuenv.app_info.app_version, emuenv.app_info.app_category, {}, {}, {}, {}, emuenv.app_info.app_short_title, emuenv.app_info.app_title, emuenv.app_info.app_title_id, app.data() }); + gui.app_selector.emu_apps.push_back({ emuenv.app_info.app_version, emuenv.app_info.app_category, {}, {}, {}, {}, emuenv.app_info.app_short_title, emuenv.app_info.app_title, emuenv.app_info.app_title_id, emuenv.app_path }); } - std::sort(gui.app_selector.sys_apps.begin(), gui.app_selector.sys_apps.end(), [](const App &lhs, const App &rhs) { + std::sort(gui.app_selector.emu_apps.begin(), gui.app_selector.emu_apps.end(), [](const App &lhs, const App &rhs) { return string_utils::toupper(lhs.title) < string_utils::toupper(rhs.title); }); } diff --git a/vita3k/gui/src/home_screen.cpp b/vita3k/gui/src/home_screen.cpp index 057262eef2..8c625b6134 100644 --- a/vita3k/gui/src/home_screen.cpp +++ b/vita3k/gui/src/home_screen.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,9 +36,9 @@ using namespace std::string_literals; namespace gui { -void init_user_apps(GuiState &gui, EmuEnvState &emuenv) { +void init_vita_apps(GuiState &gui, EmuEnvState &emuenv) { gui.apps_background.clear(); - gui.app_selector.user_apps_icon.clear(); + gui.app_selector.vita_apps_icon.clear(); gui.live_area_app_current_open = -1; gui.live_area_current_open_apps_list.clear(); gui.live_area_contents.clear(); @@ -46,30 +47,31 @@ void init_user_apps(GuiState &gui, EmuEnvState &emuenv) { gui.app_selector.icon_async_loader->quit = true; std::thread init_apps([&gui, &emuenv]() { - auto app_list_size = gui.app_selector.user_apps.size(); - gui.app_selector.user_apps.clear(); + auto apps_list_size = gui.app_selector.vita_apps["ux0"].size(); + gui.app_selector.vita_apps.clear(); + + init_fw_apps(gui, emuenv); get_user_apps_title(gui, emuenv); - if (gui.app_selector.user_apps.empty()) + if (gui.app_selector.vita_apps["ux0"].empty()) return false; gui.app_selector.is_app_list_sorted = false; init_last_time_apps(gui, emuenv); load_and_update_compat_user_apps(gui, emuenv); - init_apps_icon(gui, emuenv, gui.app_selector.user_apps); + const auto new_apps_list_size = gui.app_selector.vita_apps["ux0"].size(); + init_apps_icon(gui, emuenv, gui.app_selector.vita_apps["ux0"]); - if (app_list_size == gui.app_selector.user_apps.size()) + if (apps_list_size == new_apps_list_size) return false; std::string change_app_list = "new application(s) added"; - if (app_list_size > gui.app_selector.user_apps.size()) { + if (apps_list_size > new_apps_list_size) { change_app_list = "application(s) removed"; - app_list_size -= gui.app_selector.user_apps.size(); + apps_list_size -= new_apps_list_size; } else - app_list_size = gui.app_selector.user_apps.size() - app_list_size; - - LOG_INFO("{} {}", app_list_size, change_app_list); + apps_list_size = new_apps_list_size - apps_list_size; return true; }); @@ -87,8 +89,9 @@ void init_last_time_apps(GuiState &gui, EmuEnvState &emuenv) { } }; - last_time_apps(gui.app_selector.sys_apps); - last_time_apps(gui.app_selector.user_apps); + last_time_apps(gui.app_selector.emu_apps); + for (auto &[_, apps] : gui.app_selector.vita_apps) + last_time_apps(apps); gui.app_selector.is_app_list_sorted = false; } @@ -132,7 +135,7 @@ void open_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_p } void pre_load_app(GuiState &gui, EmuEnvState &emuenv, bool live_area, const std::string &app_path) { - if (app_path == "NPXS10003") { + if (app_path == "emu:app/NPXS10003") { update_last_time_app_used(gui, emuenv, app_path); open_path("https://Vita3k.org"); } else { @@ -145,8 +148,8 @@ void pre_load_app(GuiState &gui, EmuEnvState &emuenv, bool live_area, const std: void pre_run_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { switch_bgm_state(true); - const auto is_sys = app_path.starts_with("NPXS") && (app_path != "NPXS10007"); - if (!is_sys) { + const auto is_emu = app_path.starts_with("emu"); + if (!is_emu) { if (emuenv.io.app_path != app_path) { if (!emuenv.io.app_path.empty()) gui.vita_area.app_close = true; @@ -162,16 +165,15 @@ void pre_run_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path emuenv.app_path = app_path; gui.vita_area.home_screen = false; gui.vita_area.live_area_screen = false; - init_app_background(gui, emuenv, app_path); - update_last_time_app_used(gui, emuenv, app_path); + init_app_background(gui, emuenv, "vs0:app/" + fs::path(app_path).stem().string()); - if (app_path == "NPXS10008") { + if (app_path == "emu:app/NPXS10008") { init_trophy_collection(gui, emuenv); gui.vita_area.trophy_collection = true; - } else if (app_path == "NPXS10015") { + } else if (app_path == "emu:app/NPXS10015") { if (gui.vita_area.content_manager) { - emuenv.app_path = "NPXS10026"; - update_time_app_used(gui, emuenv, "NPXS10026"); + emuenv.app_path = "emu:app/NPXS10026"; + update_time_app_used(gui, emuenv, emuenv.app_path); gui.vita_area.content_manager = false; } @@ -184,10 +186,9 @@ void pre_run_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path } void close_system_app(GuiState &gui, EmuEnvState &emuenv) { - if (gui.vita_area.content_manager) { + if (gui.vita_area.content_manager) gui.vita_area.content_manager = false; - update_time_app_used(gui, emuenv, "NPXS10026"); - } else if (gui.vita_area.manual) { + else if (gui.vita_area.manual) { gui.vita_area.manual = false; // Free manual textures from memory when manual is closed @@ -196,15 +197,12 @@ void close_system_app(GuiState &gui, EmuEnvState &emuenv) { gui.manuals.clear(); } else if (gui.vita_area.settings) { gui.vita_area.settings = false; - update_time_app_used(gui, emuenv, "NPXS10015"); - if (emuenv.app_path == "NPXS10026") { - pre_run_app(gui, emuenv, "NPXS10026"); + if (emuenv.app_path == "emu:app/NPXS10026") { + pre_run_app(gui, emuenv, "emu:app/NPXS10026"); return; } - } else { + } else gui.vita_area.trophy_collection = false; - update_time_app_used(gui, emuenv, "NPXS10008"); - } if ((gui::get_live_area_current_open_apps_list_index(gui, emuenv.app_path) != gui.live_area_current_open_apps_list.end()) && (gui.live_area_current_open_apps_list[gui.live_area_app_current_open] == emuenv.app_path)) { gui.vita_area.live_area_screen = true; @@ -218,9 +216,10 @@ void close_system_app(GuiState &gui, EmuEnvState &emuenv) { switch_bgm_state(false); } -void close_and_run_new_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { +void close_and_run_new_app(EmuEnvState &emuenv, const std::string &app_path) { emuenv.kernel.exit_delete_all_threads(); - emuenv.load_app_path = app_path; + emuenv.load_app_device = device::get_device(emuenv.io.app_path)._to_string(); + emuenv.load_app_path = fs::path(app_path).stem().string(); emuenv.load_exec = true; } @@ -247,7 +246,7 @@ void draw_app_close(GuiState &gui, EmuEnvState &emuenv) { ImGui::SetWindowFontScale(1.4f * RES_SCALE.x); ImGui::SetCursorPos(ImVec2(50.f * SCALE.x, 108.f * SCALE.y)); ImGui::TextColored(GUI_COLOR_TEXT, "%s", gui.lang.game_data["app_close"].c_str()); - if (gui.app_selector.user_apps_icon.contains(emuenv.io.app_path)) { + if (gui.app_selector.vita_apps_icon.contains(emuenv.io.app_path)) { const auto ICON_POS_SCALE = ImVec2(50.f * SCALE.x, (WINDOW_SIZE.y / 2.f) - (ICON_SIZE.y / 2.f) - (10.f * SCALE.y)); ImGui::SetCursorPos(ICON_POS_SCALE); const auto POS_MIN = ImGui::GetCursorScreenPos(); @@ -261,7 +260,7 @@ void draw_app_close(GuiState &gui, EmuEnvState &emuenv) { ImGui::SameLine(0, 20.f * SCALE.x); if (ImGui::Button(common["ok"].c_str(), BUTTON_SIZE)) { const auto &app_path = gui.vita_area.live_area_screen ? gui.live_area_current_open_apps_list[gui.live_area_app_current_open] : emuenv.app_path; - close_and_run_new_app(gui, emuenv, app_path); + close_and_run_new_app(emuenv, app_path); } ImGui::PopStyleVar(); ImGui::EndChild(); @@ -345,7 +344,7 @@ static void sort_app_list(GuiState &gui, EmuEnvState &emuenv, const SortType &ty gui.app_selector.is_app_list_sorted = true; } - std::sort(gui.app_selector.user_apps.begin(), gui.app_selector.user_apps.end(), [&](const App &lhs, const App &rhs) { + std::sort(gui.app_selector.vita_apps["ux0"].begin(), gui.app_selector.vita_apps["ux0"].end(), [&](const App &lhs, const App &rhs) { switch (type) { case APP_VER: switch (sorted) { @@ -461,6 +460,11 @@ void browse_home_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t bu } }; + const auto has_preinst_app = gui.app_selector.vita_apps.contains("pd0"); + const auto &preinst_app = gui.app_selector.vita_apps["pd0"][0]; + const auto &user_app = gui.app_selector.vita_apps["ux0"]; + const auto &selected_app = current_selected_app_index < 0 ? gui.app_selector.emu_apps[current_selected_app_index + 4] : (has_preinst_app ? (current_selected_app_index == 0 ? preinst_app : user_app[current_selected_app_index - 1]) : user_app[current_selected_app_index]); + switch (button) { case SCE_CTRL_UP: if (emuenv.cfg.apps_list_grid) { @@ -495,16 +499,12 @@ void browse_home_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t bu gui.vita_area.home_screen = !gui.vita_area.live_area_screen; break; case SCE_CTRL_CIRCLE: - if (emuenv.cfg.sys_button == 0) { - const auto &selected_app = current_selected_app_index < 0 ? gui.app_selector.sys_apps[current_selected_app_index + 4] : gui.app_selector.user_apps[current_selected_app_index]; + if (emuenv.cfg.sys_button == 0) pre_load_app(gui, emuenv, emuenv.cfg.show_live_area_screen, selected_app.path); - } break; case SCE_CTRL_CROSS: - if (emuenv.cfg.sys_button == 1) { - const auto &selected_app = current_selected_app_index < 0 ? gui.app_selector.sys_apps[current_selected_app_index + 4] : gui.app_selector.user_apps[current_selected_app_index]; + if (emuenv.cfg.sys_button == 1) pre_load_app(gui, emuenv, emuenv.cfg.show_live_area_screen, selected_app.path); - } break; default: break; } @@ -513,14 +513,14 @@ void browse_home_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t bu static int selected_app_index = INVALID_APP_INDEX; void select_app(GuiState &gui, const std::string &title_id) { // Find the app in the user apps list - auto app_it = std::find_if(gui.app_selector.user_apps.begin(), gui.app_selector.user_apps.end(), [&](const App &app) { + auto app_it = std::find_if(gui.app_selector.vita_apps["ux0"].begin(), gui.app_selector.vita_apps["ux0"].end(), [&](const App &app) { return app.title_id == title_id; }); // Check if the app was found - if (app_it != gui.app_selector.user_apps.end()) { + if (app_it != gui.app_selector.vita_apps["ux0"].end()) { // Set the selected app index - current_selected_app_index = selected_app_index = std::distance(gui.app_selector.user_apps.begin(), app_it); + current_selected_app_index = selected_app_index = std::distance(gui.app_selector.vita_apps["ux0"].begin(), app_it); gui.is_nav_button = true; } else LOG_ERROR("App with title id {} not found", title_id); @@ -723,7 +723,7 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) { const auto search_bar_size = 120.f * VIEWPORT_SCALE.x; ImGui::SameLine(ImGui::GetColumnWidth() - ImGui::CalcTextSize(lang["refresh"].c_str()).x - search_bar_size - (78 * VIEWPORT_SCALE.x)); if (ImGui::Button(lang["refresh"].c_str())) - init_user_apps(gui, emuenv); + init_vita_apps(gui, emuenv); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, GUI_COLOR_SEARCH_BAR_TEXT); ImGui::PushStyleColor(ImGuiCol_FrameBg, GUI_COLOR_SEARCH_BAR_BG); @@ -779,9 +779,9 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) { const auto display_app = [&](const std::vector &apps_list, std::map &apps_icon) { for (const auto &app : apps_list) { - const auto is_sys = app.path.starts_with("NPXS") && (app.path != "NPXS10007"); + const auto is_emu = app.path.starts_with("emu"); - if (!is_sys) { + if (!is_emu) { // Filter app by region and type if (app_filter(app.title_id)) continue; @@ -804,9 +804,13 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) { if (emuenv.cfg.apps_list_grid) ImGui::SetCursorPosX(GRID_ICON_POS); + const auto is_preinst_app = app.path.starts_with("pd0"); + const auto is_user_app = app.path.starts_with("ux0"); + const auto has_preinst_app = gui.app_selector.vita_apps.contains("pd0"); + // Get the current app index off the apps list. const auto app_index = static_cast(&app - apps_list.data()); - const auto current_app_index = !is_sys ? app_index : app_index - 4; + const auto current_app_index = !is_emu ? (is_preinst_app ? app_index : app_index + 1) : app_index - 4; apps_list_filtered.push_back(current_app_index); // Check if the current app is selected. @@ -888,7 +892,7 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) { ImGui::NextColumn(); // Draw the compatibility badge for commercial apps when they are within the visible area. - if (element_is_within_visible_area && (app.title_id.starts_with("PCS") || (app.title_id == "NPXS10007"))) { + if (element_is_within_visible_area && (app.path.starts_with("pd0") || app.title_id.starts_with("PCS"))) { const auto compat_state = (gui.compat.compat_db_loaded ? gui.compat.app_compat_db.contains(app.title_id) : false) ? gui.compat.app_compat_db[app.title_id].state : compat::UNKNOWN; const auto &compat_state_vec4 = gui.compat.compat_color[compat_state]; const ImU32 compat_state_color = IM_COL32((int)(compat_state_vec4.x * 255.0f), (int)(compat_state_vec4.y * 255.0f), (int)(compat_state_vec4.z * 255.0f), (int)(compat_state_vec4.w * 255.0f)); @@ -940,10 +944,11 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) { // Draw System Applications if (emuenv.cfg.display_system_apps) - display_app(gui.app_selector.sys_apps, gui.app_selector.sys_apps_icon); + display_app(gui.app_selector.emu_apps, gui.app_selector.emu_apps_icon); - // Draw User Applications - display_app(gui.app_selector.user_apps, gui.app_selector.user_apps_icon); + // Draw Vita Applications + for (const auto &[_, apps] : gui.app_selector.vita_apps) + display_app(apps, gui.app_selector.vita_apps_icon); ImGui::PopStyleColor(); ImGui::Columns(1); diff --git a/vita3k/gui/src/information_bar.cpp b/vita3k/gui/src/information_bar.cpp index 3ba3907d60..7b71bc5d81 100644 --- a/vita3k/gui/src/information_bar.cpp +++ b/vita3k/gui/src/information_bar.cpp @@ -456,11 +456,11 @@ static void draw_notice_info(GuiState &gui, EmuEnvState &emuenv) { save_notice_list(emuenv); if (notice.type == "content") { if (notice.group == "theme") - pre_load_app(gui, emuenv, false, "NPXS10015"); + pre_load_app(gui, emuenv, false, "vs0:app/NPXS10015"); else select_app(gui, notice.id); } else { - pre_load_app(gui, emuenv, false, "NPXS10008"); + pre_load_app(gui, emuenv, false, "vs0:app/NPXS10008"); open_trophy_unlocked(gui, emuenv, notice.id, notice.content_id); } notice_info_state = false; @@ -599,7 +599,7 @@ void draw_information_bar(GuiState &gui, EmuEnvState &emuenv) { const ImVec2 ICON_POS_MAX(ICON_POS_MIN.x + ICON_SIZE_SCALE, ICON_POS_MIN.y + ICON_SIZE_SCALE); const ImVec2 ICON_CENTER_POS(ICON_POS_MIN.x + (ICON_SIZE_SCALE / 2.f), ICON_POS_MIN.y + (ICON_SIZE_SCALE / 2.f)); const auto &APPS_OPENED = gui.live_area_current_open_apps_list[a]; - auto &APP_ICON_TYPE = APPS_OPENED.starts_with("NPXS") && (APPS_OPENED != "NPXS10007") ? gui.app_selector.sys_apps_icon : gui.app_selector.user_apps_icon; + auto &APP_ICON_TYPE = APPS_OPENED.starts_with("emu") ? gui.app_selector.emu_apps_icon : gui.app_selector.vita_apps_icon; // Check if icon exist if (APP_ICON_TYPE.contains(APPS_OPENED)) diff --git a/vita3k/gui/src/live_area.cpp b/vita3k/gui/src/live_area.cpp index 85f9cf7db4..34c4fa1d3f 100644 --- a/vita3k/gui/src/live_area.cpp +++ b/vita3k/gui/src/live_area.cpp @@ -21,7 +21,11 @@ #include #include #include + +#include +#include #include + #include #include #include @@ -152,26 +156,27 @@ static std::map items_styles = { void init_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path) { const auto &live_area_lang = gui.lang.user_lang[LIVE_AREA]; - const auto is_sys_app = app_path.starts_with("NPXS") && (app_path != "NPXS10007"); - const auto is_ps_app = app_path.starts_with("PCS") || (app_path == "NPXS10007"); - const VitaIoDevice app_device = is_sys_app ? VitaIoDevice::vs0 : VitaIoDevice::ux0; + const auto is_emu_app = app_path.starts_with("emu"); const auto APP_INDEX = get_app_index(gui, app_path); + const auto is_com_app = APP_INDEX->title_id.starts_with("PCS"); + const auto is_fw_app = app_path.starts_with("vs0"); - if (is_ps_app && !sku_flag.contains(app_path)) + if (is_com_app && !sku_flag.contains(app_path)) sku_flag[app_path] = get_license_sku_flag(emuenv, APP_INDEX->content_id); if (!gui.live_area_contents.contains(app_path)) { auto default_contents = false; const auto fw_path{ emuenv.pref_path / "vs0" }; const auto default_fw_contents{ fw_path / "data/internal/livearea/default/sce_sys/livearea/contents/template.xml" }; - const auto APP_PATH{ emuenv.pref_path / app_device._to_string() / "app" / app_path }; + const auto live_area_app_path = app_path.starts_with("emu") ? "vs0:app/" + fs::path(app_path).stem().string() : app_path; + const auto APP_PATH{ emuenv.pref_path / convert_path(live_area_app_path) }; const auto live_area_path{ fs::path("sce_sys") / ((sku_flag[app_path] == 3) && fs::exists(APP_PATH / "sce_sys/retail/livearea") ? "retail/livearea" : "livearea") }; auto template_xml{ APP_PATH / live_area_path / "contents/template.xml" }; pugi::xml_document doc; if (!doc.load_file(template_xml.c_str())) { - if (is_ps_app || is_sys_app) + if (is_com_app || is_fw_app || is_emu_app) LOG_WARN("Live Area Contents is corrupted or missing for title: {} '{}' in path: {}.", APP_INDEX->title_id, APP_INDEX->title, template_xml); if (doc.load_file(default_fw_contents.c_str())) { template_xml = default_fw_contents; @@ -253,13 +258,11 @@ void init_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_p if (default_contents) vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, "data/internal/livearea/default/sce_sys/livearea/contents/" + contents.second); - else if (app_device == VitaIoDevice::vs0) - vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, "app/" + app_path + "/sce_sys/livearea/contents/" + contents.second); else - vfs::read_app_file(buffer, emuenv.pref_path, app_path, live_area_path / "contents" / contents.second); + vfs::read_app_file(buffer, emuenv.pref_path, live_area_app_path, live_area_path / "contents" / contents.second); if (buffer.empty()) { - if (is_ps_app || is_sys_app) + if (is_com_app || is_fw_app) LOG_WARN("Contents {} '{}' Not found for title {} [{}].", contents.first, contents.second, app_path, APP_INDEX->title); continue; } @@ -441,13 +444,10 @@ void init_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_p int32_t height = 0; vfs::FileBuffer buffer; - if (app_device == VitaIoDevice::vs0) - vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, fmt::format("app/{}/sce_sys/livearea/contents/{}", app_path, bg_name)); - else - vfs::read_app_file(buffer, emuenv.pref_path, app_path, live_area_path / "contents" / bg_name); + vfs::read_app_file(buffer, emuenv.pref_path, live_area_app_path, live_area_path / "contents" / bg_name); if (buffer.empty()) { - if (is_ps_app || is_sys_app) + if (is_com_app || is_fw_app || is_emu_app) LOG_WARN("background, Id: {}, Name: '{}', Not found for title: {} [{}].", item.first, bg_name, app_path, APP_INDEX->title); continue; } @@ -473,13 +473,10 @@ void init_live_area(GuiState &gui, EmuEnvState &emuenv, const std::string &app_p int32_t height = 0; vfs::FileBuffer buffer; - if (app_device == VitaIoDevice::vs0) - vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, fmt::format("app/{}/sce_sys/livearea/contents/{}", app_path, img_name)); - else - vfs::read_app_file(buffer, emuenv.pref_path, app_path, live_area_path / "contents" / img_name); + vfs::read_app_file(buffer, emuenv.pref_path, live_area_app_path, live_area_path / "contents" / img_name); if (buffer.empty()) { - if (is_ps_app || is_sys_app) + if (is_com_app || is_fw_app || is_emu_app) LOG_WARN("Image, Id: {} Name: '{}', Not found for title {} [{}].", item.first, img_name, app_path, APP_INDEX->title); continue; } @@ -554,7 +551,8 @@ static constexpr ImU32 ARROW_COLOR = 0xFFFFFFFF; // White static LiveAreaType live_area_type_selected = GATE; void browse_live_area_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t button) { - const auto manual_path{ emuenv.pref_path / "ux0/app" / gui.live_area_current_open_apps_list[gui.live_area_app_current_open] / "sce_sys/manual/" }; + const auto &APP_PATH = gui.live_area_current_open_apps_list[gui.live_area_app_current_open]; + const auto manual_path{ emuenv.pref_path / convert_path(APP_PATH) / "sce_sys/manual" }; const auto manual_found = fs::exists(manual_path) && !fs::is_empty(manual_path); if (!gui.is_nav_button) { @@ -567,18 +565,18 @@ void browse_live_area_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32 const auto live_area_current_open_apps_list_size = static_cast(gui.live_area_current_open_apps_list.size() - 1); const auto cancel = [&]() { - close_live_area_app(gui, emuenv, gui.live_area_current_open_apps_list[gui.live_area_app_current_open]); + close_live_area_app(gui, emuenv, APP_PATH); }; const auto confirm = [&]() { switch (live_area_type_selected) { case GATE: - pre_run_app(gui, emuenv, gui.live_area_current_open_apps_list[gui.live_area_app_current_open]); + pre_run_app(gui, emuenv, APP_PATH); break; case SEARCH: - open_search(get_app_index(gui, gui.live_area_current_open_apps_list[gui.live_area_app_current_open])->title); + open_search(get_app_index(gui, APP_PATH)->title); break; case MANUAL: - open_manual(gui, emuenv, gui.live_area_current_open_apps_list[gui.live_area_app_current_open]); + open_manual(gui, emuenv, APP_PATH); break; default: break; @@ -638,7 +636,7 @@ void draw_live_area_screen(GuiState &gui, EmuEnvState &emuenv) { const auto SCALE = ImVec2(RES_SCALE.x * emuenv.dpi_scale, RES_SCALE.y * emuenv.dpi_scale); const auto &app_path = gui.live_area_current_open_apps_list[gui.live_area_app_current_open]; - const VitaIoDevice app_device = app_path.starts_with("NPXS") ? VitaIoDevice::vs0 : VitaIoDevice::ux0; + const VitaIoDevice app_device = device::get_device(app_path); const auto INFO_BAR_HEIGHT = 32.f * SCALE.y; @@ -1078,7 +1076,7 @@ void draw_live_area_screen(GuiState &gui, EmuEnvState &emuenv) { const auto ICON_POS_MAX_SCALE = ImVec2(ICON_POS_MINI_SCALE.x + ICON_SIZE_SCALE, ICON_POS_MINI_SCALE.y + ICON_SIZE_SCALE); // check if app icon exist - auto &APP_ICON_TYPE = app_path.starts_with("NPXS") && (app_path != "NPXS10007") ? gui.app_selector.sys_apps_icon : gui.app_selector.user_apps_icon; + auto &APP_ICON_TYPE = app_path.starts_with("emu") ? gui.app_selector.emu_apps_icon : gui.app_selector.vita_apps_icon; if (APP_ICON_TYPE.contains(app_path)) { window_draw_list->AddImageRounded(APP_ICON_TYPE[app_path], ICON_POS_MINI_SCALE, ICON_POS_MAX_SCALE, ImVec2(0, 0), ImVec2(1, 1), IM_COL32_WHITE, 75.f * SCALE.x, ImDrawFlags_RoundCornersAll); @@ -1097,7 +1095,7 @@ void draw_live_area_screen(GuiState &gui, EmuEnvState &emuenv) { if (app_device == VitaIoDevice::ux0) { const auto widget_scal_size = ImVec2(80.0f * SCALE.x, 80.f * SCALE.y); - const auto manual_path{ emuenv.pref_path / "ux0/app" / app_path / "sce_sys/manual/" }; + const auto manual_path{ emuenv.pref_path / convert_path(app_path) / "sce_sys/manual/" }; const auto scal_widget_font_size = 23.0f / ImGui::GetFontSize(); const auto manual_exist = fs::exists(manual_path) && !fs::is_empty(manual_path); diff --git a/vita3k/gui/src/main_menubar.cpp b/vita3k/gui/src/main_menubar.cpp index 855847987b..7346960703 100644 --- a/vita3k/gui/src/main_menubar.cpp +++ b/vita3k/gui/src/main_menubar.cpp @@ -94,7 +94,7 @@ static void draw_emulation_menu(GuiState &gui, EmuEnvState &emuenv) { } if (!emuenv.cfg.display_system_apps) { ImGui::Separator(); - for (const auto &app : gui.app_selector.sys_apps) + for (const auto &app : gui.app_selector.emu_apps) draw_app(app); } ImGui::EndMenu(); diff --git a/vita3k/gui/src/manual.cpp b/vita3k/gui/src/manual.cpp index 21665bc020..b3ac453c30 100644 --- a/vita3k/gui/src/manual.cpp +++ b/vita3k/gui/src/manual.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -82,8 +83,8 @@ bool init_manual(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path height_manual_pages.clear(); const auto APP_INDEX = get_app_index(gui, app_path); - const auto APP_PATH{ emuenv.pref_path / "ux0/app" / app_path }; - auto manual_path{ fs::path("sce_sys/manual/") }; + const auto APP_PATH{ emuenv.pref_path / convert_path(app_path) }; + auto manual_path{ fs::path("sce_sys/manual") }; const auto lang = fmt::format("{:0>2d}", emuenv.cfg.sys_lang); if (fs::exists(APP_PATH / manual_path / lang)) diff --git a/vita3k/gui/src/settings.cpp b/vita3k/gui/src/settings.cpp index 8654458be7..69ebd15082 100644 --- a/vita3k/gui/src/settings.cpp +++ b/vita3k/gui/src/settings.cpp @@ -224,8 +224,8 @@ void draw_settings(GuiState &gui, EmuEnvState &emuenv) { const auto SIZE_MINI_PACKAGE = ImVec2(170.f * SCALE.x, 96.f * SCALE.y); const auto POPUP_SIZE = ImVec2(756.0f * SCALE.x, 436.0f * SCALE.y); - const auto is_background = gui.apps_background.contains("NPXS10015"); auto &common = emuenv.common_dialog.lang.common; + const auto BG_PATH = "vs0:app/NPXS10015"; ImGui::SetNextWindowPos(WINDOW_POS, ImGuiCond_Always); ImGui::SetNextWindowSize(WINDOW_SIZE, ImGuiCond_Always); @@ -237,8 +237,8 @@ void draw_settings(GuiState &gui, EmuEnvState &emuenv) { const auto draw_list = ImGui::GetBackgroundDrawList(); const ImVec2 BG_POS_MAX(VIEWPORT_POS.x + VIEWPORT_SIZE.x, VIEWPORT_POS.y + VIEWPORT_SIZE.y); - if (is_background) - draw_list->AddImage(gui.apps_background["NPXS10015"], VIEWPORT_POS, BG_POS_MAX); + if (gui.apps_background.contains(BG_PATH)) + draw_list->AddImage(gui.apps_background[BG_PATH], VIEWPORT_POS, BG_POS_MAX); else draw_list->AddRectFilled(VIEWPORT_POS, BG_POS_MAX, IM_COL32(36.f, 120.f, 12.f, 255.f), 0.f, ImDrawFlags_RoundCornersAll); diff --git a/vita3k/gui/src/settings_dialog.cpp b/vita3k/gui/src/settings_dialog.cpp index fb3703caf2..bbba781c7c 100644 --- a/vita3k/gui/src/settings_dialog.cpp +++ b/vita3k/gui/src/settings_dialog.cpp @@ -96,7 +96,7 @@ static void reset_emulator(GuiState &gui, EmuEnvState &emuenv) { config::serialize_config(emuenv.cfg, emuenv.cfg.config_path); // Clean User apps list - gui.app_selector.user_apps.clear(); + gui.app_selector.vita_apps.clear(); get_modules_list(gui, emuenv); get_sys_apps_title(gui, emuenv); @@ -1027,7 +1027,7 @@ void draw_settings_dialog(GuiState &gui, EmuEnvState &emuenv) { gui.users[emuenv.io.user_id].start_type = "default"; save_user(gui, emuenv, emuenv.io.user_id); init_theme_start_background(gui, emuenv, "default"); - init_apps_icon(gui, emuenv, gui.app_selector.sys_apps); + init_apps_icon(gui, emuenv, gui.app_selector.emu_apps); } ImGui::SameLine(); } diff --git a/vita3k/gui/src/themes.cpp b/vita3k/gui/src/themes.cpp index 76336cb7d9..614b1d9c24 100644 --- a/vita3k/gui/src/themes.cpp +++ b/vita3k/gui/src/themes.cpp @@ -226,7 +226,7 @@ bool init_theme(GuiState &gui, EmuEnvState &emuenv, const std::string &content_i }; // Clear the current theme - gui.app_selector.sys_apps_icon.clear(); + gui.app_selector.emu_apps_icon.clear(); gui.current_theme_bg = 0; gui.information_bar_color = {}; gui.theme_backgrounds.clear(); @@ -342,8 +342,9 @@ bool init_theme(GuiState &gui, EmuEnvState &emuenv, const std::string &content_i const auto &title_id = icon.first; const auto &name = icon.second; + const auto icon_path = fs::path("app") / title_id / "sce_sys/icon0.png"; if (name.empty()) - vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, "app/" + title_id + "/sce_sys/icon0.png"); + vfs::read_file(VitaIoDevice::vs0, buffer, emuenv.pref_path, fs::path("app") / title_id / "sce_sys/icon0.png"); else vfs::read_file(VitaIoDevice::ux0, buffer, emuenv.pref_path, fs::path("theme") / content_id_path / name); @@ -361,7 +362,8 @@ bool init_theme(GuiState &gui, EmuEnvState &emuenv, const std::string &content_i continue; } - gui.app_selector.sys_apps_icon[title_id].init(gui.imgui_state.get(), data, width, height); + const auto app_path = "emu:app/" + title_id; + gui.app_selector.emu_apps_icon[app_path].init(gui.imgui_state.get(), data, width, height); stbi_image_free(data); } diff --git a/vita3k/gui/src/trophy_collection.cpp b/vita3k/gui/src/trophy_collection.cpp index 3a90ef3c71..617b45dfaa 100644 --- a/vita3k/gui/src/trophy_collection.cpp +++ b/vita3k/gui/src/trophy_collection.cpp @@ -413,7 +413,7 @@ void draw_trophy_collection(GuiState &gui, EmuEnvState &emuenv) { const auto TROPHY_PATH{ emuenv.pref_path / "ux0/user" / emuenv.io.user_id / "trophy" }; - const auto is_background = gui.apps_background.contains("NPXS10008"); + const auto BG_PATH = "vs0:app/NPXS10008"; const auto is_12_hour_format = emuenv.cfg.sys_time_format == SCE_SYSTEM_PARAM_TIME_FORMAT_12HOUR; ImGui::SetNextWindowPos(WINDOW_POS, ImGuiCond_Always); @@ -426,8 +426,8 @@ void draw_trophy_collection(GuiState &gui, EmuEnvState &emuenv) { const auto draw_list = ImGui::GetBackgroundDrawList(); const ImVec2 BG_POS_MAX(VIEWPORT_POS.x + VIEWPORT_SIZE.x, VIEWPORT_POS.y + VIEWPORT_SIZE.y); - if (is_background) - draw_list->AddImage(gui.apps_background["NPXS10008"], VIEWPORT_POS, BG_POS_MAX); + if (gui.apps_background.contains(BG_PATH)) + draw_list->AddImage(gui.apps_background[BG_PATH], VIEWPORT_POS, BG_POS_MAX); else draw_list->AddRectFilled(VIEWPORT_POS, BG_POS_MAX, IM_COL32(31.f, 12.f, 0.f, 255.f), 0.f, ImDrawFlags_RoundCornersAll); diff --git a/vita3k/gui/src/user_management.cpp b/vita3k/gui/src/user_management.cpp index 43d8abb60c..f0c906b645 100644 --- a/vita3k/gui/src/user_management.cpp +++ b/vita3k/gui/src/user_management.cpp @@ -204,7 +204,7 @@ static uint32_t current_user_id_selected = 0; static UserMenu menu_selected = SELECT, menu = SELECT; void init_user_management(GuiState &gui, EmuEnvState &emuenv) { - init_app_background(gui, emuenv, "NPXS10013"); + init_app_background(gui, emuenv, "vs0:app/NPXS10013"); gui.vita_area.home_screen = false; gui.vita_area.information_bar = false; gui.vita_area.user_management = true; @@ -485,8 +485,8 @@ void draw_user_management(GuiState &gui, EmuEnvState &emuenv) { ImGui::GetBackgroundDrawList()->AddRectFilled(ImVec2(0.f, 0.f), ImGui::GetIO().DisplaySize, IM_COL32(0.f, 0.f, 0.f, 255.f), 0.f, ImDrawFlags_RoundCornersAll); const ImVec2 WINDOW_POS_MAX(WINDOW_POS.x + WINDOW_SIZE.x, WINDOW_POS.y + WINDOW_SIZE.y); - if (gui.apps_background.contains("NPXS10013")) - ImGui::GetBackgroundDrawList()->AddImage(gui.apps_background["NPXS10013"], WINDOW_POS, WINDOW_POS_MAX); + if (gui.apps_background.contains("vs0:app/NPXS10013")) + ImGui::GetBackgroundDrawList()->AddImage(gui.apps_background["vs0:app/NPXS10013"], WINDOW_POS, WINDOW_POS_MAX); else ImGui::GetBackgroundDrawList()->AddRectFilled(WINDOW_POS, WINDOW_POS_MAX, IM_COL32(10.f, 50.f, 140.f, 255.f), 0.f, ImDrawFlags_RoundCornersAll); diff --git a/vita3k/interface.cpp b/vita3k/interface.cpp index f72f2bbfa3..62d52e366f 100644 --- a/vita3k/interface.cpp +++ b/vita3k/interface.cpp @@ -220,7 +220,7 @@ bool install_archive_content(EmuEnvState &emuenv, GuiState *gui, const ZipPtr &z if (!gui->file_menu.archive_install_dialog && (emuenv.app_info.app_category != "theme")) { gui::update_notice_info(*gui, emuenv, "content"); if ((emuenv.app_info.app_category.find("gd") != std::string::npos) || (emuenv.app_info.app_category.find("gp") != std::string::npos)) { - gui::init_user_app(*gui, emuenv, emuenv.app_info.app_title_id); + gui::init_user_app(*gui, emuenv, "ux0:app/" + emuenv.app_info.app_title_id); gui::save_apps_cache(*gui, emuenv); } } @@ -363,7 +363,7 @@ static bool install_content(EmuEnvState &emuenv, GuiState *gui, const fs::path & LOG_INFO("{} [{}] installed successfully!", emuenv.app_info.app_title, emuenv.app_info.app_title_id); if ((emuenv.app_info.app_category.find("gd") != std::string::npos) || (emuenv.app_info.app_category.find("gp") != std::string::npos)) { - gui::init_user_app(*gui, emuenv, emuenv.app_info.app_title_id); + gui::init_user_app(*gui, emuenv, "ux0:app/" + emuenv.app_info.app_title_id); gui::save_apps_cache(*gui, emuenv); } @@ -446,8 +446,8 @@ static ExitCode load_app_impl(SceUID &main_module_id, EmuEnvState &emuenv) { } // Load main executable - emuenv.self_path = !emuenv.cfg.self_path.empty() ? emuenv.cfg.self_path : EBOOT_PATH; - main_module_id = load_module(emuenv, "app0:" + emuenv.self_path); + emuenv.self_path = !emuenv.cfg.self_path.empty() ? emuenv.cfg.app_device + ":" + emuenv.cfg.self_path : (fs::path(emuenv.io.app_path) / EBOOT_PATH).string(); + main_module_id = load_module(emuenv, emuenv.self_path); if (main_module_id >= 0) { const auto module = emuenv.kernel.loaded_modules[main_module_id]; LOG_INFO("Main executable {} ({}) loaded", module->info.module_name, emuenv.self_path); @@ -465,7 +465,7 @@ static ExitCode load_app_impl(SceUID &main_module_id, EmuEnvState &emuenv) { process_preload_disabled = *preload_disabled_ptr.get(emuenv.mem); } } - const auto module_app_path{ emuenv.pref_path / "ux0/app" / emuenv.io.app_path / "sce_module" }; + const auto module_app_path{ emuenv.pref_path / convert_path(emuenv.io.app_path) / "sce_module" }; std::vector lib_load_list = {}; // todo: check if module is imported @@ -474,7 +474,7 @@ static ExitCode load_app_impl(SceUID &main_module_id, EmuEnvState &emuenv) { if (is_lle_module(name, emuenv)) { const auto module_name_file = fmt::format("{}.suprx", name); if (load_from_app && fs::exists(module_app_path / module_name_file)) - lib_load_list.emplace_back(fmt::format("app0:sce_module/{}", module_name_file)); + lib_load_list.emplace_back(fmt::format("{}/sce_module/{}.suprx", emuenv.io.app_path, name)); else if (fs::exists(emuenv.pref_path / "vs0/sys/external" / module_name_file)) lib_load_list.emplace_back(fmt::format("vs0:sys/external/{}", module_name_file)); } @@ -574,8 +574,8 @@ bool handle_events(EmuEnvState &emuenv, GuiState &gui) { gui.vita_area.app_close = false; }; const auto confirm = [&gui, &emuenv]() { - const auto app_path = gui.vita_area.live_area_screen ? gui.live_area_current_open_apps_list[gui.live_area_app_current_open] : emuenv.app_path; - gui::close_and_run_new_app(gui, emuenv, app_path); + const auto &app_path = gui.vita_area.live_area_screen ? gui.live_area_current_open_apps_list[gui.live_area_app_current_open] : emuenv.app_path; + gui::close_and_run_new_app(emuenv, app_path); }; switch (sce_ctrl_btn) { case SCE_CTRL_CIRCLE: diff --git a/vita3k/io/include/io/functions.h b/vita3k/io/include/io/functions.h index 52ad284eda..d0583d5830 100644 --- a/vita3k/io/include/io/functions.h +++ b/vita3k/io/include/io/functions.h @@ -41,7 +41,8 @@ bool find_case_isens_path(IOState &io, VitaIoDevice &device, const fs::path &tra fs::path find_in_cache(IOState &io, const std::string &system_path); fs::path expand_path(IOState &io, const char *path, const fs::path &pref_path); -std::string translate_path(const char *path, VitaIoDevice &device, const IOState::DevicePaths &device_paths); +std::string convert_path(const std::string &path); +std::string translate_path(const char *path, VitaIoDevice &device, const IOState &io); /** * @brief Copy all directories and files from one location into another diff --git a/vita3k/io/src/io.cpp b/vita3k/io/src/io.cpp index d05a1e296c..47df65b2c6 100644 --- a/vita3k/io/src/io.cpp +++ b/vita3k/io/src/io.cpp @@ -78,7 +78,8 @@ bool read_file(const VitaIoDevice device, FileBuffer &buf, const fs::path &pref_ } bool read_app_file(FileBuffer &buf, const fs::path &pref_path, const std::string &app_path, const fs::path &vfs_file_path) { - return read_file(VitaIoDevice::ux0, buf, pref_path, fs::path("app") / app_path / vfs_file_path); + const auto app_device = device::get_device(app_path); + return read_file(app_device, buf, pref_path, device::remove_device_from_path(app_path, app_device) / vfs_file_path); } SpaceInfo get_space_info(const VitaIoDevice device, const std::string &vfs_path, const fs::path &pref_path) { @@ -134,7 +135,7 @@ bool init(IOState &io, const fs::path &cache_path, const fs::path &log_path, con void init_device_paths(IOState &io) { io.device_paths.savedata0 = "user/" + io.user_id + "/savedata/" + io.savedata; - io.device_paths.app0 = "app/" + io.app_path; + io.device_paths.app0 = device::remove_device_from_path(io.app_path, device::get_device(io.app_path)); io.device_paths.addcont0 = "addcont/" + io.addcont; } @@ -195,7 +196,16 @@ fs::path find_in_cache(IOState &io, const std::string &system_path) { } } -std::string translate_path(const char *path, VitaIoDevice &device, const IOState::DevicePaths &device_paths) { +std::string convert_path(const std::string &path) { + auto convert_path = path; + + // replace colon with slash + string_utils::replace(convert_path, ":", "/"); + + return convert_path; +} + +std::string translate_path(const char *path, VitaIoDevice &device, const IOState &io) { auto relative_path = device::remove_duplicate_device(path, device); // replace invalid slashes with proper forward slash @@ -207,17 +217,17 @@ std::string translate_path(const char *path, VitaIoDevice &device, const IOState switch (device) { case +VitaIoDevice::savedata0: // Redirect savedata0: to ux0:user/00/savedata/ case +VitaIoDevice::savedata1: { - relative_path = device::remove_device_from_path(relative_path, device, device_paths.savedata0); + relative_path = device::remove_device_from_path(relative_path, device, io.device_paths.savedata0); device = VitaIoDevice::ux0; break; } case +VitaIoDevice::app0: { // Redirect app0: to ux0:app/ - relative_path = device::remove_device_from_path(relative_path, device, device_paths.app0); - device = VitaIoDevice::ux0; + relative_path = device::remove_device_from_path(relative_path, device, io.device_paths.app0); + device = device::get_device(io.app_path); break; } case +VitaIoDevice::addcont0: { // Redirect addcont0: to ux0:addcont/ - relative_path = device::remove_device_from_path(relative_path, device, device_paths.addcont0); + relative_path = device::remove_device_from_path(relative_path, device, io.device_paths.addcont0); device = VitaIoDevice::ux0; break; } @@ -279,7 +289,7 @@ std::string translate_path(const char *path, VitaIoDevice &device, const IOState fs::path expand_path(IOState &io, const char *path, const fs::path &pref_path) { auto device = device::get_device(path); - const auto translated_path = translate_path(path, device, io.device_paths); + const auto translated_path = translate_path(path, device, io); return device::construct_emulated_path(device, translated_path, pref_path, io.redirect_stdio).string(); } @@ -307,7 +317,7 @@ SceUID open_file(IOState &io, const char *path, const int flags, const fs::path return fd; } - const auto translated_path = translate_path(path, device, io.device_paths); + const auto translated_path = translate_path(path, device, io); if (translated_path.empty()) { LOG_ERROR("Cannot translate path: {}", path); return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); @@ -496,7 +506,7 @@ int stat_file(IOState &io, const char *file, SceIoStat *statp, const fs::path &p return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); } - const auto translated_path = translate_path(file, device, io.device_paths); + const auto translated_path = translate_path(file, device, io); file_path = device::construct_emulated_path(device, translated_path, pref_path, io.redirect_stdio); if (!fs::exists(file_path)) { @@ -608,7 +618,7 @@ int remove_file(IOState &io, const char *file, const fs::path &pref_path, const return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); } - const auto translated_path = translate_path(file, device, io.device_paths); + const auto translated_path = translate_path(file, device, io); if (translated_path.empty()) { LOG_ERROR("Cannot translate path: {}", translated_path); return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); @@ -640,13 +650,13 @@ int rename(IOState &io, const char *old_name, const char *new_name, const fs::pa return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); } - const auto translated_old_path = translate_path(old_name, device, io.device_paths); + const auto translated_old_path = translate_path(old_name, device, io); if (translated_old_path.empty()) { LOG_ERROR("Cannot translate path: {}", translated_old_path); return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); } - const auto translated_new_path = translate_path(new_name, device, io.device_paths); + const auto translated_new_path = translate_path(new_name, device, io); if (translated_new_path.empty()) { LOG_ERROR("Cannot translate path: {}", translated_new_path); return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); @@ -677,7 +687,7 @@ int rename(IOState &io, const char *old_name, const char *new_name, const fs::pa SceUID open_dir(IOState &io, const char *path, const fs::path &pref_path, const char *export_name) { auto device = device::get_device(path); auto device_for_icase = device; - const auto translated_path = translate_path(path, device, io.device_paths); + const auto translated_path = translate_path(path, device, io); auto dir_path = device::construct_emulated_path(device, translated_path, pref_path, io.redirect_stdio) / ""; if (!fs::exists(dir_path)) { @@ -794,7 +804,7 @@ bool copy_path(const fs::path &src_path, const fs::path &pref_path, const std::s int create_dir(IOState &io, const char *dir, int mode, const fs::path &pref_path, const char *export_name, const bool recursive) { auto device = device::get_device(dir); - const auto translated_path = translate_path(dir, device, io.device_paths); + const auto translated_path = translate_path(dir, device, io); if (translated_path.empty()) { LOG_ERROR("Failed to translate path: {}", dir); return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); @@ -841,7 +851,7 @@ int remove_dir(IOState &io, const char *dir, const fs::path &pref_path, const ch return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); } - const auto translated_path = translate_path(dir, device, io.device_paths); + const auto translated_path = translate_path(dir, device, io); if (translated_path.empty()) { LOG_ERROR("Cannot translate path: {}", dir); return IO_ERROR(SCE_ERROR_ERRNO_ENOENT); diff --git a/vita3k/main.cpp b/vita3k/main.cpp index fdeb2c241b..44ad9ab158 100644 --- a/vita3k/main.cpp +++ b/vita3k/main.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -56,30 +57,31 @@ #include static void run_execv(char *argv[], EmuEnvState &emuenv) { - char const *args[10]; + char const *args[12]; args[0] = argv[0]; args[1] = "-a"; args[2] = "true"; if (!emuenv.load_app_path.empty()) { - args[3] = "-r"; - args[4] = emuenv.load_app_path.data(); + args[3] = "--app-device"; + args[4] = emuenv.load_app_device.data(); + args[5] = "-r"; + args[6] = emuenv.load_app_path.data(); if (!emuenv.load_exec_path.empty()) { - args[5] = "--self"; - args[6] = emuenv.load_exec_path.data(); + args[7] = "--self"; + args[8] = emuenv.load_exec_path.data(); if (!emuenv.load_exec_argv.empty()) { - args[7] = "--app-args"; - args[8] = emuenv.load_exec_argv.data(); - args[9] = nullptr; + args[9] = "--app-args"; + args[10] = emuenv.load_exec_argv.data(); + args[11] = nullptr; } else - args[7] = nullptr; + args[8] = nullptr; } else - args[5] = nullptr; + args[6] = nullptr; } else args[3] = nullptr; // Execute the emulator again with some arguments #ifdef _WIN32 - FreeConsole(); _execv(argv[0], args); #elif defined(__unix__) || defined(__APPLE__) && defined(__MACH__) execv(argv[0], const_cast(args)); @@ -266,7 +268,7 @@ int main(int argc, char *argv[]) { } if (run_type == app::AppRunType::Extracted) { - emuenv.io.app_path = cfg.run_app_path ? *cfg.run_app_path : emuenv.app_info.app_title_id; + emuenv.io.app_path = cfg.app_device + ":app/" + (cfg.run_app_path ? *cfg.run_app_path : emuenv.app_info.app_title_id); gui::init_user_app(gui, emuenv, emuenv.io.app_path); if (emuenv.cfg.run_app_path.has_value()) emuenv.cfg.run_app_path.reset(); @@ -324,7 +326,8 @@ int main(int argc, char *argv[]) { // When backend render is changed before boot app, reboot emu in new backend render and run app if (emuenv.renderer->current_backend != emuenv.backend_renderer) { - emuenv.load_app_path = emuenv.io.app_path; + emuenv.load_app_device = device::get_device(emuenv.io.app_path)._to_string(); + emuenv.load_app_path = fs::path(emuenv.io.app_path).stem().string(); run_execv(argv, emuenv); return Success; } diff --git a/vita3k/modules/SceCommonDialog/SceCommonDialog.cpp b/vita3k/modules/SceCommonDialog/SceCommonDialog.cpp index f4a3eb53cf..38be9510ce 100644 --- a/vita3k/modules/SceCommonDialog/SceCommonDialog.cpp +++ b/vita3k/modules/SceCommonDialog/SceCommonDialog.cpp @@ -825,7 +825,7 @@ static void check_empty_param(EmuEnvState &emuenv, const SceAppUtilSaveDataSlotE vfs::FileBuffer thumbnail_buffer; if (iconPath) { auto device = device::get_device(empty_param->iconPath.get(emuenv.mem)); - auto thumbnail_path = translate_path(empty_param->iconPath.get(emuenv.mem), device, emuenv.io.device_paths); + auto thumbnail_path = translate_path(empty_param->iconPath.get(emuenv.mem), device, emuenv.io); vfs::read_file(VitaIoDevice::ux0, thumbnail_buffer, emuenv.pref_path, thumbnail_path); emuenv.common_dialog.savedata.icon_buffer[idx] = thumbnail_buffer; } else if (iconBuf && iconBufSize != 0) { @@ -853,7 +853,7 @@ static void check_save_file(const uint32_t index, EmuEnvState &emuenv, const cha emuenv.common_dialog.savedata.date[index] = slot_param.modifiedTime; emuenv.common_dialog.savedata.has_date[index] = true; auto device = device::get_device(slot_param.iconPath); - auto thumbnail_path = translate_path(slot_param.iconPath, device, emuenv.io.device_paths); + auto thumbnail_path = translate_path(slot_param.iconPath, device, emuenv.io); vfs::read_file(device, thumbnail_buffer, emuenv.pref_path, thumbnail_path); emuenv.common_dialog.savedata.icon_buffer[index] = thumbnail_buffer; emuenv.common_dialog.savedata.icon_texture[index] = {}; diff --git a/vita3k/modules/module_parent.cpp b/vita3k/modules/module_parent.cpp index b8e7bbf8ce..0d29c3a133 100644 --- a/vita3k/modules/module_parent.cpp +++ b/vita3k/modules/module_parent.cpp @@ -185,10 +185,9 @@ SceUID load_module(EmuEnvState &emuenv, const std::string &module_path) { LOG_INFO("Loading module \"{}\"", module_path); vfs::FileBuffer module_buffer; - bool res; VitaIoDevice device = device::get_device(module_path); auto device_for_icase = device; - fs::path translated_module_path = translate_path(module_path.c_str(), device, emuenv.io.device_paths); + fs::path translated_module_path = translate_path(module_path.c_str(), device, emuenv.io); auto system_path = device::construct_emulated_path(device, translated_module_path, emuenv.pref_path, emuenv.io.redirect_stdio); if (emuenv.io.case_isens_find_enabled && !fs::exists(system_path)) { @@ -212,11 +211,7 @@ SceUID load_module(EmuEnvState &emuenv, const std::string &module_path) { } } - if (device == VitaIoDevice::app0) - res = vfs::read_app_file(module_buffer, emuenv.pref_path, emuenv.io.app_path, translated_module_path); - else - res = vfs::read_file(device, module_buffer, emuenv.pref_path, translated_module_path); - if (!res) { + if (!vfs::read_file(device, module_buffer, emuenv.pref_path, translated_module_path)) { LOG_ERROR("Failed to read module file {}", module_path); return SCE_ERROR_ERRNO_ENOENT; } diff --git a/vita3k/packages/src/exfat.cpp b/vita3k/packages/src/exfat.cpp index 8a4dddf4ab..e7ecafb593 100644 --- a/vita3k/packages/src/exfat.cpp +++ b/vita3k/packages/src/exfat.cpp @@ -17,6 +17,8 @@ #include +#include + namespace exfat { static std::string get_exfat_file_name(fs::ifstream &img, uint8_t continuations) { @@ -172,6 +174,10 @@ void extract_exfat(const fs::path &partition_path, const std::string &partition, // Close the partition file img.close(); + + fs::ofstream work_bin_file(output_path / "app/NPXS10007/sce_sys/package/work.bin", std::ios::out | std::ios::binary); + zrif2rif("KO5ifR1dg/J5YXzPMLCpfgERwYYgV4HsD3f1cfb3dQ1wDPI2MDQyNsHnv97zVkrdJx8wVzy+Ktc05XHqaIwPbgAAckoVWgAA", work_bin_file); + work_bin_file.close(); } } // namespace exfat