Disable exception handling.

Use -fno-exceptions in cmake.
On MSVC, enable _HAS_EXCEPTION=0.
Cleanup throw/catch from the source.
Create yaml.cpp enclave because it needs exception to work.
Disable thread_local optimizations in logs.cpp (TODO).
Implement cpu_counter for cpu_threads (moved globals).
This commit is contained in:
Nekotekina 2020-03-09 19:18:39 +03:00
parent 47bbfdd2aa
commit 04dedb17eb
39 changed files with 421 additions and 437 deletions

4
.gitmodules vendored
View File

@ -16,7 +16,7 @@
ignore = dirty ignore = dirty
[submodule "3rdparty/cereal"] [submodule "3rdparty/cereal"]
path = 3rdparty/cereal path = 3rdparty/cereal
url = https://github.com/USCiLab/cereal.git url = https://github.com/RPCS3/cereal.git
ignore = dirty ignore = dirty
[submodule "3rdparty/zlib"] [submodule "3rdparty/zlib"]
path = 3rdparty/zlib path = 3rdparty/zlib
@ -37,7 +37,7 @@
ignore = dirty ignore = dirty
[submodule "3rdparty/yaml-cpp"] [submodule "3rdparty/yaml-cpp"]
path = 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 ignore = dirty
[submodule "3rdparty/libpng"] [submodule "3rdparty/libpng"]
path = 3rdparty/libpng path = 3rdparty/libpng

2
3rdparty/cereal vendored

@ -1 +1 @@
Subproject commit 42a45b6e15fcbd1a3d65b033f5d4d0b2ef6c023d Subproject commit 60c69df968d1c72c998cd5f23ba34e2e3718a84b

2
3rdparty/yaml-cpp vendored

@ -1 +1 @@
Subproject commit eca9cfd64899525d0a61abb0553849676a0fe511 Subproject commit 6a211f0bc71920beef749e6c35d7d1bcc2447715

View File

@ -37,6 +37,11 @@
<Import Project="..\rpcs3_release.props" /> <Import Project="..\rpcs3_release.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<ExceptionHandling>Sync</ExceptionHandling>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="yaml-cpp\src\binary.cpp"> <ClCompile Include="yaml-cpp\src\binary.cpp">
</ClCompile> </ClCompile>

View File

@ -1,11 +1,14 @@
#include "stdafx.h" #include "stdafx.h"
#include "Config.h" #include "Config.h"
#include "Utilities/types.h"
#include "yaml-cpp/yaml.h" #include "util/yaml.hpp"
#include <typeinfo> #include <typeinfo>
#include <charconv> #include <charconv>
[[noreturn]] void report_fatal_error(const std::string&);
LOG_CHANNEL(cfg_log, "CFG"); LOG_CHANNEL(cfg_log, "CFG");
namespace cfg namespace cfg
@ -15,7 +18,7 @@ namespace cfg
{ {
if (_type != type::node) 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) 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) 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<std::string>&&) bool _base::from_list(std::vector<std::string>&&)
{ {
fmt::throw_exception("from_list() purecall" HERE); report_fatal_error("from_list() purecall" HERE);
} }
// Emit YAML // Emit YAML
@ -302,14 +305,17 @@ std::string cfg::node::to_string() const
return {out.c_str(), out.size()}; 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); auto [result, error] = yaml_load(value);
return true;
} if (error.empty())
catch (const std::exception& e) {
{ cfg::decode(result, *this, dynamic);
cfg_log.fatal("%s thrown: %s", typeid(e).name(), e.what()); return true;
}
cfg_log.fatal("Failed to load node: %s", error);
return false; return false;
} }

View File

