1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-21 18:22:33 +01:00

overlays: localize RPCS3 progress dialog

This commit is contained in:
Megamouse 2024-11-15 03:24:03 +01:00
parent 070add461f
commit 7866dc2e34
8 changed files with 100 additions and 53 deletions

View File

@ -6,6 +6,7 @@
#include "Crypto/unself.h"
#include "Loader/ELF.h"
#include "Loader/mself.hpp"
#include "Emu/localized_string.h"
#include "Emu/perf_meter.hpp"
#include "Emu/Memory/vm_reservation.h"
#include "Emu/Memory/vm_locking.h"
@ -3862,7 +3863,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
return;
}
std::optional<scoped_progress_dialog> progr(std::in_place, "Scanning PPU Executable...");
std::optional<scoped_progress_dialog> progress_dialog(std::in_place, get_localized_string(localized_string_id::PROGRESS_DIALOG_SCANNING_PPU_EXECUTABLE));
// Make sure we only have one '/' at the end and remove duplicates.
for (std::string& dir : dir_queue)
@ -4063,7 +4064,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
g_progr_ftotal_bits += total_files_size;
*progr = "Compiling PPU Modules...";
*progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_COMPILING_PPU_MODULES);
atomic_t<usz> fnext = 0;
@ -4380,7 +4381,7 @@ extern void ppu_initialize()
auto& _main = g_fxo->get<main_ppu_module>();
std::optional<scoped_progress_dialog> progr(std::in_place, "Analyzing PPU Executable...");
std::optional<scoped_progress_dialog> progress_dialog(std::in_place, get_localized_string(localized_string_id::PROGRESS_DIALOG_ANALYZING_PPU_EXECUTABLE));
// Analyse executable
if (!_main.analyse(0, _main.elf_entry, _main.seg0_code_end, _main.applied_patches, std::vector<u32>{}, [](){ return Emu.IsStopped(); }))
@ -4391,7 +4392,7 @@ extern void ppu_initialize()
// Validate analyser results (not required)
_main.validate(0);
*progr = "Scanning PPU Modules...";
*progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_SCANNING_PPU_MODULES);
bool compile_main = false;
@ -4479,7 +4480,7 @@ extern void ppu_initialize()
dir_queue.insert(std::end(dir_queue), std::begin(dirs), std::end(dirs));
}
progr.reset();
progress_dialog.reset();
ppu_precompile(dir_queue, &module_list);
@ -4612,12 +4613,12 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
}
#ifdef LLVM_AVAILABLE
std::optional<scoped_progress_dialog> progr;
std::optional<scoped_progress_dialog> progress_dialog;
if (!check_only)
{
// Initialize progress dialog
progr.emplace("Loading PPU Modules...");
progress_dialog.emplace(get_localized_string(localized_string_id::PROGRESS_DIALOG_LOADING_PPU_MODULES));
}
// Permanently loaded compiled PPU modules (name -> data)
@ -4983,7 +4984,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
// Create worker threads for compilation
if (!workload.empty())
{
*progr = "Compiling PPU Modules...";
*progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_COMPILING_PPU_MODULES);
u32 thread_count = rpcs3::utils::get_max_threads();
@ -5096,7 +5097,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
if (workload.size() < link_workload.size())
{
// Only show this message if this task is relevant
*progr = "Linking PPU Modules...";
*progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_LINKING_PPU_MODULES);
}
for (const auto& [obj_name, is_compiled] : link_workload)
@ -5142,9 +5143,9 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
// Try to patch all single and unregistered BLRs with the same function (TODO: Maybe generalize it into PIC code detection and patching)
ppu_intrp_func_t BLR_func = nullptr;
const bool showing_only_apply_stage = !g_progr.load() && !g_progr_ptotal && !g_progr_ftotal && g_progr_ptotal.compare_and_swap_test(0, 1);
const bool showing_only_apply_stage = !g_progr_text.load() && !g_progr_ptotal && !g_progr_ftotal && g_progr_ptotal.compare_and_swap_test(0, 1);
progr = "Applying PPU Code...";
progress_dialog = get_localized_string(localized_string_id::PROGRESS_DIALOG_APPLYING_PPU_CODE);
if (!jit)
{

View File

@ -7,6 +7,7 @@
#include "Emu/system_utils.hpp"
#include "Emu/cache_utils.hpp"
#include "Emu/IdManager.h"
#include "Emu/localized_string.h"
#include "Crypto/sha1.h"
#include "Utilities/StrUtil.h"
#include "Utilities/JIT.h"
@ -804,7 +805,7 @@ void spu_cache::initialize(bool build_existing_cache)
u32 worker_count = 0;
std::optional<scoped_progress_dialog> progr;
std::optional<scoped_progress_dialog> progress_dialog;
u32 total_funcs = 0;
@ -827,7 +828,7 @@ void spu_cache::initialize(bool build_existing_cache)
{
g_progr_ptotal += total_funcs;
showing_progress.release(true);
progr.emplace("Building SPU cache...");
progress_dialog.emplace(get_localized_string(localized_string_id::PROGRESS_DIALOG_BUILDING_SPU_CACHE));
}
named_thread_group workers("SPU Worker ", worker_count, [&]() -> uint
@ -937,12 +938,12 @@ void spu_cache::initialize(bool build_existing_cache)
if (is_first_thread && !showing_progress)
{
if (!g_progr.load() && !g_progr_ptotal && !g_progr_ftotal)
if (!g_progr_text.load() && !g_progr_ptotal && !g_progr_ftotal)
{
showing_progress = true;
g_progr_pdone += pending_progress.exchange(0);
g_progr_ptotal += total_funcs;
progr.emplace("Building SPU cache...");
progress_dialog.emplace(get_localized_string(localized_string_id::PROGRESS_DIALOG_BUILDING_SPU_CACHE));
}
}
else if (showing_progress && pending_progress)
@ -1114,12 +1115,13 @@ void spu_cache::initialize(bool build_existing_cache)
if (is_first_thread && !showing_progress)
{
if (!g_progr.load() && !g_progr_ptotal && !g_progr_ftotal)
if (!g_progr_text.load() && !g_progr_ptotal && !g_progr_ftotal)
{
showing_progress = true;
g_progr_pdone += pending_progress.exchange(0);
g_progr_ptotal += total_funcs;
progr.emplace("Building SPU cache...");
progress_dialog.emplace(get_localized_string(localized_string_id::PROGRESS_DIALOG_BUILDING_SPU_CACHE));
}
}
else if (showing_progress && pending_progress)

View File

@ -3111,7 +3111,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
{
// Show visual feedback to the user in case that stopping takes a while.
// This needs to be done before actually stopping, because otherwise the necessary threads will be terminated before we can show an image.
if (auto progress_dialog = g_fxo->try_get<named_thread<progress_dialog_server>>(); progress_dialog && g_progr.load())
if (auto progress_dialog = g_fxo->try_get<named_thread<progress_dialog_server>>(); progress_dialog && g_progr_text.load())
{
// We are currently showing a progress dialog. Notify it that we are going to stop emulation.
g_system_progress_stopping = true;

View File

@ -269,6 +269,24 @@ enum class localized_string_id
HOME_MENU_RELOAD_SAVESTATE,
HOME_MENU_RECORDING,
PROGRESS_DIALOG_PROGRESS,
PROGRESS_DIALOG_PROGRESS_ANALYZING,
PROGRESS_DIALOG_REMAINING,
PROGRESS_DIALOG_DONE,
PROGRESS_DIALOG_FILE,
PROGRESS_DIALOG_MODULE,
PROGRESS_DIALOG_OF,
PROGRESS_DIALOG_PLEASE_WAIT,
PROGRESS_DIALOG_STOPPING_PLEASE_WAIT,
PROGRESS_DIALOG_SCANNING_PPU_EXECUTABLE,
PROGRESS_DIALOG_ANALYZING_PPU_EXECUTABLE,
PROGRESS_DIALOG_SCANNING_PPU_MODULES,
PROGRESS_DIALOG_LOADING_PPU_MODULES,
PROGRESS_DIALOG_COMPILING_PPU_MODULES,
PROGRESS_DIALOG_LINKING_PPU_MODULES,
PROGRESS_DIALOG_APPLYING_PPU_CODE,
PROGRESS_DIALOG_BUILDING_SPU_CACHE,
EMULATION_PAUSED_RESUME_WITH_START,
EMULATION_RESUMING,
EMULATION_FROZEN,

View File

@ -13,7 +13,7 @@
LOG_CHANNEL(sys_log, "SYS");
// Progress display server synchronization variables
atomic_t<progress_dialog_string_t> g_progr{};
atomic_t<progress_dialog_string_t> g_progr_text{};
atomic_t<u32> g_progr_ftotal{0};
atomic_t<u32> g_progr_fdone{0};
atomic_t<u64> g_progr_ftotal_bits{0};
@ -43,11 +43,11 @@ void progress_dialog_server::operator()()
const auto get_state = []()
{
auto whole_state = std::make_tuple(+g_progr.load(), +g_progr_ftotal, +g_progr_fdone, +g_progr_ftotal_bits, +g_progr_fknown_bits, +g_progr_ptotal, +g_progr_pdone);
auto whole_state = std::make_tuple(+g_progr_text.load(), +g_progr_ftotal, +g_progr_fdone, +g_progr_ftotal_bits, +g_progr_fknown_bits, +g_progr_ptotal, +g_progr_pdone);
while (true)
{
auto new_state = std::make_tuple(+g_progr.load(), +g_progr_ftotal, +g_progr_fdone, +g_progr_ftotal_bits, +g_progr_fknown_bits, +g_progr_ptotal, +g_progr_pdone);
auto new_state = std::make_tuple(+g_progr_text.load(), +g_progr_ftotal, +g_progr_fdone, +g_progr_ftotal_bits, +g_progr_fknown_bits, +g_progr_ptotal, +g_progr_pdone);
if (new_state == whole_state)
{
@ -64,7 +64,7 @@ void progress_dialog_server::operator()()
while (!g_system_progress_stopping && thread_ctrl::state() != thread_state::aborting)
{
// Wait for the start condition
const char* text0 = g_progr.load();
const char* text0 = g_progr_text.load();
while (!text0)
{
@ -97,7 +97,7 @@ void progress_dialog_server::operator()()
}
thread_ctrl::wait_for(5000);
text0 = g_progr.load();
text0 = g_progr_text.load();
}
if (g_system_progress_stopping || thread_ctrl::state() == thread_state::aborting)
@ -131,7 +131,7 @@ void progress_dialog_server::operator()()
native_dlg = manager->create<rsx::overlays::progress_dialog>(true);
native_dlg->show(false, text0, type, msg_dialog_source::sys_progress, nullptr);
native_dlg->progress_bar_set_message(0, "Please wait");
native_dlg->progress_bar_set_message(0, get_localized_string(localized_string_id::PROGRESS_DIALOG_PLEASE_WAIT));
}
}
@ -250,14 +250,16 @@ void progress_dialog_server::operator()()
const u64 done = pdone;
const u32 value = static_cast<u32>(done >= total ? 100 : done * 100 / total);
std::string progr = "Progress:";
std::string progr;
if (ftotal || ptotal)
{
progr = get_localized_string(localized_string_id::PROGRESS_DIALOG_PROGRESS);
if (ftotal)
fmt::append(progr, " file %u of %u%s", fdone, ftotal, ptotal ? "," : "");
fmt::append(progr, " %s %u %s %u%s", get_localized_string(localized_string_id::PROGRESS_DIALOG_FILE), fdone, get_localized_string(localized_string_id::PROGRESS_DIALOG_OF), ftotal, ptotal ? "," : "");
if (ptotal)
fmt::append(progr, " module %u of %u", pdone, ptotal);
fmt::append(progr, " %s %u %s %u", get_localized_string(localized_string_id::PROGRESS_DIALOG_MODULE), pdone, get_localized_string(localized_string_id::PROGRESS_DIALOG_OF), ptotal);
const u32 of_1000 = static_cast<u32>(done >= total ? 1000 : done * 1000 / total);
@ -303,29 +305,29 @@ void progress_dialog_server::operator()()
}
else if (done >= total)
{
fmt::append(progr, " (done)", minutes, seconds);
fmt::append(progr, " (%s)", get_localized_string(localized_string_id::PROGRESS_DIALOG_DONE));
}
else if (hours)
{
fmt::append(progr, " (%uh %2um remaining)", hours, minutes);
fmt::append(progr, " (%uh %2um %s)", hours, minutes, get_localized_string(localized_string_id::PROGRESS_DIALOG_REMAINING));
}
else if (minutes >= 2)
{
fmt::append(progr, " (%um remaining)", minutes);
fmt::append(progr, " (%um %s)", minutes, get_localized_string(localized_string_id::PROGRESS_DIALOG_REMAINING));
}
else if (minutes == 0)
{
fmt::append(progr, " (%us remaining)", std::max<u64>(seconds, 1));
fmt::append(progr, " (%us %s)", std::max<u64>(seconds, 1), get_localized_string(localized_string_id::PROGRESS_DIALOG_REMAINING));
}
else
{
fmt::append(progr, " (%um %2us remaining)", minutes, seconds);
fmt::append(progr, " (%um %2us %s)", minutes, seconds, get_localized_string(localized_string_id::PROGRESS_DIALOG_REMAINING));
}
}
}
else
{
fmt::append(progr, " analyzing...");
progr = get_localized_string(localized_string_id::PROGRESS_DIALOG_PROGRESS_ANALYZING);
}
// Changes detected, send update
@ -409,7 +411,7 @@ void progress_dialog_server::operator()()
if (native_dlg && g_system_progress_stopping)
{
native_dlg->set_text("Stopping. Please wait...");
native_dlg->set_text(get_localized_string(localized_string_id::PROGRESS_DIALOG_STOPPING_PLEASE_WAIT));
native_dlg->refresh();
}
@ -427,5 +429,5 @@ progress_dialog_server::~progress_dialog_server()
g_progr_fknown_bits.release(0);
g_progr_ptotal.release(0);
g_progr_pdone.release(0);
g_progr.release(progress_dialog_string_t{});
g_progr_text.release(progress_dialog_string_t{});
}

View File

@ -15,7 +15,7 @@ struct alignas(16) progress_dialog_string_t
}
};
extern atomic_t<progress_dialog_string_t> g_progr;
extern atomic_t<progress_dialog_string_t> g_progr_text;
extern atomic_t<u32> g_progr_ftotal;
extern atomic_t<u32> g_progr_fdone;
extern atomic_t<u64> g_progr_ftotal_bits;
@ -28,23 +28,27 @@ extern atomic_t<bool> g_system_progress_stopping;
// Initialize progress dialog (can be recursive)
class scoped_progress_dialog final
{
// Saved previous value
const char* m_prev;
private:
std::string m_text; // Saved current value
std::string m_prev; // Saved previous value
u32 m_prev_id;
u32 m_id;
public:
scoped_progress_dialog(const char* text) noexcept
scoped_progress_dialog(const std::string& text) noexcept
{
std::tie(m_prev, m_prev_id, m_id) = g_progr.atomic_op([text = ensure(text)](progress_dialog_string_t& progr)
ensure(!text.empty());
m_text = text;
std::tie(m_prev, m_prev_id, m_id) = g_progr_text.atomic_op([this](progress_dialog_string_t& progr)
{
const char* old = progr.m_text;
std::string old = progr.m_text ? progr.m_text : std::string();
progr.m_user_count++;
progr.m_update_id++;
progr.m_text = text;
progr.m_text = m_text.c_str();
ensure(progr.m_user_count > 1 || !old); // Ensure it was nullptr before first use
return std::make_tuple(old, progr.m_update_id - 1, progr.m_update_id);
ensure(progr.m_user_count > 1 || old.empty()); // Ensure it was empty before first use
return std::make_tuple(std::move(old), progr.m_update_id - 1, progr.m_update_id);
});
}
@ -52,23 +56,26 @@ public:
scoped_progress_dialog& operator=(const scoped_progress_dialog&) = delete;
scoped_progress_dialog& operator=(const char* text) noexcept
scoped_progress_dialog& operator=(const std::string& text) noexcept
{
ensure(!text.empty());
m_text = text;
// This method is destroying the previous value and replacing it with a new one
std::tie(m_prev, m_prev_id, m_id) = g_progr.atomic_op([this, text = ensure(text)](progress_dialog_string_t& progr)
std::tie(m_prev, m_prev_id, m_id) = g_progr_text.atomic_op([this](progress_dialog_string_t& progr)
{
if (m_id == progr.m_update_id)
{
progr.m_update_id = m_prev_id;
progr.m_text = m_prev;
progr.m_text = m_prev.c_str();
}
const char* old = progr.m_text;
progr.m_text = text;
std::string old = progr.m_text ? progr.m_text : std::string();
progr.m_text = m_text.c_str();
progr.m_update_id++;
ensure(progr.m_user_count > 0);
return std::make_tuple(old, progr.m_update_id - 1, progr.m_update_id);
return std::make_tuple(std::move(old), progr.m_update_id - 1, progr.m_update_id);
});
return *this;
@ -76,7 +83,7 @@ public:
~scoped_progress_dialog() noexcept
{
g_progr.atomic_op([this](progress_dialog_string_t& progr)
g_progr_text.atomic_op([this](progress_dialog_string_t& progr)
{
if (progr.m_user_count-- == 1)
{
@ -87,7 +94,7 @@ public:
else if (m_id == progr.m_update_id)
{
// Restore text only if no other updates were made by other threads
progr.m_text = ensure(m_prev);
progr.m_text = m_prev.c_str();
progr.m_update_id = m_prev_id;
}
});

View File

@ -568,7 +568,7 @@ void gs_frame::hide_on_close()
m_gui_settings->SetValue(gui::gs_visibility, current_visibility == Visibility::Hidden ? Visibility::AutomaticVisibility : current_visibility, false);
m_gui_settings->SetValue(gui::gs_geometry, geometry(), true);
if (!g_progr.load())
if (!g_progr_text.load())
{
// Hide the dialog before stopping if no progress bar is being shown.
// Otherwise users might think that the game softlocked if stopping takes too long.

View File

@ -289,6 +289,23 @@ private:
case localized_string_id::HOME_MENU_SAVESTATE_AND_EXIT: return tr("Save Emulation State And Exit");
case localized_string_id::HOME_MENU_RELOAD_SAVESTATE: return tr("Reload Last Emulation State");
case localized_string_id::HOME_MENU_RECORDING: return tr("Start/Stop Recording");
case localized_string_id::PROGRESS_DIALOG_PROGRESS: return tr("Progress:");
case localized_string_id::PROGRESS_DIALOG_PROGRESS_ANALYZING: return tr("Progress: analyzing...");
case localized_string_id::PROGRESS_DIALOG_REMAINING: return tr("remaining");
case localized_string_id::PROGRESS_DIALOG_DONE: return tr("done");
case localized_string_id::PROGRESS_DIALOG_FILE: return tr("file");
case localized_string_id::PROGRESS_DIALOG_MODULE: return tr("module");
case localized_string_id::PROGRESS_DIALOG_OF: return tr("of");
case localized_string_id::PROGRESS_DIALOG_PLEASE_WAIT: return tr("Please wait");
case localized_string_id::PROGRESS_DIALOG_STOPPING_PLEASE_WAIT: return tr("Stopping. Please wait...");
case localized_string_id::PROGRESS_DIALOG_SCANNING_PPU_EXECUTABLE: return tr("Scanning PPU Executable...");
case localized_string_id::PROGRESS_DIALOG_ANALYZING_PPU_EXECUTABLE: return tr("Analyzing PPU Executable...");
case localized_string_id::PROGRESS_DIALOG_SCANNING_PPU_MODULES: return tr("Scanning PPU Modules...");
case localized_string_id::PROGRESS_DIALOG_LOADING_PPU_MODULES: return tr("Loading PPU Modules...");
case localized_string_id::PROGRESS_DIALOG_COMPILING_PPU_MODULES: return tr("Compiling PPU Modules...");
case localized_string_id::PROGRESS_DIALOG_LINKING_PPU_MODULES: return tr("Linking PPU Modules...");
case localized_string_id::PROGRESS_DIALOG_APPLYING_PPU_CODE: return tr("Applying PPU Code...");
case localized_string_id::PROGRESS_DIALOG_BUILDING_SPU_CACHE: return tr("Building SPU Cache...");
case localized_string_id::EMULATION_PAUSED_RESUME_WITH_START: return tr("Press and hold the START button to resume");
case localized_string_id::EMULATION_RESUMING: return tr("Resuming...!");
case localized_string_id::EMULATION_FROZEN: return tr("The PS3 application has likely crashed, you can close it.");