mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-19 19:15:26 +00:00
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:
parent
47bbfdd2aa
commit
04dedb17eb
39 changed files with 421 additions and 437 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -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
|
||||
|
|
2
3rdparty/cereal
vendored
2
3rdparty/cereal
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 42a45b6e15fcbd1a3d65b033f5d4d0b2ef6c023d
|
||||
Subproject commit 60c69df968d1c72c998cd5f23ba34e2e3718a84b
|
2
3rdparty/yaml-cpp
vendored
2
3rdparty/yaml-cpp
vendored
|
@ -1 +1 @@
|
|||
Subproject commit eca9cfd64899525d0a61abb0553849676a0fe511
|
||||
Subproject commit 6a211f0bc71920beef749e6c35d7d1bcc2447715
|
5
3rdparty/yaml-cpp.vcxproj
vendored
5
3rdparty/yaml-cpp.vcxproj
vendored
|
@ -37,6 +37,11 @@
|
|||
<Import Project="..\rpcs3_release.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="yaml-cpp\src\binary.cpp">
|
||||
</ClCompile>
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#include "stdafx.h"
|
||||
#include "Config.h"
|
||||
#include "Utilities/types.h"
|
||||
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include "util/yaml.hpp"
|
||||
|
||||
#include <typeinfo>
|
||||
#include <charconv>
|
||||
|
||||
[[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<std::string>&&)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,22 +60,6 @@ void fmt_class_string<std::thread::id>::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 };
|
||||
|
|
|
@ -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<Context>, 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<named_thread*>(static_cast<thread*>(arg));
|
||||
|
@ -272,10 +269,6 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
|
|||
thread::finalize();
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
catch_all_exceptions();
|
||||
}
|
||||
|
||||
bool entry_point()
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "bin_patch.h"
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -243,28 +243,83 @@ using cpu_profiler = named_thread<cpu_prof>;
|
|||
|
||||
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<u32> g_cpu_array_sema{0};
|
||||
// Semaphore for global thread array (global counter)
|
||||
alignas(64) atomic_t<u32> cpu_array_sema{0};
|
||||
|
||||
// Semaphore subdivision for each array slot (64 x N in total)
|
||||
atomic_t<u64> g_cpu_array_bits[6]{};
|
||||
// Semaphore subdivision for each array slot (64 x N in total)
|
||||
atomic_t<u64> cpu_array_bits[6]{};
|
||||
|
||||
// All registered threads
|
||||
atomic_t<cpu_thread*> g_cpu_array[sizeof(g_cpu_array_bits) * 8]{};
|
||||
// All registered threads
|
||||
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>
|
||||
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);
|
||||
|
||||
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<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)
|
||||
{
|
||||
g_fxo->get<cpu_profiler>()->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<cpu_counter>()->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<cpu_counter>()->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_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;
|
||||
}
|
||||
|
||||
g_cpu_suspend_lock.lock_vip();
|
||||
g_fxo->get<cpu_counter>()->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_counter>()->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_counter>()->cpu_suspend_lock.unlock_low();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_cpu_suspend_lock.lock_unlock();
|
||||
g_fxo->get<cpu_counter>()->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_counter>()->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_counter>()->cpu_array_sema)
|
||||
{
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<u8> d
|
|||
if (stream->buffer->length > 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);
|
||||
}
|
||||
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<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);
|
||||
streamInfo->decodedStrmSize += streamParam->strmSize;
|
||||
try
|
||||
{
|
||||
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;
|
||||
}
|
||||
png_process_data(stream->png_ptr, stream->info_ptr, static_cast<u8*>(streamParam->strmPtr.get_ptr()), streamParam->strmSize);
|
||||
}
|
||||
|
||||
freeMem();
|
||||
|
@ -767,7 +744,6 @@ s32 pngDecodeData(ppu_thread& ppu, PHandle handle, PStream stream, vm::ptr<u8> 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<u8> 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<u8*>(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());
|
||||
|
|
|
@ -114,7 +114,9 @@ void cellSpursModuleExit(spu_thread& spu)
|
|||
{
|
||||
auto ctxt = vm::_ptr<SpursKernelContext>(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<SpursTasksetContext>(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;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "PPUModule.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#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;
|
||||
|
||||
|
|
|
@ -859,16 +859,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
|
|||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
exec_task();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
at_ret();
|
||||
throw;
|
||||
}
|
||||
|
||||
exec_task();
|
||||
at_ret();
|
||||
}
|
||||
|
||||
|
|
|
@ -4357,7 +4357,7 @@ Value* PPUTranslator::GetVr(u32 vr, VrType type)
|
|||
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)
|
||||
|
@ -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);
|
||||
|
|
|
@ -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<u32>* 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)
|
||||
|
|
|
@ -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<void*>(&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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u8>(type));
|
||||
}
|
||||
|
||||
struct vertex_input_state
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <charconv>
|
||||
|
||||
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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<u8>(type));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "../Crypto/unself.h"
|
||||
#include "../Crypto/unpkg.h"
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -87,6 +87,13 @@
|
|||
<ClCompile Include="util\atomic2.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</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">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
|
|
@ -869,6 +869,15 @@
|
|||
<ClCompile Include="util\atomic2.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</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">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -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 <thread>
|
||||
#include <charconv>
|
||||
|
||||
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<int>(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<int>(Qt::HighDpiScaleFactorRoundingPolicy::Unset) && rounding_val_cli <= 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&)
|
||||
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<int>(Qt::HighDpiScaleFactorRoundingPolicy::Unset), static_cast<int>(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<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();
|
||||
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));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,6 @@
|
|||
<BrowseInformation>false</BrowseInformation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<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>
|
||||
|
@ -180,7 +179,6 @@
|
|||
<BrowseInformation>false</BrowseInformation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<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>
|
||||
|
@ -233,7 +231,6 @@
|
|||
<BrowseInformation>false</BrowseInformation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<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>
|
||||
|
@ -287,7 +284,6 @@
|
|||
<BrowseInformation>false</BrowseInformation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<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>
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include <QClipboard>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "Loader/PSF.h"
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/lockless.h"
|
||||
#include "util/yaml.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
@ -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>(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<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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ void register_editor_dialog::OnOkay(const std::shared_ptr<cpu_thread>& _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_thread>& _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_thread>& _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_thread>& _cpu)
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (std::invalid_argument&)
|
||||
{
|
||||
}
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error"), tr("This value could not be converted.\nNo changes were made."));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
10
rpcs3/util/cereal.cpp
Normal file
10
rpcs3/util/cereal.cpp
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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<u64> args;
|
||||
/*constinit thread_local*/ std::string text;
|
||||
/*constinit thread_local*/ std::basic_string<u64> 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)
|
||||
|
|
17
rpcs3/util/yaml.cpp
Normal file
17
rpcs3/util/yaml.cpp
Normal 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
20
rpcs3/util/yaml.hpp
Normal 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);
|
|
@ -13,10 +13,11 @@
|
|||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
</Lib>
|
||||
<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>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalOptions>/Zc:throwingNew %(AdditionalOptions)</AdditionalOptions>
|
||||
|
|
Loading…
Add table
Reference in a new issue