@ -60,22 +60,6 @@ void fmt_class_string<std::thread::id>::format(std::string& out, u64 arg)
out += ss.str(); 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 #ifndef _WIN32
bool IsDebuggerPresent() 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) if (rsx::g_access_violation_handler)
{ {
bool handled = false; if (cpu)
try
{ {
if (cpu) vm::temporary_unlock(*cpu);
{
vm::temporary_unlock(*cpu);
}
handled = rsx::g_access_violation_handler(addr, is_writing);
} }
catch (const std::exception& e)
{
rsx_log.fatal("g_access_violation_handler(0x%x, %d): %s", addr, is_writing, e.what());
if (cpu) bool handled = rsx::g_access_violation_handler(addr, is_writing);
{
cpu->state += cpu_flag::dbg_pause;
if (cpu->test_stopped())
{
std::terminate();
}
}
return false;
}
if (handled) if (handled)
{ {
@ -1769,7 +1732,7 @@ const bool s_exception_handler_set = []() -> bool
if (::sigaction(SIGSEGV, &sa, NULL) == -1) 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(); std::abort();
} }
@ -1779,6 +1742,23 @@ const bool s_exception_handler_set = []() -> bool
#endif #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; thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
DECLARE(thread_ctrl::g_native_core_layout) { native_core_arrangement::undefined }; DECLARE(thread_ctrl::g_native_core_layout) { native_core_arrangement::undefined };

View File

@ -15,9 +15,6 @@
// Report error and call std::abort(), defined in main.cpp // Report error and call std::abort(), defined in main.cpp
[[noreturn]] void report_fatal_error(const std::string&); [[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 // Hardware core layout
enum class native_core_arrangement : u32 enum class native_core_arrangement : u32
{ {
@ -256,9 +253,9 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
// Type-erased thread entry point // Type-erased thread entry point
#ifdef _WIN32 #ifdef _WIN32
static inline uint __stdcall entry_point(void* arg) try static inline uint __stdcall entry_point(void* arg)
#else #else
static inline void* entry_point(void* arg) try static inline void* entry_point(void* arg)
#endif #endif
{ {
const auto _this = static_cast<named_thread*>(static_cast<thread*>(arg)); const auto _this = static_cast<named_thread*>(static_cast<thread*>(arg));
@ -272,10 +269,6 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
thread::finalize(); thread::finalize();
return 0; return 0;
} }
catch (...)
{
catch_all_exceptions();
}
bool entry_point() bool entry_point()
{ {

View File

@ -1,5 +1,5 @@
#include "bin_patch.h" #include "bin_patch.h"
#include <yaml-cpp/yaml.h> #include "util/yaml.hpp"
#include "File.h" #include "File.h"
#include "Config.h" #include "Config.h"
@ -34,15 +34,11 @@ void patch_engine::append(const std::string& patch)
{ {
if (fs::file f{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()); patch_log.fatal("Failed to load patch file %s:\n%s", patch, error);
}
catch (const std::exception& e)
{
patch_log.fatal("Failed to load patch file %s\n%s thrown: %s", patch, typeid(e).name(), e.what());
return; return;
} }

View File

@ -32,6 +32,8 @@ target_sources(rpcs3_emu PRIVATE
../util/shared_cptr.cpp ../util/shared_cptr.cpp
../util/fixed_typemap.cpp ../util/fixed_typemap.cpp
../util/logs.cpp ../util/logs.cpp
../util/yaml.cpp
../util/cereal.cpp
../../Utilities/bin_patch.cpp ../../Utilities/bin_patch.cpp
../../Utilities/cond.cpp ../../Utilities/cond.cpp
../../Utilities/Config.cpp ../../Utilities/Config.cpp
@ -62,6 +64,12 @@ else()
set_source_files_properties("../../Utilities/JIT.cpp" PROPERTIES COMPILE_FLAGS -fno-rtti) set_source_files_properties("../../Utilities/JIT.cpp" PROPERTIES COMPILE_FLAGS -fno-rtti)
endif() 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 # Crypto
target_sources(rpcs3_emu PRIVATE target_sources(rpcs3_emu PRIVATE

View File

@ -243,28 +243,83 @@ using cpu_profiler = named_thread<cpu_prof>;
thread_local cpu_thread* g_tls_current_cpu_thread = nullptr; thread_local cpu_thread* g_tls_current_cpu_thread = nullptr;
// For synchronizing suspend_all operation struct cpu_counter
alignas(64) shared_mutex g_cpu_suspend_lock; {
// For synchronizing suspend_all operation
alignas(64) shared_mutex cpu_suspend_lock;
// Semaphore for global thread array (global counter) // Semaphore for global thread array (global counter)
alignas(64) atomic_t<u32> g_cpu_array_sema{0}; alignas(64) atomic_t<u32> cpu_array_sema{0};
// Semaphore subdivision for each array slot (64 x N in total) // Semaphore subdivision for each array slot (64 x N in total)
atomic_t<u64> g_cpu_array_bits[6]{}; atomic_t<u64> cpu_array_bits[6]{};
// All registered threads // All registered threads
atomic_t<cpu_thread*> g_cpu_array[sizeof(g_cpu_array_bits) * 8]{}; atomic_t<cpu_thread*> 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 <typename F> template <typename F>
void for_all_cpu(F&& func) noexcept void for_all_cpu(F&& func) noexcept
{ {
for (u32 i = 0; i < ::size32(g_cpu_array_bits); i++) auto ctr = g_fxo->get<cpu_counter>();
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); 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); func(cpu);
} }
@ -301,6 +356,12 @@ void cpu_thread::operator()()
} }
} }
while (!g_fxo->get<cpu_counter>() && !g_fxo->get<cpu_profiler>())
{
// 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) if (id_type() == 1 && false)
{ {
g_fxo->get<cpu_profiler>()->registered.push(id); g_fxo->get<cpu_profiler>()->registered.push(id);
@ -312,67 +373,51 @@ void cpu_thread::operator()()
} }
// Register thread in g_cpu_array // 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<cpu_counter>()->add(this);
if (array_slot == umax)
{ {
sys_log.fatal("Too many threads."); sys_log.fatal("Too many threads.");
return; 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 static thread_local struct thread_cleanup_t
{ {
cpu_thread* _this; cpu_thread* _this;
u64 slot; u64 slot;
std::string name;
thread_cleanup_t(cpu_thread* _this, u64 slot) thread_cleanup_t(cpu_thread* _this, u64 slot)
: _this(_this) : _this(_this)
, slot(slot) , slot(slot)
, name(thread_ctrl::get_name())
{ {
} }
~thread_cleanup_t() void cleanup()
{ {
if (_this == nullptr)
{
return;
}
if (auto ptr = vm::g_tls_locked) if (auto ptr = vm::g_tls_locked)
{ {
ptr->compare_and_swap(_this, nullptr); ptr->compare_and_swap(_this, nullptr);
} }
// Unregister and wait if necessary g_fxo->get<cpu_counter>()->remove(_this, slot);
_this->state += cpu_flag::wait;
if (g_cpu_array[slot].exchange(nullptr) != _this) _this = nullptr;
sys_log.fatal("Inconsistency for array slot %u", slot); }
g_cpu_array_bits[slot / 64] &= ~(1ull << (slot % 64));
g_cpu_array_sema--; ~thread_cleanup_t()
g_cpu_suspend_lock.lock_unlock(); {
if (_this)
{
sys_log.warning("CPU Thread '%s' terminated abnormally:\n%s", name, _this->dump());
cleanup();
}
} }
} cleanup{this, array_slot}; } cleanup{this, array_slot};
@ -382,23 +427,16 @@ void cpu_thread::operator()()
// Check stop status // Check stop status
if (!(state & cpu_flag::stop)) if (!(state & cpu_flag::stop))
{ {
try cpu_task();
{
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;
}
state -= cpu_flag::ret; state -= cpu_flag::ret;
continue; continue;
} }
thread_ctrl::wait(); thread_ctrl::wait();
} }
// Complete cleanup gracefully
cleanup.cleanup();
} }
cpu_thread::~cpu_thread() cpu_thread::~cpu_thread()
@ -493,7 +531,7 @@ bool cpu_thread::check_state() noexcept
else else
{ {
// If only cpu_flag::pause was set, notification won't arrive // If only cpu_flag::pause was set, notification won't arrive
g_cpu_suspend_lock.lock_unlock(); g_fxo->get<cpu_counter>()->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; m_this->state += cpu_flag::wait;
} }
g_cpu_suspend_lock.lock_vip(); g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_vip();
for_all_cpu([](cpu_thread* cpu) 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() cpu_thread::suspend_all::~suspend_all()
{ {
// Make sure the latest thread does the cleanup and notifies others // 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_counter>()->cpu_suspend_lock.downgrade_unique_vip_lock_to_low_or_unlock())
{ {
for_all_cpu([&](cpu_thread* cpu) for_all_cpu([&](cpu_thread* cpu)
{ {
cpu->state -= cpu_flag::pause; cpu->state -= cpu_flag::pause;
}); });
g_cpu_suspend_lock.unlock_low(); g_fxo->get<cpu_counter>()->cpu_suspend_lock.unlock_low();
} }
else else
{ {
g_cpu_suspend_lock.lock_unlock(); g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
} }
if (m_this) if (m_this)
@ -640,7 +678,7 @@ void cpu_thread::stop_all() noexcept
} }
else else
{ {
::vip_lock lock(g_cpu_suspend_lock); ::vip_lock lock(g_fxo->get<cpu_counter>()->cpu_suspend_lock);
for_all_cpu([](cpu_thread* cpu) 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."); sys_log.notice("All CPU threads have been signaled.");
while (g_cpu_array_sema) while (g_fxo->get<cpu_counter>()->cpu_array_sema)
{ {
std::this_thread::sleep_for(10ms); std::this_thread::sleep_for(10ms);
} }

View File

@ -138,15 +138,9 @@ struct content_permission final
bool success = false; bool success = false;
fs::g_tls_error = fs::error::ok; fs::g_tls_error = fs::error::ok;
try if (temp.size() <= 1 || fs::remove_all(temp))
{
if (temp.size() <= 1 || fs::remove_all(temp))
{
success = true;
}
}
catch (...)
{ {
success = true;
} }
if (!success) if (!success)

View File

@ -151,7 +151,7 @@ void pngDecError(png_structp png_ptr, png_const_charp error_message)
{ {
cellPngDec.error("%s", error_message); cellPngDec.error("%s", error_message);
// we can't return here or libpng blows up // 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 // 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); png_set_progressive_read_fn(stream->png_ptr, stream.get_ptr(), pngDecInfoCallback, pngDecRowCallback, pngDecEndCallback);
// push header tag to libpng to keep us in sync // push header tag to libpng to keep us in sync
try png_process_data(stream->png_ptr, stream->info_ptr, header, 8);
{
png_process_data(stream->png_ptr, stream->info_ptr, header, 8);
}
catch (LibPngCustomException&)
{
return CELL_PNGDEC_ERROR_HEADER;
}
} }
else else
{ {
@ -729,15 +722,7 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr<u8> d
if (stream->buffer->length > stream->buffer->cursor) if (stream->buffer->length > stream->buffer->cursor)
{ {
u8* data = static_cast<u8*>(stream->buffer->data.get_ptr()) + stream->buffer->cursor; u8* data = static_cast<u8*>(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);
{
png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length - stream->buffer->cursor);
}
catch (LibPngCustomException&)
{
freeMem();
return CELL_PNGDEC_ERROR_FATAL;
}
streamInfo->decodedStrmSize = ::narrow<u32>(stream->buffer->length); streamInfo->decodedStrmSize = ::narrow<u32>(stream->buffer->length);
} }
@ -747,15 +732,7 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr<u8> d
{ {
stream->cbCtrlStream.cbCtrlStrmFunc(ppu, streamInfo, streamParam, stream->cbCtrlStream.cbCtrlStrmArg); stream->cbCtrlStream.cbCtrlStrmFunc(ppu, streamInfo, streamParam, stream->cbCtrlStream.cbCtrlStrmArg);
streamInfo->decodedStrmSize += streamParam->strmSize; streamInfo->decodedStrmSize += streamParam->strmSize;
try png_process_data(stream->png_ptr, stream->info_ptr, static_cast<u8*>(streamParam->strmPtr.get_ptr()), streamParam->strmSize);
{
png_process_data(stream->png_ptr, stream->info_ptr, static_cast<u8*>(streamParam->strmPtr.get_ptr()), streamParam->strmSize);
}
catch (LibPngCustomException&)
{
freeMem();
return CELL_PNGDEC_ERROR_FATAL;
}
} }
freeMem(); freeMem();
@ -767,7 +744,6 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr<u8> d
// Decode the image // Decode the image
// todo: commandptr // todo: commandptr
try
{ {
for (u32 j = 0; j < stream->passes; j++) for (u32 j = 0; j < stream->passes; j++)
{ {
@ -779,10 +755,6 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr<u8> d
} }
png_read_end(stream->png_ptr, stream->info_ptr); 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 // 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 // lets push what we have so far
u8* data = static_cast<u8*>(stream->buffer->data.get_ptr()) + stream->buffer->cursor; u8* data = static_cast<u8*>(stream->buffer->data.get_ptr()) + stream->buffer->cursor;
try png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length);
{
png_process_data(stream->png_ptr, stream->info_ptr, data, stream->buffer->length);
}
catch (LibPngCustomException&)
{
return CELL_PNGDEC_ERROR_HEADER;
}
// lets hope we pushed enough for callback // lets hope we pushed enough for callback
pngSetHeader(stream.get_ptr()); pngSetHeader(stream.get_ptr());

View File

@ -114,7 +114,9 @@ void cellSpursModuleExit(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100);
spu.pc = ctxt->exitToKernelAddr; spu.pc = ctxt->exitToKernelAddr;
throw SpursModuleExit();
// TODO: use g_escape for actual long jump
//throw SpursModuleExit();
} }
// Execute a DMA operation // Execute a DMA operation
@ -728,7 +730,6 @@ bool spursSysServiceEntry(spu_thread& spu)
auto arg = spu.gpr[4]._u64[1]; auto arg = spu.gpr[4]._u64[1];
auto pollStatus = spu.gpr[5]._u32[3]; auto pollStatus = spu.gpr[5]._u32[3];
try
{ {
if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID)
{ {
@ -743,10 +744,6 @@ bool spursSysServiceEntry(spu_thread& spu)
cellSpursModuleExit(spu); cellSpursModuleExit(spu);
} }
catch (SpursModuleExit)
{
}
return false; return false;
} }
@ -1326,7 +1323,6 @@ bool spursTasksetEntry(spu_thread& spu)
//spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry); //spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry);
//spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry); //spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry);
try
{ {
// Initialise the taskset policy module // Initialise the taskset policy module
spursTasksetInit(spu, pollStatus); spursTasksetInit(spu, pollStatus);
@ -1334,9 +1330,6 @@ bool spursTasksetEntry(spu_thread& spu)
// Dispatch // Dispatch
spursTasksetDispatch(spu); spursTasksetDispatch(spu);
} }
catch (SpursModuleExit)
{
}
return false; return false;
} }
@ -1346,7 +1339,6 @@ bool spursTasksetSyscallEntry(spu_thread& spu)
{ {
auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700); auto ctxt = vm::_ptr<SpursTasksetContext>(spu.offset + 0x2700);
try
{ {
// Save task context // Save task context
ctxt->savedContextLr = spu.gpr[0]; ctxt->savedContextLr = spu.gpr[0];
@ -1365,9 +1357,6 @@ bool spursTasksetSyscallEntry(spu_thread& spu)
// spursTasksetResumeTask(spu); // spursTasksetResumeTask(spu);
//} //}
} }
catch (SpursModuleExit)
{
}
return false; return false;
} }

View File

@ -5,7 +5,7 @@
#include "PPUModule.h" #include "PPUModule.h"
#include <unordered_set> #include <unordered_set>
#include "yaml-cpp/yaml.h" #include "util/yaml.hpp"
#include "Utilities/asm.h" #include "Utilities/asm.h"
LOG_CHANNEL(ppu_validator); LOG_CHANNEL(ppu_validator);
@ -54,7 +54,13 @@ void ppu_module::validate(u32 reloc)
// Load custom PRX configuration if available // Load custom PRX configuration if available
if (fs::file yml{path + ".yml"}) 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; u32 index = 0;

View File

@ -859,16 +859,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
} }
}; };
try exec_task();
{
exec_task();
}
catch (...)
{
at_ret();
throw;
}
at_ret(); at_ret();
} }

