diff --git a/rpcs3/Emu/system_utils.cpp b/rpcs3/Emu/system_utils.cpp index ba98a44795..e840887bac 100644 --- a/rpcs3/Emu/system_utils.cpp +++ b/rpcs3/Emu/system_utils.cpp @@ -101,6 +101,48 @@ namespace rpcs3::utils return worker(); } + std::vector> get_vfs_disk_usage() + { + std::vector> disk_usage; + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_hdd0_dir(), 1); data_size != umax) + { + disk_usage.push_back({"dev_hdd0", data_size}); + } + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_hdd1_dir(), 1); data_size != umax) + { + disk_usage.push_back({"dev_hdd1", data_size}); + } + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_flash_dir(), 1); data_size != umax) + { + disk_usage.push_back({"dev_flash", data_size}); + } + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_flash2_dir(), 1); data_size != umax) + { + disk_usage.push_back({"dev_flash2", data_size}); + } + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_flash3_dir(), 1); data_size != umax) + { + disk_usage.push_back({"dev_flash3", data_size}); + } + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_bdvd_dir(), 1); data_size != umax) + { + disk_usage.push_back({"dev_bdvd", data_size}); + } + + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_games_dir(), 1); data_size != umax) + { + disk_usage.push_back({"games", data_size}); + } + + return disk_usage; + } + std::string get_emu_dir() { const std::string& emu_dir_ = g_cfg_vfs.emulator_dir; @@ -122,6 +164,36 @@ namespace rpcs3::utils return g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, get_emu_dir()); } + std::string get_flash_dir() + { + return g_cfg_vfs.get(g_cfg_vfs.dev_flash, get_emu_dir()); + } + + std::string get_flash2_dir() + { + return g_cfg_vfs.get(g_cfg_vfs.dev_flash2, get_emu_dir()); + } + + std::string get_flash3_dir() + { + return g_cfg_vfs.get(g_cfg_vfs.dev_flash3, get_emu_dir()); + } + + std::string get_bdvd_dir() + { + return g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, get_emu_dir()); + } + + u64 get_cache_disk_usage() + { + if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_cache_dir(), 1); data_size != umax) + { + return data_size; + } + + return 0; + } + std::string get_cache_dir() { return fs::get_cache_dir() + "cache/"; diff --git a/rpcs3/Emu/system_utils.hpp b/rpcs3/Emu/system_utils.hpp index 30ccb0add0..b4142dacb9 100644 --- a/rpcs3/Emu/system_utils.hpp +++ b/rpcs3/Emu/system_utils.hpp @@ -23,10 +23,19 @@ namespace rpcs3::utils bool install_pkg(const std::string& path); + // VFS directories and disk usage + std::vector> get_vfs_disk_usage(); std::string get_emu_dir(); std::string get_games_dir(); std::string get_hdd0_dir(); std::string get_hdd1_dir(); + std::string get_flash_dir(); + std::string get_flash2_dir(); + std::string get_flash3_dir(); + std::string get_bdvd_dir(); + + // Cache directories and disk usage + u64 get_cache_disk_usage(); std::string get_cache_dir(); std::string get_cache_dir(std::string_view module_path); diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index 4dd664a99e..a155cf215d 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -4,10 +4,14 @@ #include "hex_validator.h" #include "memory_viewer_panel.h" +#include "Emu/System.h" +#include "Emu/system_utils.hpp" #include "Utilities/lockless.h" #include "util/asm.hpp" +#include #include +#include #include #include #include @@ -17,6 +21,8 @@ #include #include +LOG_CHANNEL(sys_log, "SYS"); + extern fs::file g_tty; extern atomic_t g_tty_size; extern std::array, 16> g_tty_input; @@ -165,6 +171,28 @@ log_frame::log_frame(std::shared_ptr _gui_settings, QWidget* paren connect(m_timer, &QTimer::timeout, this, &log_frame::UpdateUI); } +void log_frame::show_disk_usage(const std::vector>& vfs_disk_usage, u64 cache_disk_usage) +{ + QString text; + u64 tot_data_size = 0; + + for (const auto& [dev, data_size] : vfs_disk_usage) + { + text += tr("\n %0: %1").arg(QString::fromStdString(dev)).arg(gui::utils::format_byte_size(data_size)); + tot_data_size += data_size; + } + + if (!text.isEmpty()) + { + text = tr("\n VFS disk usage: %0%1").arg(gui::utils::format_byte_size(tot_data_size)).arg(text); + } + + text += tr("\n Cache disk usage: %0").arg(gui::utils::format_byte_size(cache_disk_usage)); + + sys_log.success("%s", text); + QMessageBox::information(this, tr("Disk usage"), text); +} + void log_frame::SetLogLevel(logs::level lev) const { switch (lev) @@ -245,6 +273,26 @@ void log_frame::CreateAndConnectActions() m_tty->clear(); }); + m_show_disk_usage_act = new QAction(tr("Show Disk Usage"), this); + connect(m_show_disk_usage_act, &QAction::triggered, [this]() + { + if (m_disk_usage_future.isRunning()) + { + return; // Still running the last request + } + + m_disk_usage_future = QtConcurrent::run([this]() + { + const std::vector> vfs_disk_usage = rpcs3::utils::get_vfs_disk_usage(); + const u64 cache_disk_usage = rpcs3::utils::get_cache_disk_usage(); + + Emu.CallFromMainThread([this, vfs_disk_usage, cache_disk_usage]() + { + show_disk_usage(vfs_disk_usage, cache_disk_usage); + }, nullptr, false); + }); + }); + m_perform_goto_on_debugger = new QAction(tr("Go-To On The Debugger"), this); connect(m_perform_goto_on_debugger, &QAction::triggered, [this]() { @@ -369,6 +417,9 @@ void log_frame::CreateAndConnectActions() { QMenu* menu = m_log->createStandardContextMenu(); menu->addAction(m_clear_act); + menu->addSeparator(); + menu->addAction(m_show_disk_usage_act); + menu->addSeparator(); menu->addAction(m_perform_goto_on_debugger); menu->addAction(m_perform_goto_thread_on_debugger); menu->addAction(m_perform_show_in_mem_viewer); diff --git a/rpcs3/rpcs3qt/log_frame.h b/rpcs3/rpcs3qt/log_frame.h index 0de081863c..159fdd38aa 100644 --- a/rpcs3/rpcs3qt/log_frame.h +++ b/rpcs3/rpcs3qt/log_frame.h @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -38,6 +39,7 @@ protected: private Q_SLOTS: void UpdateUI(); private: + void show_disk_usage(const std::vector>& vfs_disk_usage, u64 cache_disk_usage); void SetLogLevel(logs::level lev) const; void SetTTYLogging(bool val) const; @@ -48,6 +50,7 @@ private: std::unique_ptr m_find_dialog; QTimer* m_timer = nullptr; + QFuture m_disk_usage_future; std::vector m_color; QColor m_color_stack; @@ -72,6 +75,7 @@ private: QAction* m_clear_act = nullptr; QAction* m_clear_tty_act = nullptr; + QAction* m_show_disk_usage_act = nullptr; QAction* m_perform_goto_on_debugger = nullptr; QAction* m_perform_goto_thread_on_debugger = nullptr; QAction* m_perform_show_in_mem_viewer = nullptr;