diff --git a/rpcs3/Emu/Cell/ErrorCodes.h b/rpcs3/Emu/Cell/ErrorCodes.h index 15e8a1fc3e3d..5817211187fc 100644 --- a/rpcs3/Emu/Cell/ErrorCodes.h +++ b/rpcs3/Emu/Cell/ErrorCodes.h @@ -12,25 +12,28 @@ class error_code error_code() = default; // Implementation must be provided independently - static s32 error_report(s32 result, const char* fmt, const fmt_type_info* sup, const u64* args); + static s32 make_report(s32 result, const char* fmt, const fmt_type_info* sup, const u64* args); + static void log_report(); + static void set_report_as_warning(); + bool silence_report(); // Common constructor template - error_code(const ET& value) + error_code(const ET& value) noexcept : value(error_report(static_cast(value), " : %s", fmt::type_info_v, fmt_args_t{fmt_unveil::get(value)})) { } // Error constructor (2 args) template - error_code(const ET& value, const T& arg) + error_code(const ET& value, const T& arg) noexcept : value(error_report(static_cast(value), " : %s, %s", fmt::type_info_v, fmt_args_t{fmt_unveil::get(value), fmt_unveil::get(arg)})) { } // Formatting constructor (error, format string, variadic list) template requires (sizeof...(Args) > 0) - error_code(const ET& value, const const_str& fmt, const Args&... args) + error_code(const ET& value, const const_str& fmt, const Args&... args) noexcept : value(error_report(static_cast(value), fmt, fmt::type_info_v, fmt_args_t{fmt_unveil::get(args)...})) { } @@ -71,6 +74,7 @@ struct ppu_gpr_cast_impl { static inline u64 to(const error_code& code) { + error_code::log_report(); return code; } diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index ff533d5cb0eb..f09ca31cac3e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -945,6 +945,11 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr path, s32 flags, vm::ptr< return not_an_error(CELL_EEXIST); } + if (error == CELL_ENOENT && lv2_fs_object::get_mp(vpath) == &g_mp_sys_dev_hdd1) + { + error_code::set_report_as_warning(); + } + return {error, path}; } @@ -1246,6 +1251,11 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr path, vm::ptr fd) { if (ext.empty()) { + if (lv2_fs_object::get_mp(vpath) == &g_mp_sys_dev_hdd1) + { + error_code::set_report_as_warning(); + } + return {CELL_ENOENT, path}; } @@ -1435,6 +1445,11 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr path, vm::ptr break; } + if (lv2_fs_object::get_mp(vpath) == &g_mp_sys_dev_hdd1) + { + error_code::set_report_as_warning(); + } + return {CELL_ENOENT, path}; } default: @@ -1563,8 +1578,20 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr path, s32 mode) { switch (auto error = fs::g_tls_error) { - case fs::error::noent: return {CELL_ENOENT, path}; - case fs::error::exist: return {CELL_EEXIST, path}; + case fs::error::noent: + { + if (mp == &g_mp_sys_dev_hdd1) + { + error_code::set_report_as_warning(); + } + + return {CELL_ENOENT, path}; + } + case fs::error::exist: + { + error_code::set_report_as_warning(); + return {CELL_EEXIST, path}; + } default: sys_fs.error("sys_fs_mkdir(): unknown error %s", error); } @@ -1737,7 +1764,15 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr path) { switch (auto error = fs::g_tls_error) { - case fs::error::noent: return {CELL_ENOENT, path}; + case fs::error::noent: + { + if (mp == &g_mp_sys_dev_hdd1) + { + error_code::set_report_as_warning(); + } + + return {CELL_ENOENT, path}; + } default: sys_fs.error("sys_fs_unlink(): unknown error %s", error); } @@ -2690,7 +2725,15 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr path, u64 size) { switch (auto error = fs::g_tls_error) { - case fs::error::noent: return {CELL_ENOENT, path}; + case fs::error::noent: + { + if (mp == &g_mp_sys_dev_hdd1) + { + error_code::set_report_as_warning(); + } + + return {CELL_ENOENT, path}; + } default: sys_fs.error("sys_fs_truncate(): unknown error %s", error); } @@ -2890,7 +2933,15 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr path, vm::cptr g_tls_error_stats; - static thread_local std::string g_tls_error_str; +static thread_local std::string g_tls_error_str; +static thread_local std::unordered_map g_tls_error_stats; +static thread_local bool g_tls_is_error_a_warning; +s32 error_code::make_report(s32 result, const char* fmt, const fmt_type_info* sup, const u64* args) +{ if (!sup && !args) { if (!fmt) @@ -2776,7 +2777,6 @@ s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* s ensure(fmt); - logs::channel* channel = &sys_log; const char* func = "Unknown function"; if (auto ppu = get_current_cpu_thread()) @@ -2804,24 +2804,53 @@ s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* s if (!g_tls_error_stats.empty()) { // Report and clean error state - error_report(0, nullptr, nullptr, nullptr); + make_report(0, nullptr, nullptr, nullptr); } - - channel->error("%s", g_tls_error_str); } else { const auto stat = ++g_tls_error_stats[g_tls_error_str]; - if (stat <= 3) + if (stat > 3) { - channel->error("%s [%u]", g_tls_error_str, stat); + g_tls_error_str.clear(); } } return result; } +void error_code::log_report() +{ + const bool is_warning = std::exchange(g_tls_is_error_a_warning, false); + + if (g_tls_error_str.empty()) + { + // No error + return; + } + + (is_warning ? sys_log.warning : sys_log.error)("%s", g_tls_error_str); + g_tls_error_str.clear(); +} + +void error_code::set_report_as_warning() +{ + g_tls_is_error_a_warning = true; +} + +bool error_code::silence_report() +{ + if (!g_tls_error_str.empty() && g_tls_error_str.ends_with(fmt::format("0x%08x", value))) + { + g_tls_error_str.clear(); + g_tls_is_error_a_warning = false; + return true; + } + + return false; +} + void Emulator::ConfigurePPUCache() const { auto& _main = g_fxo->get();