View File

@ -4357,7 +4357,7 @@ Value* PPUTranslator::GetVr(u32 vr, VrType type)
case VrType::i128: return m_ir->CreateBitCast(value, GetType<u128>()); case VrType::i128: return m_ir->CreateBitCast(value, GetType<u128>());
} }
throw std::logic_error("GetVr(): invalid type"); report_fatal_error("GetVr(): invalid type");
} }
void PPUTranslator::SetVr(u32 vr, Value* value) void PPUTranslator::SetVr(u32 vr, Value* value)
@ -4435,7 +4435,7 @@ void PPUTranslator::SetFPRF(Value* value, bool set_cr)
const bool is32 = const bool is32 =
value->getType()->isFloatTy() ? true : value->getType()->isFloatTy() ? true :
value->getType()->isDoubleTy() ? false : 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 zero = ConstantFP::get(value->getType(), 0.0);
//const auto is_nan = m_ir->CreateFCmpUNO(value, zero); //const auto is_nan = m_ir->CreateFCmpUNO(value, zero);

View File

@ -1154,7 +1154,7 @@ void spu_recompiler_base::branch(spu_thread& spu, void*, u8* rip)
spu_runtime::g_tail_escape(&spu, func, 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 // Select opcode table
const auto& 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; 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<u32>* ls, u32 entry_point) spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point)
{ {
@ -4608,19 +4603,7 @@ public:
} }
// Execute recompiler function (TODO) // Execute recompiler function (TODO)
try (this->*g_decoder.decode(op))({op});
{
(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;
}
} }
// Finalize block with fallthrough if necessary // Finalize block with fallthrough if necessary
@ -4994,7 +4977,6 @@ public:
} }
} }
try
{ {
m_interp_bblock = nullptr; 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) if (last_itype != itype && g_cfg.core.spu_decoder != spu_decoder_type::llvm)

View File

@ -303,21 +303,13 @@ bool gdb_thread::read_cmd(gdb_cmd& out_cmd)
{ {
while (true) 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); ack(false);
}
catch (const std::runtime_error& e)
{
GDB.error("Error: %s", e.what());
return false;
}
} }
} }
@ -866,7 +858,7 @@ void gdb_thread::operator()()
Emu.Pause(); Emu.Pause();
} }
try { {
char hostbuf[32]; char hostbuf[32];
inet_ntop(client.sin_family, reinterpret_cast<void*>(&client.sin_addr), hostbuf, 32); inet_ntop(client.sin_family, reinterpret_cast<void*>(&client.sin_addr), hostbuf, 32);
GDB.success("Got connection to GDB debug server from %s:%d.", hostbuf, client.sin_port); 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());
}
} }
} }

