diff --git a/.gitmodules b/.gitmodules
index c773416e3b..f1fabee4b5 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -16,7 +16,7 @@
ignore = dirty
[submodule "3rdparty/cereal"]
path = 3rdparty/cereal
- url = https://github.com/USCiLab/cereal.git
+ url = https://github.com/RPCS3/cereal.git
ignore = dirty
[submodule "3rdparty/zlib"]
path = 3rdparty/zlib
@@ -37,7 +37,7 @@
ignore = dirty
[submodule "3rdparty/yaml-cpp"]
path = 3rdparty/yaml-cpp
- url = https://github.com/jbeder/yaml-cpp.git
+ url = https://github.com/RPCS3/yaml-cpp.git
ignore = dirty
[submodule "3rdparty/libpng"]
path = 3rdparty/libpng
diff --git a/3rdparty/cereal b/3rdparty/cereal
index 42a45b6e15..60c69df968 160000
--- a/3rdparty/cereal
+++ b/3rdparty/cereal
@@ -1 +1 @@
-Subproject commit 42a45b6e15fcbd1a3d65b033f5d4d0b2ef6c023d
+Subproject commit 60c69df968d1c72c998cd5f23ba34e2e3718a84b
diff --git a/3rdparty/yaml-cpp b/3rdparty/yaml-cpp
index eca9cfd648..6a211f0bc7 160000
--- a/3rdparty/yaml-cpp
+++ b/3rdparty/yaml-cpp
@@ -1 +1 @@
-Subproject commit eca9cfd64899525d0a61abb0553849676a0fe511
+Subproject commit 6a211f0bc71920beef749e6c35d7d1bcc2447715
diff --git a/3rdparty/yaml-cpp.vcxproj b/3rdparty/yaml-cpp.vcxproj
index 849068e0d6..6add456fb1 100644
--- a/3rdparty/yaml-cpp.vcxproj
+++ b/3rdparty/yaml-cpp.vcxproj
@@ -37,6 +37,11 @@
+
+
+ Sync
+
+
diff --git a/Utilities/Config.cpp b/Utilities/Config.cpp
index 3c59881acb..28732b817e 100644
--- a/Utilities/Config.cpp
+++ b/Utilities/Config.cpp
@@ -1,11 +1,14 @@
#include "stdafx.h"
#include "Config.h"
+#include "Utilities/types.h"
-#include "yaml-cpp/yaml.h"
+#include "util/yaml.hpp"
#include
#include
+[[noreturn]] void report_fatal_error(const std::string&);
+
LOG_CHANNEL(cfg_log, "CFG");
namespace cfg
@@ -15,7 +18,7 @@ namespace cfg
{
if (_type != type::node)
{
- fmt::throw_exception("Invalid root node" HERE);
+ cfg_log.fatal("Invalid root node" HERE);
}
}
@@ -26,7 +29,7 @@ namespace cfg
{
if (pair.first == name)
{
- fmt::throw_exception("Node already exists: %s" HERE, name);
+ cfg_log.fatal("Node already exists: %s" HERE, name);
}
}
@@ -35,12 +38,12 @@ namespace cfg
bool _base::from_string(const std::string&, bool)
{
- fmt::throw_exception("from_string() purecall" HERE);
+ report_fatal_error("from_string() purecall" HERE);
}
bool _base::from_list(std::vector&&)
{
- fmt::throw_exception("from_list() purecall" HERE);
+ report_fatal_error("from_list() purecall" HERE);
}
// Emit YAML
@@ -302,14 +305,17 @@ std::string cfg::node::to_string() const
return {out.c_str(), out.size()};
}
-bool cfg::node::from_string(const std::string& value, bool dynamic) try
+bool cfg::node::from_string(const std::string& value, bool dynamic)
{
- cfg::decode(YAML::Load(value), *this, dynamic);
- return true;
-}
-catch (const std::exception& e)
-{
- cfg_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
+ auto [result, error] = yaml_load(value);
+
+ if (error.empty())
+ {
+ cfg::decode(result, *this, dynamic);
+ return true;
+ }
+
+ cfg_log.fatal("Failed to load node: %s", error);
return false;
}
diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp
index a0efec6ead..8655a82397 100644
--- a/Utilities/Thread.cpp
+++ b/Utilities/Thread.cpp
@@ -60,22 +60,6 @@ void fmt_class_string::format(std::string& out, u64 arg)
out += ss.str();
}
-[[noreturn]] void catch_all_exceptions()
-{
- try
- {
- throw;
- }
- catch (const std::exception& e)
- {
- report_fatal_error("{" + g_tls_log_prefix() + "} Unhandled exception of type '"s + typeid(e).name() + "': "s + e.what());
- }
- catch (...)
- {
- report_fatal_error("{" + g_tls_log_prefix() + "} Unhandled exception (unknown)");
- }
-}
-
#ifndef _WIN32
bool IsDebuggerPresent()
{
@@ -1151,33 +1135,12 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
if (rsx::g_access_violation_handler)
{
- bool handled = false;
-
- try
+ if (cpu)
{
- if (cpu)
- {
- vm::temporary_unlock(*cpu);
- }
-
- handled = rsx::g_access_violation_handler(addr, is_writing);
+ vm::temporary_unlock(*cpu);
}
- catch (const std::exception& e)
- {
- rsx_log.fatal("g_access_violation_handler(0x%x, %d): %s", addr, is_writing, e.what());
- if (cpu)
- {
- cpu->state += cpu_flag::dbg_pause;
-
- if (cpu->test_stopped())
- {
- std::terminate();
- }
- }
-
- return false;
- }
+ bool handled = rsx::g_access_violation_handler(addr, is_writing);
if (handled)
{
@@ -1769,7 +1732,7 @@ const bool s_exception_handler_set = []() -> bool
if (::sigaction(SIGSEGV, &sa, NULL) == -1)
{
- std::fprintf(stderr, "sigaction(SIGSEGV) failed (0x%x).", errno);
+ std::fprintf(stderr, "sigaction(SIGSEGV) failed (%d).\n", errno);
std::abort();
}
@@ -1779,6 +1742,23 @@ const bool s_exception_handler_set = []() -> bool
#endif
+const bool s_terminate_handler_set = []() -> bool
+{
+ std::set_terminate([]()
+ {
+ if (IsDebuggerPresent())
+#ifdef _MSC_VER
+ __debugbreak();
+#else
+ __asm("int3;");
+#endif
+
+ report_fatal_error("RPCS3 has abnormally terminated.");
+ });
+
+ return true;
+}();
+
thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
DECLARE(thread_ctrl::g_native_core_layout) { native_core_arrangement::undefined };
diff --git a/Utilities/Thread.h b/Utilities/Thread.h
index 028645dbb3..e58e8fad90 100644
--- a/Utilities/Thread.h
+++ b/Utilities/Thread.h
@@ -15,9 +15,6 @@
// Report error and call std::abort(), defined in main.cpp
[[noreturn]] void report_fatal_error(const std::string&);
-// Will report exception and call std::abort() if put in catch(...)
-[[noreturn]] void catch_all_exceptions();
-
// Hardware core layout
enum class native_core_arrangement : u32
{
@@ -256,9 +253,9 @@ class named_thread final : public Context, result_storage_t, thread_bas
// Type-erased thread entry point
#ifdef _WIN32
- static inline uint __stdcall entry_point(void* arg) try
+ static inline uint __stdcall entry_point(void* arg)
#else
- static inline void* entry_point(void* arg) try
+ static inline void* entry_point(void* arg)
#endif
{
const auto _this = static_cast(static_cast(arg));
@@ -272,10 +269,6 @@ class named_thread final : public Context, result_storage_t, thread_bas
thread::finalize();
return 0;
}
- catch (...)
- {
- catch_all_exceptions();
- }
bool entry_point()
{
diff --git a/Utilities/bin_patch.cpp b/Utilities/bin_patch.cpp
index 4765f41c09..18a5cd6c6b 100644
--- a/Utilities/bin_patch.cpp
+++ b/Utilities/bin_patch.cpp
@@ -1,5 +1,5 @@
#include "bin_patch.h"
-#include
+#include "util/yaml.hpp"
#include "File.h"
#include "Config.h"
@@ -34,15 +34,11 @@ void patch_engine::append(const std::string& patch)
{
if (fs::file f{patch})
{
- YAML::Node root;
+ auto [root, error] = yaml_load(f.to_string());
- try
+ if (!error.empty())
{
- root = YAML::Load(f.to_string());
- }
- catch (const std::exception& e)
- {
- patch_log.fatal("Failed to load patch file %s\n%s thrown: %s", patch, typeid(e).name(), e.what());
+ patch_log.fatal("Failed to load patch file %s:\n%s", patch, error);
return;
}
diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt
index ceba08fe1b..c45dbbe30d 100644
--- a/rpcs3/Emu/CMakeLists.txt
+++ b/rpcs3/Emu/CMakeLists.txt
@@ -32,6 +32,8 @@ target_sources(rpcs3_emu PRIVATE
../util/shared_cptr.cpp
../util/fixed_typemap.cpp
../util/logs.cpp
+ ../util/yaml.cpp
+ ../util/cereal.cpp
../../Utilities/bin_patch.cpp
../../Utilities/cond.cpp
../../Utilities/Config.cpp
@@ -62,6 +64,12 @@ else()
set_source_files_properties("../../Utilities/JIT.cpp" PROPERTIES COMPILE_FLAGS -fno-rtti)
endif()
+if (MSVC)
+ set_source_files_properties("../util/yaml.cpp" PROPERTIES COMPILE_FLAGS /EHsc)
+else()
+ set_source_files_properties("../util/yaml.cpp" PROPERTIES COMPILE_FLAGS -fexceptions)
+endif()
+
# Crypto
target_sources(rpcs3_emu PRIVATE
diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp
index ffbe3d98ab..aacbd9c42d 100644
--- a/rpcs3/Emu/CPU/CPUThread.cpp
+++ b/rpcs3/Emu/CPU/CPUThread.cpp
@@ -243,28 +243,83 @@ using cpu_profiler = named_thread;
thread_local cpu_thread* g_tls_current_cpu_thread = nullptr;
-// For synchronizing suspend_all operation
-alignas(64) shared_mutex g_cpu_suspend_lock;
+struct cpu_counter
+{
+ // For synchronizing suspend_all operation
+ alignas(64) shared_mutex cpu_suspend_lock;
-// Semaphore for global thread array (global counter)
-alignas(64) atomic_t g_cpu_array_sema{0};
+ // Semaphore for global thread array (global counter)
+ alignas(64) atomic_t cpu_array_sema{0};
-// Semaphore subdivision for each array slot (64 x N in total)
-atomic_t g_cpu_array_bits[6]{};
+ // Semaphore subdivision for each array slot (64 x N in total)
+ atomic_t cpu_array_bits[6]{};
-// All registered threads
-atomic_t g_cpu_array[sizeof(g_cpu_array_bits) * 8]{};
+ // All registered threads
+ atomic_t cpu_array[sizeof(cpu_array_bits) * 8]{};
+
+ u64 add(cpu_thread* _this)
+ {
+ if (!cpu_array_sema.try_inc(sizeof(cpu_counter::cpu_array_bits) * 8))
+ {
+ return -1;
+ }
+
+ u64 array_slot = -1;
+
+ for (u32 i = 0;; i = (i + 1) % ::size32(cpu_array_bits))
+ {
+ const auto [bits, ok] = cpu_array_bits[i].fetch_op([](u64& bits) -> u64
+ {
+ if (~bits) [[likely]]
+ {
+ // Set lowest clear bit
+ bits |= bits + 1;
+ return true;
+ }
+
+ return false;
+ });
+
+ if (ok) [[likely]]
+ {
+ // Get actual slot number
+ array_slot = i * 64 + utils::cnttz64(~bits, false);
+ break;
+ }
+ }
+
+ // Register and wait if necessary
+ verify("cpu_counter::add()" HERE), cpu_array[array_slot].exchange(_this) == nullptr;
+
+ _this->state += cpu_flag::wait;
+ cpu_suspend_lock.lock_unlock();
+ return array_slot;
+ }
+
+ void remove(cpu_thread* _this, u64 slot)
+ {
+ // Unregister and wait if necessary
+ _this->state += cpu_flag::wait;
+ if (cpu_array[slot].exchange(nullptr) != _this)
+ sys_log.fatal("Inconsistency for array slot %u", slot);
+ cpu_array_bits[slot / 64] &= ~(1ull << (slot % 64));
+ cpu_array_sema--;
+ cpu_suspend_lock.lock_unlock();
+ }
+};
template
void for_all_cpu(F&& func) noexcept
{
- for (u32 i = 0; i < ::size32(g_cpu_array_bits); i++)
+ auto ctr = g_fxo->get();
+
+ for (u32 i = 0; i < ::size32(ctr->cpu_array_bits); i++)
{
- for (u64 bits = g_cpu_array_bits[i]; bits; bits &= bits - 1)
+ for (u64 bits = ctr->cpu_array_bits[i]; bits; bits &= bits - 1)
{
const u64 index = i * 64 + utils::cnttz64(bits, true);
- if (cpu_thread* cpu = g_cpu_array[index].load())
+ if (cpu_thread* cpu = ctr->cpu_array[index].load())
{
func(cpu);
}
@@ -301,6 +356,12 @@ void cpu_thread::operator()()
}
}
+ while (!g_fxo->get() && !g_fxo->get())
+ {
+ // Can we have a little race, right? First thread is started concurrently with g_fxo->init()
+ std::this_thread::sleep_for(1ms);
+ }
+
if (id_type() == 1 && false)
{
g_fxo->get()->registered.push(id);
@@ -312,67 +373,51 @@ void cpu_thread::operator()()
}
// Register thread in g_cpu_array
- if (!g_cpu_array_sema.try_inc(sizeof(g_cpu_array_bits) * 8))
+ const u64 array_slot = g_fxo->get()->add(this);
+
+ if (array_slot == umax)
{
sys_log.fatal("Too many threads.");
return;
}
- u64 array_slot = -1;
-
- for (u32 i = 0;; i = (i + 1) % ::size32(g_cpu_array_bits))
- {
- const auto [bits, ok] = g_cpu_array_bits[i].fetch_op([](u64& bits) -> u64
- {
- if (~bits) [[likely]]
- {
- // Set lowest clear bit
- bits |= bits + 1;
- return true;
- }
-
- return false;
- });
-
- if (ok) [[likely]]
- {
- // Get actual slot number
- array_slot = i * 64 + utils::cnttz64(~bits, false);
- break;
- }
- }
-
- // Register and wait if necessary
- verify("g_cpu_array[...] -> this" HERE), g_cpu_array[array_slot].exchange(this) == nullptr;
-
- state += cpu_flag::wait;
- g_cpu_suspend_lock.lock_unlock();
-
static thread_local struct thread_cleanup_t
{
cpu_thread* _this;
u64 slot;
+ std::string name;
thread_cleanup_t(cpu_thread* _this, u64 slot)
: _this(_this)
, slot(slot)
+ , name(thread_ctrl::get_name())
{
}
- ~thread_cleanup_t()
+ void cleanup()
{
+ if (_this == nullptr)
+ {
+ return;
+ }
+
if (auto ptr = vm::g_tls_locked)
{
ptr->compare_and_swap(_this, nullptr);
}
- // Unregister and wait if necessary
- _this->state += cpu_flag::wait;
- if (g_cpu_array[slot].exchange(nullptr) != _this)
- sys_log.fatal("Inconsistency for array slot %u", slot);
- g_cpu_array_bits[slot / 64] &= ~(1ull << (slot % 64));
- g_cpu_array_sema--;
- g_cpu_suspend_lock.lock_unlock();
+ g_fxo->get()->remove(_this, slot);
+
+ _this = nullptr;
+ }
+
+ ~thread_cleanup_t()
+ {
+ if (_this)
+ {
+ sys_log.warning("CPU Thread '%s' terminated abnormally:\n%s", name, _this->dump());
+ cleanup();
+ }
}
} cleanup{this, array_slot};
@@ -382,23 +427,16 @@ void cpu_thread::operator()()
// Check stop status
if (!(state & cpu_flag::stop))
{
- try
- {
- cpu_task();
- }
- catch (const std::exception& e)
- {
- sys_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
- sys_log.notice("\n%s", dump());
- break;
- }
-
+ cpu_task();
state -= cpu_flag::ret;
continue;
}
thread_ctrl::wait();
}
+
+ // Complete cleanup gracefully
+ cleanup.cleanup();
}
cpu_thread::~cpu_thread()
@@ -493,7 +531,7 @@ bool cpu_thread::check_state() noexcept
else
{
// If only cpu_flag::pause was set, notification won't arrive
- g_cpu_suspend_lock.lock_unlock();
+ g_fxo->get()->cpu_suspend_lock.lock_unlock();
}
}
@@ -577,7 +615,7 @@ cpu_thread::suspend_all::suspend_all(cpu_thread* _this) noexcept
m_this->state += cpu_flag::wait;
}
- g_cpu_suspend_lock.lock_vip();
+ g_fxo->get()->cpu_suspend_lock.lock_vip();
for_all_cpu([](cpu_thread* cpu)
{
@@ -610,18 +648,18 @@ cpu_thread::suspend_all::suspend_all(cpu_thread* _this) noexcept
cpu_thread::suspend_all::~suspend_all()
{
// Make sure the latest thread does the cleanup and notifies others
- if (g_cpu_suspend_lock.downgrade_unique_vip_lock_to_low_or_unlock())
+ if (g_fxo->get()->cpu_suspend_lock.downgrade_unique_vip_lock_to_low_or_unlock())
{
for_all_cpu([&](cpu_thread* cpu)
{
cpu->state -= cpu_flag::pause;
});
- g_cpu_suspend_lock.unlock_low();
+ g_fxo->get()->cpu_suspend_lock.unlock_low();
}
else
{
- g_cpu_suspend_lock.lock_unlock();
+ g_fxo->get()->cpu_suspend_lock.lock_unlock();
}
if (m_this)
@@ -640,7 +678,7 @@ void cpu_thread::stop_all() noexcept
}
else
{
- ::vip_lock lock(g_cpu_suspend_lock);
+ ::vip_lock lock(g_fxo->get()->cpu_suspend_lock);
for_all_cpu([](cpu_thread* cpu)
{
@@ -651,7 +689,7 @@ void cpu_thread::stop_all() noexcept
sys_log.notice("All CPU threads have been signaled.");
- while (g_cpu_array_sema)
+ while (g_fxo->get()->cpu_array_sema)
{
std::this_thread::sleep_for(10ms);
}
diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp
index 17826f78de..f3b0944408 100644
--- a/rpcs3/Emu/Cell/Modules/cellGame.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp
@@ -138,15 +138,9 @@ struct content_permission final
bool success = false;
fs::g_tls_error = fs::error::ok;
- try
- {
- if (temp.size() <= 1 || fs::remove_all(temp))
- {
- success = true;
- }
- }
- catch (...)
+ if (temp.size() <= 1 || fs::remove_all(temp))
{
+ success = true;
}
if (!success)
diff --git a/rpcs3/Emu/Cell/Modules/cellPngDec.cpp b/rpcs3/Emu/Cell/Modules/cellPngDec.cpp
index d3b899e4eb..ee83107071 100644
--- a/rpcs3/Emu/Cell/Modules/cellPngDec.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellPngDec.cpp
@@ -151,7 +151,7 @@ void pngDecError(png_structp png_ptr, png_const_charp error_message)
{
cellPngDec.error("%s", error_message);
// we can't return here or libpng blows up
- throw LibPngCustomException("Fatal Error in libpng");
+ report_fatal_error("Fatal Error in libpng");
}
// Custom warning handler for libpng
@@ -486,14 +486,7 @@ s32 pngDecOpen(ppu_thread& ppu, PHandle handle, PPStream png_stream, PSrc source
png_set_progressive_read_fn(stream->png_ptr, stream.get_ptr(), pngDecInfoCallback, pngDecRowCallback, pngDecEndCallback);
// push header tag to libpng to keep us in sync
- try
- {
- png_process_data(stream->png_ptr, stream->info_ptr, header, 8);
- }
- catch (LibPngCustomException&)
- {
- return CELL_PNGDEC_ERROR_HEADER;
- }
+ png_process_data(stream->png_ptr, stream->info_ptr, header, 8);
}
else
{
@@ -729,15 +722,7 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr d
if (stream->buffer->length > stream->buffer->cursor)
{
u8* data = static_cast(stream->buffer->data.get_ptr()) + stream->buffer->cursor;
- try
- {
- png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length - stream->buffer->cursor);
- }
- catch (LibPngCustomException&)
- {
- freeMem();
- return CELL_PNGDEC_ERROR_FATAL;
- }
+ png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length - stream->buffer->cursor);
streamInfo->decodedStrmSize = ::narrow(stream->buffer->length);
}
@@ -747,15 +732,7 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr d
{
stream->cbCtrlStream.cbCtrlStrmFunc(ppu, streamInfo, streamParam, stream->cbCtrlStream.cbCtrlStrmArg);
streamInfo->decodedStrmSize += streamParam->strmSize;
- try
- {
- png_process_data(stream->png_ptr, stream->info_ptr, static_cast(streamParam->strmPtr.get_ptr()), streamParam->strmSize);
- }
- catch (LibPngCustomException&)
- {
- freeMem();
- return CELL_PNGDEC_ERROR_FATAL;
- }
+ png_process_data(stream->png_ptr, stream->info_ptr, static_cast(streamParam->strmPtr.get_ptr()), streamParam->strmSize);
}
freeMem();
@@ -767,7 +744,6 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr d
// Decode the image
// todo: commandptr
- try
{
for (u32 j = 0; j < stream->passes; j++)
{
@@ -779,10 +755,6 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr d
}
png_read_end(stream->png_ptr, stream->info_ptr);
}
- catch (LibPngCustomException&)
- {
- return CELL_PNGDEC_ERROR_FATAL;
- }
}
// Get the number of iTXt, tEXt and zTXt chunks
@@ -862,14 +834,7 @@ s32 cellPngDecExtReadHeader(PHandle handle, PStream stream, PInfo info, PExtInfo
// lets push what we have so far
u8* data = static_cast(stream->buffer->data.get_ptr()) + stream->buffer->cursor;
- try
- {
- png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length);
- }
- catch (LibPngCustomException&)
- {
- return CELL_PNGDEC_ERROR_HEADER;
- }
+ png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length);
// lets hope we pushed enough for callback
pngSetHeader(stream.get_ptr());
diff --git a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp
index 477e5378ae..f95c37568d 100644
--- a/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellSpursSpu.cpp
@@ -114,7 +114,9 @@ void cellSpursModuleExit(spu_thread& spu)
{
auto ctxt = vm::_ptr(spu.offset + 0x100);
spu.pc = ctxt->exitToKernelAddr;
- throw SpursModuleExit();
+
+ // TODO: use g_escape for actual long jump
+ //throw SpursModuleExit();
}
// Execute a DMA operation
@@ -728,7 +730,6 @@ bool spursSysServiceEntry(spu_thread& spu)
auto arg = spu.gpr[4]._u64[1];
auto pollStatus = spu.gpr[5]._u32[3];
- try
{
if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID)
{
@@ -743,10 +744,6 @@ bool spursSysServiceEntry(spu_thread& spu)
cellSpursModuleExit(spu);
}
- catch (SpursModuleExit)
- {
- }
-
return false;
}
@@ -1326,7 +1323,6 @@ bool spursTasksetEntry(spu_thread& spu)
//spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry);
//spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry);
- try
{
// Initialise the taskset policy module
spursTasksetInit(spu, pollStatus);
@@ -1334,9 +1330,6 @@ bool spursTasksetEntry(spu_thread& spu)
// Dispatch
spursTasksetDispatch(spu);
}
- catch (SpursModuleExit)
- {
- }
return false;
}
@@ -1346,7 +1339,6 @@ bool spursTasksetSyscallEntry(spu_thread& spu)
{
auto ctxt = vm::_ptr(spu.offset + 0x2700);
- try
{
// Save task context
ctxt->savedContextLr = spu.gpr[0];
@@ -1365,9 +1357,6 @@ bool spursTasksetSyscallEntry(spu_thread& spu)
// spursTasksetResumeTask(spu);
//}
}
- catch (SpursModuleExit)
- {
- }
return false;
}
diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp
index c6424ba131..fdf3c6defa 100644
--- a/rpcs3/Emu/Cell/PPUAnalyser.cpp
+++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp
@@ -5,7 +5,7 @@
#include "PPUModule.h"
#include
-#include "yaml-cpp/yaml.h"
+#include "util/yaml.hpp"
#include "Utilities/asm.h"
LOG_CHANNEL(ppu_validator);
@@ -54,7 +54,13 @@ void ppu_module::validate(u32 reloc)
// Load custom PRX configuration if available
if (fs::file yml{path + ".yml"})
{
- const auto cfg = YAML::Load(yml.to_string());
+ const auto [cfg, error] = yaml_load(yml.to_string());
+
+ if (!error.empty())
+ {
+ ppu_validator.error("Failed to load %s.yml: %s", path, error);
+ return;
+ }
u32 index = 0;
diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp
index a516c4a9a0..e84ff28cd7 100644
--- a/rpcs3/Emu/Cell/PPUThread.cpp
+++ b/rpcs3/Emu/Cell/PPUThread.cpp
@@ -859,16 +859,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
}
};
- try
- {
- exec_task();
- }
- catch (...)
- {
- at_ret();
- throw;
- }
-
+ exec_task();
at_ret();
}
diff --git a/rpcs3/Emu/Cell/PPUTranslator.cpp b/rpcs3/Emu/Cell/PPUTranslator.cpp
index ad23ba97cd..72c4a16cfc 100644
--- a/rpcs3/Emu/Cell/PPUTranslator.cpp
+++ b/rpcs3/Emu/Cell/PPUTranslator.cpp
@@ -4357,7 +4357,7 @@ Value* PPUTranslator::GetVr(u32 vr, VrType type)
case VrType::i128: return m_ir->CreateBitCast(value, GetType());
}
- throw std::logic_error("GetVr(): invalid type");
+ report_fatal_error("GetVr(): invalid type");
}
void PPUTranslator::SetVr(u32 vr, Value* value)
@@ -4435,7 +4435,7 @@ void PPUTranslator::SetFPRF(Value* value, bool set_cr)
const bool is32 =
value->getType()->isFloatTy() ? true :
value->getType()->isDoubleTy() ? false :
- throw std::logic_error("SetFPRF(): invalid value type");
+ (report_fatal_error("SetFPRF(): invalid value type"), false);
//const auto zero = ConstantFP::get(value->getType(), 0.0);
//const auto is_nan = m_ir->CreateFCmpUNO(value, zero);
diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp
index 503a0aeceb..80bc0f8396 100644
--- a/rpcs3/Emu/Cell/SPURecompiler.cpp
+++ b/rpcs3/Emu/Cell/SPURecompiler.cpp
@@ -1154,7 +1154,7 @@ void spu_recompiler_base::branch(spu_thread& spu, void*, u8* rip)
spu_runtime::g_tail_escape(&spu, func, rip);
}
-void spu_recompiler_base::old_interpreter(spu_thread& spu, void* ls, u8* rip) try
+void spu_recompiler_base::old_interpreter(spu_thread& spu, void* ls, u8* rip)
{
// Select opcode table
const auto& table = *(
@@ -1178,11 +1178,6 @@ void spu_recompiler_base::old_interpreter(spu_thread& spu, void* ls, u8* rip) tr
spu.pc += 4;
}
}
-catch (const std::exception& e)
-{
- spu_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
- spu_log.notice("\n%s", spu.dump());
-}
spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point)
{
@@ -4608,19 +4603,7 @@ public:
}
// Execute recompiler function (TODO)
- try
- {
- (this->*g_decoder.decode(op))({op});
- }
- catch (const std::exception&)
- {
- std::string dump;
- raw_string_ostream out(dump);
- out << *module; // print IR
- out.flush();
- spu_log.error("[0x%x] LLVM dump:\n%s", m_pos, dump);
- throw;
- }
+ (this->*g_decoder.decode(op))({op});
}
// Finalize block with fallthrough if necessary
@@ -4994,7 +4977,6 @@ public:
}
}
- try
{
m_interp_bblock = nullptr;
@@ -5142,15 +5124,6 @@ public:
}
}
}
- catch (const std::exception&)
- {
- std::string dump;
- raw_string_ostream out(dump);
- out << *module; // print IR
- out.flush();
- spu_log.error("[0x%x] LLVM dump:\n%s", m_pos, dump);
- throw;
- }
}
if (last_itype != itype && g_cfg.core.spu_decoder != spu_decoder_type::llvm)
diff --git a/rpcs3/Emu/GDB.cpp b/rpcs3/Emu/GDB.cpp
index 1a92539d14..f32f4c7122 100644
--- a/rpcs3/Emu/GDB.cpp
+++ b/rpcs3/Emu/GDB.cpp
@@ -303,21 +303,13 @@ bool gdb_thread::read_cmd(gdb_cmd& out_cmd)
{
while (true)
{
- try
+ if (try_read_cmd(out_cmd))
{
- if (try_read_cmd(out_cmd))
- {
- ack(true);
- return true;
- }
+ ack(true);
+ return true;
+ }
- ack(false);
- }
- catch (const std::runtime_error& e)
- {
- GDB.error("Error: %s", e.what());
- return false;
- }
+ ack(false);
}
}
@@ -866,7 +858,7 @@ void gdb_thread::operator()()
Emu.Pause();
}
- try {
+ {
char hostbuf[32];
inet_ntop(client.sin_family, reinterpret_cast(&client.sin_addr), hostbuf, 32);
GDB.success("Got connection to GDB debug server from %s:%d.", hostbuf, client.sin_port);
@@ -905,16 +897,6 @@ void gdb_thread::operator()()
}
}
}
- catch (const std::runtime_error& e)
- {
- if (client_socket != -1)
- {
- closesocket(client_socket);
- client_socket = -1;
- }
-
- GDB.error("Error: %s", e.what());
- }
}
}
diff --git a/rpcs3/Emu/RSX/Capture/rsx_replay.cpp b/rpcs3/Emu/RSX/Capture/rsx_replay.cpp
index 007bfd79c4..e60096f4a8 100644
--- a/rpcs3/Emu/RSX/Capture/rsx_replay.cpp
+++ b/rpcs3/Emu/RSX/Capture/rsx_replay.cpp
@@ -242,13 +242,6 @@ namespace rsx
void rsx_replay_thread::operator()()
{
- try
- {
- on_task();
- }
- catch (const std::exception& e)
- {
- rsx_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
- }
+ on_task();
}
}
diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h
index f2b82bf221..3364ecdcf5 100644
--- a/rpcs3/Emu/RSX/GL/GLHelpers.h
+++ b/rpcs3/Emu/RSX/GL/GLHelpers.h
@@ -2396,42 +2396,6 @@ public:
namespace glsl
{
- class compilation_exception : public exception
- {
- public:
- explicit compilation_exception(const std::string& what_arg)
- {
- m_what = "compilation failed: '" + what_arg + "'";
- }
- };
-
- class link_exception : public exception
- {
- public:
- explicit link_exception(const std::string& what_arg)
- {
- m_what = "linkage failed: '" + what_arg + "'";
- }
- };
-
- class validation_exception : public exception
- {
- public:
- explicit validation_exception(const std::string& what_arg)
- {
- m_what = "compilation failed: '" + what_arg + "'";
- }
- };
-
- class not_found_exception : public exception
- {
- public:
- explicit not_found_exception(const std::string& what_arg)
- {
- m_what = what_arg + " not found.";
- }
- };
-
class shader
{
public:
@@ -2533,7 +2497,7 @@ public:
error_msg = buf.get();
}
- throw compilation_exception(error_msg);
+ rsx_log.fatal("Compilation failed: %s", error_msg);
}
return *this;
@@ -2655,7 +2619,8 @@ public:
}
else
{
- throw not_found_exception(name);
+ rsx_log.fatal("%s not found.", name);
+ return -1;
}
}
@@ -2663,7 +2628,8 @@ public:
if (result < 0)
{
- throw not_found_exception(name);
+ rsx_log.fatal("%s not found.", name);
+ return result;
}
locations[name] = result;
@@ -2749,7 +2715,7 @@ public:
error_msg = buf.get();
}
- throw link_exception(error_msg);
+ rsx_log.fatal("Linkage failed: %s", error_msg);
}
}
diff --git a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp
index 016f7151e6..4cbc65cbf3 100644
--- a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp
+++ b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp
@@ -42,7 +42,7 @@ namespace
case rsx::index_array_type::u16: return GL_UNSIGNED_SHORT;
case rsx::index_array_type::u32: return GL_UNSIGNED_INT;
}
- throw;
+ fmt::throw_exception("Invalid index array type (%u)", static_cast(type));
}
struct vertex_input_state
diff --git a/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp b/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp
index 8f9a911212..feb3000931 100644
--- a/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp
+++ b/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp
@@ -9,6 +9,7 @@
#include
#include
+#include
namespace rsx
{
@@ -21,22 +22,65 @@ namespace rsx
hex_color.erase(0, 1);
}
- unsigned long hexval;
- const size_t len = hex_color.length();
+ unsigned hexval = 0;
+ const auto len = hex_color.length();
- try
+ if (len != 6 && len != 8)
{
- if (len != 6 && len != 8)
- {
- fmt::throw_exception("wrong length: %d", len);
- }
- hexval = std::stoul(hex_color, nullptr, 16);
- }
- catch (const std::exception& e)
- {
- rsx_log.error("Overlays: tried to convert incompatible color code: '%s' exception: '%s'", hex_color, e.what());
+ rsx_log.error("Incompatible color code: '%s' has wrong length: %d", hex_color, len);
return color4f(0.0f, 0.0f, 0.0f, 0.0f);
}
+ else
+ {
+ // auto&& [ptr, ec] = std::from_chars(hex_color.c_str(), hex_color.c_str() + len, &hexval, 16);
+
+ // if (ptr != hex_color.c_str() + len || ec)
+ // {
+ // rsx_log.error("Overlays: tried to convert incompatible color code: '%s'", hex_color);
+ // return color4f(0.0f, 0.0f, 0.0f, 0.0f);
+ // }
+ for (u32 i = 0; i < len; i++)
+ {
+ hexval <<= 4;
+
+ switch (char c = hex_color[i])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ hexval |= (c - '0');
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ hexval |= (c - 'a' + 10);
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ hexval |= (c - 'A' + 10);
+ break;
+ default:
+ {
+ rsx_log.error("Overlays: invalid characters in color code: '%s'", hex_color);
+ return color4f(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+ }
const int r = (len == 8 ? (hexval >> 24) : (hexval >> 16)) & 0xff;
const int g = (len == 8 ? (hexval >> 16) : (hexval >> 8)) & 0xff;
diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp
index 5813de0c6a..28132ff242 100644
--- a/rpcs3/Emu/RSX/RSXThread.cpp
+++ b/rpcs3/Emu/RSX/RSXThread.cpp
@@ -442,7 +442,6 @@ namespace rsx
void thread::operator()()
{
- try
{
// Wait for startup (TODO)
while (m_rsx_thread_exiting)
@@ -457,10 +456,6 @@ namespace rsx
on_task();
}
- catch (const std::exception& e)
- {
- rsx_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
- }
on_exit();
}
diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp
index 3a3c32fe32..972b015a4f 100644
--- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp
+++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp
@@ -52,7 +52,7 @@ namespace vk
case rsx::index_array_type::u16:
return VK_INDEX_TYPE_UINT16;
}
- throw;
+ fmt::throw_exception("Invalid index array type (%u)", static_cast(type));
}
}
diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp
index 3b060298a2..c0f12b8cb0 100644
--- a/rpcs3/Emu/System.cpp
+++ b/rpcs3/Emu/System.cpp
@@ -30,7 +30,7 @@
#include "../Crypto/unself.h"
#include "../Crypto/unpkg.h"
-#include
+#include "util/yaml.hpp"
#include "cereal/archives/binary.hpp"
@@ -760,12 +760,23 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
m_title_id = title_id;
}
- try
{
Init();
// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations)
- YAML::Node games = YAML::Load(fs::file{fs::get_config_dir() + "/games.yml", fs::read + fs::create}.to_string());
+ YAML::Node games;
+
+ if (fs::file f{fs::get_config_dir() + "/games.yml", fs::read + fs::create})
+ {
+ auto [result, error] = yaml_load(f.to_string());
+
+ if (!error.empty())
+ {
+ sys_log.error("Failed to load games.yml: %s", error);
+ }
+
+ games = result;
+ }
if (!games.IsMap())
{
@@ -1462,12 +1473,6 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
}
return game_boot_result::no_errors;
}
- catch (const std::exception& e)
- {
- sys_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
- Stop();
- return game_boot_result::generic_error;
- }
}
void Emulator::Run(bool start_playtime)
diff --git a/rpcs3/cmake_modules/ConfigureCompiler.cmake b/rpcs3/cmake_modules/ConfigureCompiler.cmake
index 93a264d68e..0fe5911b0a 100644
--- a/rpcs3/cmake_modules/ConfigureCompiler.cmake
+++ b/rpcs3/cmake_modules/ConfigureCompiler.cmake
@@ -2,7 +2,7 @@
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew /D _CRT_SECURE_NO_DEPRECATE=1 /D _CRT_NON_CONFORMING_SWPRINTFS=1 /D _SCL_SECURE_NO_WARNINGS=1")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _ENABLE_EXTENDED_ALIGNED_STORAGE=1")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _ENABLE_EXTENDED_ALIGNED_STORAGE=1 /D _HAS_EXCEPTIONS=0")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /DYNAMICBASE:NO /BASE:0x10000 /FIXED")
@@ -23,7 +23,7 @@ else()
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
add_compile_options(-Wall)
- add_compile_options(-fexceptions)
+ add_compile_options(-fno-exceptions)
add_compile_options(-ftemplate-depth=1024)
add_compile_options(-msse -msse2 -mcx16)
add_compile_options(-fno-strict-aliasing)
diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj
index 95b4b86483..ac4022dd8a 100644
--- a/rpcs3/emucore.vcxproj
+++ b/rpcs3/emucore.vcxproj
@@ -87,6 +87,13 @@
NotUsing
+
+ NotUsing
+ Sync
+
+
+ NotUsing
+
NotUsing
diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters
index 4aaa51b2de..b83eb77f4d 100644
--- a/rpcs3/emucore.vcxproj.filters
+++ b/rpcs3/emucore.vcxproj.filters
@@ -869,6 +869,15 @@
Utilities
+
+ Utilities
+
+
+ Utilities
+
+
+ Utilities
+
Utilities
diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp
index 5db3d7f7bc..9b4be29257 100644
--- a/rpcs3/main.cpp
+++ b/rpcs3/main.cpp
@@ -38,9 +38,11 @@ DYNAMIC_IMPORT("ntdll.dll", NtSetTimerResolution, NTSTATUS(ULONG DesiredResoluti
#endif
#include "Utilities/sysinfo.h"
+#include "Utilities/Config.h"
#include "rpcs3_version.h"
#include "Emu/System.h"
#include
+#include
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
@@ -213,49 +215,44 @@ QCoreApplication* createApplication(int& argc, char* argv[])
auto rounding_val = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
auto rounding_str = std::to_string(static_cast(rounding_val));
const auto i_rounding = find_arg(arg_rounding, argc, argv);
+
if (i_rounding)
{
const auto i_rounding_2 = (argc > (i_rounding + 1)) ? (i_rounding + 1) : 0;
+
if (i_rounding_2)
{
const auto arg_val = argv[i_rounding_2];
- try
- {
- const auto rounding_val_cli = std::stoi(arg_val);
- if (rounding_val_cli >= static_cast(Qt::HighDpiScaleFactorRoundingPolicy::Unset) && rounding_val_cli <= static_cast(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough))
- {
- rounding_val = static_cast(rounding_val_cli);
- rounding_str = std::to_string(static_cast(rounding_val));
- }
- else
- {
- throw std::exception();
- }
- }
- catch (const std::exception&)
+ const auto arg_len = std::strlen(arg_val);
+ s64 rounding_val_cli = 0;
+
+ if (!cfg::try_to_int64(&rounding_val_cli, arg_val, static_cast(Qt::HighDpiScaleFactorRoundingPolicy::Unset), static_cast(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)))
{
std::cout << "The value " << arg_val << " for " << arg_rounding << " is not allowed. Please use a valid value for Qt::HighDpiScaleFactorRoundingPolicy.\n";
}
+ else
+ {
+ rounding_val = static_cast(static_cast(rounding_val_cli));
+ rounding_str = std::to_string(static_cast(rounding_val));
+ }
}
}
- try
+
{
rounding_str = qEnvironmentVariable("QT_SCALE_FACTOR_ROUNDING_POLICY", rounding_str.c_str()).toStdString();
- const auto rounding_val_final = std::stoi(rounding_str);
- if (rounding_val_final >= static_cast(Qt::HighDpiScaleFactorRoundingPolicy::Unset) && rounding_val_final <= static_cast(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough))
+
+ s64 rounding_val_final = 0;
+
+ if (cfg::try_to_int64(&rounding_val_final, rounding_str, static_cast(Qt::HighDpiScaleFactorRoundingPolicy::Unset), static_cast(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)))
{
- rounding_val = static_cast(rounding_val_final);
+ rounding_val = static_cast(static_cast(rounding_val_final));
rounding_str = std::to_string(static_cast(rounding_val));
}
else
{
- throw std::exception();
+ std::cout << "The value " << rounding_str << " for " << arg_rounding << " is not allowed. Please use a valid value for Qt::HighDpiScaleFactorRoundingPolicy.\n";
}
}
- catch (const std::exception&)
- {
- std::cout << "The value " << rounding_str << " for " << arg_rounding << " is not allowed. Please use a valid value for Qt::HighDpiScaleFactorRoundingPolicy.\n";
- }
QApplication::setHighDpiScaleFactorRoundingPolicy(rounding_val);
}
diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index 2075781b41..5ff74a87a7 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -127,7 +127,6 @@
false
ProgramDatabase
4577;4467;%(DisableSpecificWarnings)
- Sync
$(IntDir)
MaxSpeed
_WINDOWS;UNICODE;WIN32;WIN64;WITH_DISCORD_RPC;QT_NO_DEBUG;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;%(PreprocessorDefinitions)
@@ -180,7 +179,6 @@
false
ProgramDatabase
4577;4467;%(DisableSpecificWarnings)
- Sync
$(IntDir)
MaxSpeed
_WINDOWS;UNICODE;WIN32;WIN64;WITH_DISCORD_RPC;QT_NO_DEBUG;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;BRANCH=$(BRANCH);QT_CONCURRENT_LIB;%(PreprocessorDefinitions)
@@ -233,7 +231,6 @@
false
ProgramDatabase
4577;4467;%(DisableSpecificWarnings)
- Sync
$(IntDir)
Disabled
_WINDOWS;UNICODE;WIN32;WIN64;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;%(PreprocessorDefinitions)
@@ -287,7 +284,6 @@
false
ProgramDatabase
4577;4467;%(DisableSpecificWarnings)
- Sync
$(IntDir)
Disabled
_WINDOWS;UNICODE;WIN32;WIN64;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;%(PreprocessorDefinitions)
diff --git a/rpcs3/rpcs3qt/cheat_manager.cpp b/rpcs3/rpcs3qt/cheat_manager.cpp
index 857e112c67..2b6cc9f701 100644
--- a/rpcs3/rpcs3qt/cheat_manager.cpp
+++ b/rpcs3/rpcs3qt/cheat_manager.cpp
@@ -6,8 +6,6 @@
#include
#include
-#include
-
#include "cheat_manager.h"
#include "Emu/System.h"
@@ -19,6 +17,7 @@
#include "Emu/Cell/PPUAnalyser.h"
#include "Emu/Cell/PPUFunction.h"
+#include "util/yaml.hpp"
#include "Utilities/StrUtil.h"
LOG_CHANNEL(log_cheat, "Cheat");
@@ -110,9 +109,14 @@ std::string cheat_info::to_str() const
cheat_engine::cheat_engine()
{
- try
+ if (fs::file cheat_file{fs::get_config_dir() + cheats_filename, fs::read + fs::create})
{
- YAML::Node yml_cheats = YAML::Load(fs::file{fs::get_config_dir() + cheats_filename, fs::read + fs::create}.to_string());
+ auto [yml_cheats, error] = yaml_load(cheat_file.to_string());
+
+ if (!error.empty())
+ {
+ log_cheat.error("Error parsing %s: %s", cheats_filename, error);
+ }
for (const auto& yml_cheat : yml_cheats)
{
@@ -127,9 +131,9 @@ cheat_engine::cheat_engine()
}
}
}
- catch (YAML::Exception& e)
+ else
{
- log_cheat.error("Error parsing %s\n%s", cheats_filename, e.what());
+ log_cheat.error("Error loading %s", cheats_filename);
}
}
diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp
index eaeaf8edf2..62bb61c0dd 100644
--- a/rpcs3/rpcs3qt/game_list_frame.cpp
+++ b/rpcs3/rpcs3qt/game_list_frame.cpp
@@ -18,6 +18,7 @@
#include "Loader/PSF.h"
#include "Utilities/types.h"
#include "Utilities/lockless.h"
+#include "util/yaml.hpp"
#include
#include
@@ -543,24 +544,23 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
auto get_games = []() -> YAML::Node
{
- try
- {
- fs::file games(fs::get_config_dir() + "/games.yml", fs::read + fs::create);
+ fs::file games(fs::get_config_dir() + "/games.yml", fs::read + fs::create);
- if (games)
+ if (games)
+ {
+ auto [result, error] = yaml_load(games.to_string());
+
+ if (!error.empty())
{
- return YAML::Load(games.to_string());
- }
- else
- {
- game_list_log.error("Failed to load games.yml, check permissions.");
+ game_list_log.error("Failed to load games.yml: %s", error);
return {};
}
+
+ return result;
}
- catch (...)
+ else
{
- // YAML exception aren't very useful so just ignore them
- game_list_log.fatal("Failed to parse games.yml");
+ game_list_log.error("Failed to load games.yml, check permissions.");
return {};
}
@@ -616,7 +616,6 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
{
const Localized thread_localized;
- try
{
const std::string sfo_dir = Emulator::GetSfoDirFromGamePath(dir, Emu.GetUsr());
const fs::file sfo_file(sfo_dir + "/PARAM.SFO");
@@ -724,11 +723,6 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
games.push(std::make_shared(gui_game_info{game, qt_cat, compat, icon, pxmap, hasCustomConfig, hasCustomPadConfig}));
}
- catch (const std::exception& e)
- {
- game_list_log.fatal("Failed to update game list at %s\n%s thrown: %s", dir, typeid(e).name(), e.what());
- return;
- }
});
for (auto&& g : games.pop_all())
@@ -744,29 +738,37 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
for (const auto& other : m_game_data)
{
// The patch is game data and must have the same serial and an app version
+ static constexpr auto version_is_bigger = [](const std::string& v0, const std::string& v1, const std::string& serial, bool is_fw)
+ {
+ std::add_pointer_t ev0, ev1;
+ const double ver0 = std::strtod(v0.c_str(), &ev0);
+ const double ver1 = std::strtod(v1.c_str(), &ev1);
+
+ if (v0.c_str() + v0.size() == ev0 && v1.c_str() + v1.size() == ev1)
+ {
+ return ver0 > ver1;
+ }
+
+ game_list_log.error("Failed to update the displayed %s numbers for title ID %s\n'%s'-'%s'", is_fw ? "firmware version" : "version", serial, v0, v1);
+ return false;
+ };
+
if (entry->info.serial == other->info.serial && other->info.category == "GD" && other->info.app_ver != cat_unknown_localized)
{
- try
+ // Update the app version if it's higher than the disc's version (old games may not have an app version)
+ if (entry->info.app_ver == cat_unknown_localized || version_is_bigger(other->info.app_ver, entry->info.app_ver, entry->info.serial, true))
{
- // Update the app version if it's higher than the disc's version (old games may not have an app version)
- if (entry->info.app_ver == cat_unknown_localized || std::stod(other->info.app_ver) > std::stod(entry->info.app_ver))
- {
- entry->info.app_ver = other->info.app_ver;
- }
- // Update the firmware version if possible and if it's higher than the disc's version
- if (other->info.fw != cat_unknown_localized && std::stod(other->info.fw) > std::stod(entry->info.fw))
- {
- entry->info.fw = other->info.fw;
- }
- // Update the parental level if possible and if it's higher than the disc's level
- if (other->info.parental_lvl != 0 && other->info.parental_lvl > entry->info.parental_lvl)
- {
- entry->info.parental_lvl = other->info.parental_lvl;
- }
+ entry->info.app_ver = other->info.app_ver;
}
- catch (const std::exception& e)
+ // Update the firmware version if possible and if it's higher than the disc's version
+ if (other->info.fw != cat_unknown_localized && version_is_bigger(other->info.fw, entry->info.fw, entry->info.serial, false))
{
- game_list_log.error("Failed to update the displayed version numbers for title ID %s\n%s thrown: %s", entry->info.serial, typeid(e).name(), e.what());
+ entry->info.fw = other->info.fw;
+ }
+ // Update the parental level if possible and if it's higher than the disc's level
+ if (other->info.parental_lvl != 0 && other->info.parental_lvl > entry->info.parental_lvl)
+ {
+ entry->info.parental_lvl = other->info.parental_lvl;
}
}
}
diff --git a/rpcs3/rpcs3qt/register_editor_dialog.cpp b/rpcs3/rpcs3qt/register_editor_dialog.cpp
index a938eb6c1d..63644596b5 100644
--- a/rpcs3/rpcs3qt/register_editor_dialog.cpp
+++ b/rpcs3/rpcs3qt/register_editor_dialog.cpp
@@ -147,7 +147,7 @@ void register_editor_dialog::OnOkay(const std::shared_ptr& _cpu)
while (value.length() < 32) value = "0" + value;
const auto first_brk = reg.find('[');
- try
+ // TODO: handle invalid conversions
{
if (first_brk != umax)
{
@@ -182,9 +182,6 @@ void register_editor_dialog::OnOkay(const std::shared_ptr& _cpu)
return;
}
}
- catch (std::invalid_argument&) //if any of the stoull conversion fail
- {
- }
}
else
{
@@ -192,7 +189,7 @@ void register_editor_dialog::OnOkay(const std::shared_ptr& _cpu)
while (value.length() < 32) value = "0" + value;
const auto first_brk = reg.find('[');
- try
+ // TODO: handle invalid conversions
{
if (first_brk != umax)
{
@@ -207,9 +204,6 @@ void register_editor_dialog::OnOkay(const std::shared_ptr& _cpu)
}
}
}
- catch (std::invalid_argument&)
- {
- }
}
QMessageBox::critical(this, tr("Error"), tr("This value could not be converted.\nNo changes were made."));
}
diff --git a/rpcs3/rpcs3qt/trophy_manager_dialog.cpp b/rpcs3/rpcs3qt/trophy_manager_dialog.cpp
index 9b0fc70fc2..98db2bc8b2 100644
--- a/rpcs3/rpcs3qt/trophy_manager_dialog.cpp
+++ b/rpcs3/rpcs3qt/trophy_manager_dialog.cpp
@@ -710,15 +710,12 @@ void trophy_manager_dialog::StartTrophyLoadThreads()
{
const std::string dir_name = sstr(folder_list.value(i));
gui_log.trace("Loading trophy dir: %s", dir_name);
- try
- {
- LoadTrophyFolderToDB(dir_name);
- }
- catch (const std::exception& e)
+
+ if (!LoadTrophyFolderToDB(dir_name))
{
// TODO: Add error checks & throws to LoadTrophyFolderToDB so that they can be caught here.
// Also add a way of showing the number of corrupted/invalid folders in UI somewhere.
- gui_log.error("Exception occurred while parsing folder %s for trophies: %s", dir_name, e.what());
+ gui_log.error("Error occurred while parsing folder %s for trophies.", dir_name);
}
}));
diff --git a/rpcs3/util/cereal.cpp b/rpcs3/util/cereal.cpp
new file mode 100644
index 0000000000..02598ba918
--- /dev/null
+++ b/rpcs3/util/cereal.cpp
@@ -0,0 +1,10 @@
+#include
+#include "Utilities/Thread.h"
+
+namespace cereal
+{
+ [[noreturn]] void throw_exception(const std::string& err)
+ {
+ report_fatal_error(err);
+ }
+}
diff --git a/rpcs3/util/logs.cpp b/rpcs3/util/logs.cpp
index d7e4f6009e..8cc7bc1550 100644
--- a/rpcs3/util/logs.cpp
+++ b/rpcs3/util/logs.cpp
@@ -307,8 +307,8 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, ...) co
const u64 stamp = get_stamp();
// Get text, extract va_args
- thread_local std::string text;
- thread_local std::vector args;
+ /*constinit thread_local*/ std::string text;
+ /*constinit thread_local*/ std::basic_string args;
static constexpr fmt_type_info empty_sup{};
@@ -316,7 +316,7 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, ...) co
for (auto v = sup; v && v->fmt_string; v++)
args_count++;
- text.clear();
+ text.reserve(50000);
args.resize(args_count);
va_list c_args;
@@ -589,7 +589,8 @@ logs::file_listener::file_listener(const std::string& path, u64 max_size)
void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::string& prefix, const std::string& _text)
{
- thread_local std::string text;
+ /*constinit thread_local*/ std::string text;
+ text.reserve(50000);
// Used character: U+00B7 (Middle Dot)
switch (msg.sev)
diff --git a/rpcs3/util/yaml.cpp b/rpcs3/util/yaml.cpp
new file mode 100644
index 0000000000..71cfde00b7
--- /dev/null
+++ b/rpcs3/util/yaml.cpp
@@ -0,0 +1,17 @@
+#include "util/yaml.hpp"
+
+std::pair yaml_load(const std::string& from)
+{
+ YAML::Node result;
+
+ try
+ {
+ result = YAML::Load(from);
+ }
+ catch(const std::exception& e)
+ {
+ return{YAML::Node(), std::string("YAML exception:\n") + e.what()};
+ }
+
+ return{result, ""};
+}
diff --git a/rpcs3/util/yaml.hpp b/rpcs3/util/yaml.hpp
new file mode 100644
index 0000000000..e36a1744cd
--- /dev/null
+++ b/rpcs3/util/yaml.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include
+#include
+
+#ifdef _MSC_VER
+#pragma warning(push, 0)
+#include "yaml-cpp/yaml.h"
+#pragma warning(pop)
+#else
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wall"
+#pragma GCC diagnostic ignored "-Wextra"
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#include "yaml-cpp/yaml.h"
+#pragma GCC diagnostic pop
+#endif
+
+// Load from string and consume exception
+std::pair yaml_load(const std::string& from);
diff --git a/rpcs3_default.props b/rpcs3_default.props
index 14ebef99eb..4b672af78d 100644
--- a/rpcs3_default.props
+++ b/rpcs3_default.props
@@ -13,10 +13,11 @@
true
- PUGIXML_HEADER_ONLY;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;%(PreprocessorDefinitions)
+ PUGIXML_HEADER_ONLY;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
true
Level3
false
+ false
true
NotUsing
/Zc:throwingNew %(AdditionalOptions)