View File

@ -242,13 +242,6 @@ namespace rsx
void rsx_replay_thread::operator()() void rsx_replay_thread::operator()()
{ {
try on_task();
{
on_task();
}
catch (const std::exception& e)
{
rsx_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
}
} }
} }

View File

@ -2396,42 +2396,6 @@ public:
namespace glsl 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 class shader
{ {
public: public:
@ -2533,7 +2497,7 @@ public:
error_msg = buf.get(); error_msg = buf.get();
} }
throw compilation_exception(error_msg); rsx_log.fatal("Compilation failed: %s", error_msg);
} }
return *this; return *this;
@ -2655,7 +2619,8 @@ public:
} }
else else
{ {
throw not_found_exception(name); rsx_log.fatal("%s not found.", name);
return -1;
} }
} }
@ -2663,7 +2628,8 @@ public:
if (result < 0) if (result < 0)
{ {
throw not_found_exception(name); rsx_log.fatal("%s not found.", name);
return result;
} }
locations[name] = result; locations[name] = result;
@ -2749,7 +2715,7 @@ public:
error_msg = buf.get(); error_msg = buf.get();
} }
throw link_exception(error_msg); rsx_log.fatal("Linkage failed: %s", error_msg);
} }
} }

View File

@ -42,7 +42,7 @@ namespace
case rsx::index_array_type::u16: return GL_UNSIGNED_SHORT; case rsx::index_array_type::u16: return GL_UNSIGNED_SHORT;
case rsx::index_array_type::u32: return GL_UNSIGNED_INT; case rsx::index_array_type::u32: return GL_UNSIGNED_INT;
} }
throw; fmt::throw_exception("Invalid index array type (%u)", static_cast<u8>(type));
} }
struct vertex_input_state struct vertex_input_state

View File

@ -9,6 +9,7 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <charconv>
namespace rsx namespace rsx
{ {
@ -21,22 +22,65 @@ namespace rsx
hex_color.erase(0, 1); hex_color.erase(0, 1);
} }
unsigned long hexval; unsigned hexval = 0;
const size_t len = hex_color.length(); const auto len = hex_color.length();
try if (len != 6 && len != 8)
{ {
if (len != 6 && len != 8) rsx_log.error("Incompatible color code: '%s' has wrong length: %d", hex_color, len);
{
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());
return color4f(0.0f, 0.0f, 0.0f, 0.0f); 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 r = (len == 8 ? (hexval >> 24) : (hexval >> 16)) & 0xff;
const int g = (len == 8 ? (hexval >> 16) : (hexval >> 8)) & 0xff; const int g = (len == 8 ? (hexval >> 16) : (hexval >> 8)) & 0xff;

View File

@ -442,7 +442,6 @@ namespace rsx
void thread::operator()() void thread::operator()()
{ {
try
{ {
// Wait for startup (TODO) // Wait for startup (TODO)
while (m_rsx_thread_exiting) while (m_rsx_thread_exiting)
@ -457,10 +456,6 @@ namespace rsx
on_task(); on_task();
} }
catch (const std::exception& e)
{
rsx_log.fatal("%s thrown: %s", typeid(e).name(), e.what());
}
on_exit(); on_exit();
} }

View File

@ -52,7 +52,7 @@ namespace vk
case rsx::index_array_type::u16: case rsx::index_array_type::u16:
return VK_INDEX_TYPE_UINT16; return VK_INDEX_TYPE_UINT16;
} }
throw; fmt::throw_exception("Invalid index array type (%u)", static_cast<u8>(type));
} }
} }

View File

@ -30,7 +30,7 @@
#include "../Crypto/unself.h" #include "../Crypto/unself.h"
#include "../Crypto/unpkg.h" #include "../Crypto/unpkg.h"
#include <yaml-cpp/yaml.h> #include "util/yaml.hpp"
#include "cereal/archives/binary.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; m_title_id = title_id;
} }
try
{ {
Init(); Init();
// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations) // 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()) 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; 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) void Emulator::Run(bool start_playtime)

View File

@ -2,7 +2,7 @@
if(MSVC) 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} /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} /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") 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) CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
add_compile_options(-Wall) add_compile_options(-Wall)
add_compile_options(-fexceptions) add_compile_options(-fno-exceptions)
add_compile_options(-ftemplate-depth=1024) add_compile_options(-ftemplate-depth=1024)
add_compile_options(-msse -msse2 -mcx16) add_compile_options(-msse -msse2 -mcx16)
add_compile_options(-fno-strict-aliasing) add_compile_options(-fno-strict-aliasing)

View File

@ -87,6 +87,13 @@
<ClCompile Include="util\atomic2.cpp"> <ClCompile Include="util\atomic2.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="util\yaml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<ExceptionHandling>Sync</ExceptionHandling>
</ClCompile>
<ClCompile Include="util\cereal.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="util\shared_cptr.cpp"> <ClCompile Include="util\shared_cptr.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>

View File

@ -869,6 +869,15 @@
<ClCompile Include="util\atomic2.cpp"> <ClCompile Include="util\atomic2.cpp">
<Filter>Utilities</Filter> <Filter>Utilities</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="util\yaml.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="util\cereal.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="util\yaml.hpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="util\shared_cptr.cpp"> <ClCompile Include="util\shared_cptr.cpp">
<Filter>Utilities</Filter> <Filter>Utilities</Filter>
</ClCompile> </ClCompile>

View File

@ -38,9 +38,11 @@ DYNAMIC_IMPORT("ntdll.dll", NtSetTimerResolution, NTSTATUS(ULONG DesiredResoluti
#endif #endif
#include "Utilities/sysinfo.h" #include "Utilities/sysinfo.h"
#include "Utilities/Config.h"
#include "rpcs3_version.h" #include "rpcs3_version.h"
#include "Emu/System.h" #include "Emu/System.h"
#include <thread> #include <thread>
#include <charconv>
inline std::string sstr(const QString& _in) { return _in.toStdString(); } 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_val = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
auto rounding_str = std::to_string(static_cast<int>(rounding_val)); auto rounding_str = std::to_string(static_cast<int>(rounding_val));
const auto i_rounding = find_arg(arg_rounding, argc, argv); const auto i_rounding = find_arg(arg_rounding, argc, argv);
if (i_rounding) if (i_rounding)
{ {
const auto i_rounding_2 = (argc > (i_rounding + 1)) ? (i_rounding + 1) : 0; const auto i_rounding_2 = (argc > (i_rounding + 1)) ? (i_rounding + 1) : 0;
if (i_rounding_2) if (i_rounding_2)
{ {
const auto arg_val = argv[i_rounding_2]; const auto arg_val = argv[i_rounding_2];
try const auto arg_len = std::strlen(arg_val);
{ s64 rounding_val_cli = 0;
const auto rounding_val_cli = std::stoi(arg_val);
if (rounding_val_cli >= static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::Unset) && rounding_val_cli <= static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)) if (!cfg::try_to_int64(&rounding_val_cli, arg_val, static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::Unset), static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)))
{
rounding_val = static_cast<Qt::HighDpiScaleFactorRoundingPolicy>(rounding_val_cli);
rounding_str = std::to_string(static_cast<int>(rounding_val));
}
else
{
throw std::exception();
}
}
catch (const std::exception&)
{ {
std::cout << "The value " << arg_val << " for " << arg_rounding << " is not allowed. Please use a valid value for Qt::HighDpiScaleFactorRoundingPolicy.\n"; 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<Qt::HighDpiScaleFactorRoundingPolicy>(static_cast<int>(rounding_val_cli));
rounding_str = std::to_string(static_cast<int>(rounding_val));
}
} }
} }
try
{ {
rounding_str = qEnvironmentVariable("QT_SCALE_FACTOR_ROUNDING_POLICY", rounding_str.c_str()).toStdString(); 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<int>(Qt::HighDpiScaleFactorRoundingPolicy::Unset) && rounding_val_final <= static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)) s64 rounding_val_final = 0;
if (cfg::try_to_int64(&rounding_val_final, rounding_str, static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::Unset), static_cast<int>(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)))
{ {
rounding_val = static_cast<Qt::HighDpiScaleFactorRoundingPolicy>(rounding_val_final); rounding_val = static_cast<Qt::HighDpiScaleFactorRoundingPolicy>(static_cast<int>(rounding_val_final));
rounding_str = std::to_string(static_cast<int>(rounding_val)); rounding_str = std::to_string(static_cast<int>(rounding_val));
} }
else 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); QApplication::setHighDpiScaleFactorRoundingPolicy(rounding_val);
} }

View File

@ -127,7 +127,6 @@
<BrowseInformation>false</BrowseInformation> <BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>$(IntDir)</ObjectFileName> <ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_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)</PreprocessorDefinitions> <PreprocessorDefinitions>_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)</PreprocessorDefinitions>
@ -180,7 +179,6 @@
<BrowseInformation>false</BrowseInformation> <BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>$(IntDir)</ObjectFileName> <ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_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)</PreprocessorDefinitions> <PreprocessorDefinitions>_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)</PreprocessorDefinitions>
@ -233,7 +231,6 @@
<BrowseInformation>false</BrowseInformation> <BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>$(IntDir)</ObjectFileName> <ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_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)</PreprocessorDefinitions> <PreprocessorDefinitions>_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)</PreprocessorDefinitions>
@ -287,7 +284,6 @@
<BrowseInformation>false</BrowseInformation> <BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>$(IntDir)</ObjectFileName> <ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_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)</PreprocessorDefinitions> <PreprocessorDefinitions>_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)</PreprocessorDefinitions>

View File

@ -6,8 +6,6 @@
#include <QClipboard> #include <QClipboard>
#include <QGuiApplication> #include <QGuiApplication>
#include <yaml-cpp/yaml.h>
#include "cheat_manager.h" #include "cheat_manager.h"
#include "Emu/System.h" #include "Emu/System.h"
@ -19,6 +17,7 @@
#include "Emu/Cell/PPUAnalyser.h" #include "Emu/Cell/PPUAnalyser.h"
#include "Emu/Cell/PPUFunction.h" #include "Emu/Cell/PPUFunction.h"
#include "util/yaml.hpp"
#include "Utilities/StrUtil.h" #include "Utilities/StrUtil.h"
LOG_CHANNEL(log_cheat, "Cheat"); LOG_CHANNEL(log_cheat, "Cheat");
@ -110,9 +109,14 @@ std::string cheat_info::to_str() const
cheat_engine::cheat_engine() 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) 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);
} }
} }

View File

@ -18,6 +18,7 @@
#include "Loader/PSF.h" #include "Loader/PSF.h"
#include "Utilities/types.h" #include "Utilities/types.h"
#include "Utilities/lockless.h" #include "Utilities/lockless.h"
#include "util/yaml.hpp"
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
@ -543,24 +544,23 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
auto get_games = []() -> YAML::Node 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()); game_list_log.error("Failed to load games.yml: %s", error);
}
else
{
game_list_log.error("Failed to load games.yml, check permissions.");
return {}; return {};
} }
return result;
} }
catch (...) else
{ {
// YAML exception aren't very useful so just ignore them game_list_log.error("Failed to load games.yml, check permissions.");
game_list_log.fatal("Failed to parse games.yml");
return {}; return {};
} }
@ -616,7 +616,6 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
{ {
const Localized thread_localized; const Localized thread_localized;
try
{ {
const std::string sfo_dir = Emulator::GetSfoDirFromGamePath(dir, Emu.GetUsr()); const std::string sfo_dir = Emulator::GetSfoDirFromGamePath(dir, Emu.GetUsr());
const fs::file sfo_file(sfo_dir + "/PARAM.SFO"); 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>(gui_game_info{game, qt_cat, compat, icon, pxmap, hasCustomConfig, hasCustomPadConfig})); games.push(std::make_shared<gui_game_info>(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()) 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) for (const auto& other : m_game_data)
{ {
// The patch is game data and must have the same serial and an app version // 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<char> 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) 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) entry->info.app_ver = other->info.app_ver;
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;
}
} }
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;
} }
} }
} }

View File

@ -147,7 +147,7 @@ void register_editor_dialog::OnOkay(const std::shared_ptr<cpu_thread>& _cpu)
while (value.length() < 32) value = "0" + value; while (value.length() < 32) value = "0" + value;
const auto first_brk = reg.find('['); const auto first_brk = reg.find('[');
try // TODO: handle invalid conversions
{ {
if (first_brk != umax) if (first_brk != umax)
{ {
@ -182,9 +182,6 @@ void register_editor_dialog::OnOkay(const std::shared_ptr<cpu_thread>& _cpu)
return; return;
} }
} }
catch (std::invalid_argument&) //if any of the stoull conversion fail
{
}
} }
else else
{ {
@ -192,7 +189,7 @@ void register_editor_dialog::OnOkay(const std::shared_ptr<cpu_thread>& _cpu)
while (value.length() < 32) value = "0" + value; while (value.length() < 32) value = "0" + value;
const auto first_brk = reg.find('['); const auto first_brk = reg.find('[');
try // TODO: handle invalid conversions
{ {
if (first_brk != umax) if (first_brk != umax)
{ {
@ -207,9 +204,6 @@ void register_editor_dialog::OnOkay(const std::shared_ptr<cpu_thread>& _cpu)
} }
} }
} }
catch (std::invalid_argument&)
{
}
} }
QMessageBox::critical(this, tr("Error"), tr("This value could not be converted.\nNo changes were made.")); QMessageBox::critical(this, tr("Error"), tr("This value could not be converted.\nNo changes were made."));
} }

View File

@ -710,15 +710,12 @@ void trophy_manager_dialog::StartTrophyLoadThreads()
{ {
const std::string dir_name = sstr(folder_list.value(i)); const std::string dir_name = sstr(folder_list.value(i));
gui_log.trace("Loading trophy dir: %s", dir_name); gui_log.trace("Loading trophy dir: %s", dir_name);
try
{ if (!LoadTrophyFolderToDB(dir_name))
LoadTrophyFolderToDB(dir_name);
}
catch (const std::exception& e)
{ {
// TODO: Add error checks & throws to LoadTrophyFolderToDB so that they can be caught here. // 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. // 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);
} }
})); }));

10
rpcs3/util/cereal.cpp Normal file
View File

@ -0,0 +1,10 @@
#include <string>
#include "Utilities/Thread.h"
namespace cereal
{
[[noreturn]] void throw_exception(const std::string& err)
{
report_fatal_error(err);
}
}

View File

@ -307,8 +307,8 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, ...) co
const u64 stamp = get_stamp(); const u64 stamp = get_stamp();
// Get text, extract va_args // Get text, extract va_args
thread_local std::string text; /*constinit thread_local*/ std::string text;
thread_local std::vector<u64> args; /*constinit thread_local*/ std::basic_string<u64> args;
static constexpr fmt_type_info empty_sup{}; 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++) for (auto v = sup; v && v->fmt_string; v++)
args_count++; args_count++;
text.clear(); text.reserve(50000);
args.resize(args_count); args.resize(args_count);
va_list c_args; 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) 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) // Used character: U+00B7 (Middle Dot)
switch (msg.sev) switch (msg.sev)

17
rpcs3/util/yaml.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "util/yaml.hpp"
std::pair<YAML::Node, std::string> 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, ""};
}

20
rpcs3/util/yaml.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <utility>
#include <string>
#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::Node, std::string> yaml_load(const std::string& from);

View File

@ -13,10 +13,11 @@
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib> </Lib>
<ClCompile> <ClCompile>
<PreprocessorDefinitions>PUGIXML_HEADER_ONLY;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>PUGIXML_HEADER_ONLY;_ENABLE_EXTENDED_ALIGNED_STORAGE;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SDLCheck>false</SDLCheck> <SDLCheck>false</SDLCheck>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalOptions>/Zc:throwingNew %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/Zc:throwingNew %(AdditionalOptions)</AdditionalOptions>