mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-20 01:16:38 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b42fe803f | |||
| 847e91c3a8 | |||
| 2d1eb0dab9 |
+18
-20
@@ -17,35 +17,33 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
// glibc, mlibc, musl, and newlib all define their own variants of strerror_r
|
||||
// We don't need to use the preprocessor, we can just select depending on return type
|
||||
template<typename T> std::string HandleStrerrorR(T r, char *err_str);
|
||||
template<> std::string HandleStrerrorR(char* r, char *) { return std::string{r}; }
|
||||
template<> std::string HandleStrerrorR(const char* r, char *) { return std::string{r}; }
|
||||
template<> std::string HandleStrerrorR(int r, char *err_str) {
|
||||
return std::string{r != 0
|
||||
? "(strerror_r failed to format error)"
|
||||
: err_str};
|
||||
}
|
||||
|
||||
std::string NativeErrorToString(int e) {
|
||||
#ifdef _WIN32
|
||||
LPSTR err_str;
|
||||
|
||||
DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<LPSTR>(&err_str), 1, nullptr);
|
||||
if (!res) {
|
||||
return "(FormatMessageA failed to format error)";
|
||||
LPSTR(&err_str), 1, nullptr);
|
||||
if (res) {
|
||||
std::string ret(err_str);
|
||||
LocalFree(err_str);
|
||||
return ret;
|
||||
}
|
||||
std::string ret(err_str);
|
||||
LocalFree(err_str);
|
||||
return ret;
|
||||
return "(FormatMessageA failed to format error)";
|
||||
#else
|
||||
char err_str[255];
|
||||
#if defined(__ANDROID__) || \
|
||||
(defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)))
|
||||
// Thread safe (GNU-specific)
|
||||
const char* str = strerror_r(e, err_str, sizeof(err_str));
|
||||
return std::string(str);
|
||||
#else
|
||||
// Thread safe (XSI-compliant)
|
||||
int second_err = strerror_r(e, err_str, sizeof(err_str));
|
||||
if (second_err != 0) {
|
||||
return "(strerror_r failed to format error)";
|
||||
}
|
||||
return std::string(err_str);
|
||||
#endif // GLIBC etc.
|
||||
return HandleStrerrorR(strerror_r(e, err_str, sizeof(err_str)), err_str);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
||||
#include "core/hle/service/am/frontend/applets.h"
|
||||
#include "core/hle/service/am/service/storage.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::AM::Frontend {
|
||||
@@ -72,10 +73,16 @@ void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) {
|
||||
|
||||
void FrontendApplet::Exit() {
|
||||
auto applet_ = applet.lock();
|
||||
|
||||
std::scoped_lock lk{applet_->lock};
|
||||
applet_->is_completed = true;
|
||||
applet_->state_changed_event.Signal(system.Kernel());
|
||||
{
|
||||
std::scoped_lock lk{applet_->lock};
|
||||
applet_->is_completed = true;
|
||||
applet_->state_changed_event.Signal(system.Kernel());
|
||||
}
|
||||
if (auto caller_applet = applet_->caller_applet.lock()) {
|
||||
std::scoped_lock lk{caller_applet->lock};
|
||||
std::erase(caller_applet->child_applets, applet_);
|
||||
}
|
||||
if (auto* window_system = system.GetAppletManager().GetWindowSystem()) window_system->RequestUpdate();
|
||||
}
|
||||
|
||||
FrontendAppletSet::FrontendAppletSet() = default;
|
||||
|
||||
@@ -122,7 +122,10 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||
auto broker = std::make_shared<AppletDataBroker>(system);
|
||||
applet->caller_applet = caller_applet;
|
||||
applet->caller_applet_broker = broker;
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
{
|
||||
std::scoped_lock lk{caller_applet->lock};
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
}
|
||||
window_system.TrackApplet(applet, false);
|
||||
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
|
||||
}
|
||||
@@ -148,10 +151,10 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste
|
||||
applet->caller_applet = caller_applet;
|
||||
applet->caller_applet_broker = storage;
|
||||
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
|
||||
window_system.TrackApplet(applet, false);
|
||||
|
||||
{
|
||||
std::scoped_lock lk{caller_applet->lock};
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
}
|
||||
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "common/logging.h"
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include "dynarmic/mcl/integer_of_size.hpp"
|
||||
#include "dynarmic/backend/x64/xbyak.h"
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "common/logging.h"
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include "dynarmic/mcl/integer_of_size.hpp"
|
||||
#include "dynarmic/backend/x64/xbyak.h"
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#define AxxJitState CONCATENATE_TOKENS(Axx, JitState)
|
||||
#define AxxUserConfig Axx::UserConfig
|
||||
|
||||
namespace {
|
||||
using Vector = std::array<u64, 2>;
|
||||
}
|
||||
|
||||
std::optional<AxxEmitX64::DoNotFastmemMarker> AxxEmitX64::ShouldFastmem(AxxEmitContext& ctx, IR::Inst* inst) const {
|
||||
if (!conf.fastmem_pointer || !exception_handler.SupportsFastmem()) {
|
||||
return std::nullopt;
|
||||
@@ -27,19 +31,22 @@ std::optional<AxxEmitX64::DoNotFastmemMarker> AxxEmitX64::ShouldFastmem(AxxEmitC
|
||||
}
|
||||
|
||||
FakeCall AxxEmitX64::FastmemCallback(u64 rip_) {
|
||||
if (auto const it = fastmem_patch_info.find(rip_); it != fastmem_patch_info.end()) {
|
||||
const auto iter = fastmem_patch_info.find(rip_);
|
||||
if (iter != fastmem_patch_info.end()) {
|
||||
FakeCall result{
|
||||
.call_rip = it->second.callback,
|
||||
.ret_rip = it->second.resume_rip,
|
||||
.call_rip = iter->second.callback,
|
||||
.ret_rip = iter->second.resume_rip,
|
||||
};
|
||||
if (it->second.recompile) {
|
||||
const auto marker = it->second.marker;
|
||||
if (iter->second.recompile) {
|
||||
const auto marker = iter->second.marker;
|
||||
do_not_fastmem.insert(marker);
|
||||
InvalidateBasicBlocks({std::get<0>(marker)});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
UNREACHABLE_MSG("SIGSEGV @ JIT, rip={:#016x}", rip_); //("iter != fastmem_patch_info.end()");
|
||||
fmt::print("dynarmic: Segfault happened within JITted code at rip = {:016x}\n"
|
||||
"Segfault wasn't at a fastmem patch location!\n", rip_);
|
||||
UNREACHABLE(); //("iter != fastmem_patch_info.end()");
|
||||
}
|
||||
|
||||
template<std::size_t bitsize, auto callback>
|
||||
@@ -76,17 +83,22 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(code, args[1]);
|
||||
const int value_idx = bitsize == 128 ? ctx.reg_alloc.ScratchXmm(code).getIdx() : ctx.reg_alloc.ScratchGpr(code).getIdx();
|
||||
|
||||
const auto wrapped_fn = read_fallbacks[std::make_tuple(ordered, bitsize, vaddr.getIdx(), value_idx)];
|
||||
|
||||
SharedLabel abort = ctx.GenSharedLabel(), end = ctx.GenSharedLabel();
|
||||
|
||||
if (fastmem_marker) {
|
||||
// Use fastmem
|
||||
bool require_abort_handling = false;
|
||||
const auto src_ptr = EmitFastmemVAddr(code, ctx, *abort, vaddr, require_abort_handling);
|
||||
|
||||
const auto location = EmitReadMemoryMov<bitsize>(code, value_idx, src_ptr, ordered);
|
||||
|
||||
ctx.deferred_emits.emplace_back([=, this, &ctx] {
|
||||
code.L(*abort);
|
||||
code.call(wrapped_fn);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
std::bit_cast<u64>(location),
|
||||
FastmemPatchInfo{
|
||||
@@ -95,23 +107,25 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
*fastmem_marker,
|
||||
conf.recompile_on_fastmem_failure,
|
||||
});
|
||||
|
||||
EmitCheckMemoryAbort(ctx, inst, end);
|
||||
code.jmp(*end, code.T_NEAR);
|
||||
});
|
||||
} else if (conf.page_table) {
|
||||
} else {
|
||||
// Use page table
|
||||
ASSERT(conf.page_table);
|
||||
const auto src_ptr = EmitVAddrLookup(code, ctx, bitsize, *abort, vaddr);
|
||||
EmitReadMemoryMov<bitsize>(code, value_idx, src_ptr, ordered);
|
||||
|
||||
ctx.deferred_emits.emplace_back([=, this, &ctx] {
|
||||
code.L(*abort);
|
||||
code.call(wrapped_fn);
|
||||
EmitCheckMemoryAbort(ctx, inst, end);
|
||||
code.jmp(*end, code.T_NEAR);
|
||||
});
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
code.L(*end);
|
||||
|
||||
if constexpr (bitsize == 128) {
|
||||
ctx.reg_alloc.DefineValue(code, inst, Xbyak::Xmm{value_idx});
|
||||
} else {
|
||||
@@ -154,16 +168,18 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(code, args[1]);
|
||||
const int value_idx = bitsize == 128
|
||||
? ctx.reg_alloc.UseXmm(code, args[2]).getIdx()
|
||||
: (ordered ? ctx.reg_alloc.UseScratchGpr(code, args[2]).getIdx() : ctx.reg_alloc.UseGpr(code, args[2]).getIdx());
|
||||
? ctx.reg_alloc.UseXmm(code, args[2]).getIdx()
|
||||
: (ordered ? ctx.reg_alloc.UseScratchGpr(code, args[2]).getIdx() : ctx.reg_alloc.UseGpr(code, args[2]).getIdx());
|
||||
|
||||
const auto wrapped_fn = write_fallbacks[std::make_tuple(ordered, bitsize, vaddr.getIdx(), value_idx)];
|
||||
|
||||
SharedLabel abort = ctx.GenSharedLabel(), end = ctx.GenSharedLabel();
|
||||
|
||||
if (fastmem_marker) {
|
||||
// Use fastmem
|
||||
bool require_abort_handling = false;
|
||||
const auto dest_ptr = EmitFastmemVAddr(code, ctx, *abort, vaddr, require_abort_handling);
|
||||
|
||||
const auto location = EmitWriteMemoryMov<bitsize>(code, dest_ptr, value_idx, ordered);
|
||||
|
||||
ctx.deferred_emits.emplace_back([=, this, &ctx] {
|
||||
@@ -182,8 +198,9 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
EmitCheckMemoryAbort(ctx, inst, end);
|
||||
code.jmp(*end, code.T_NEAR);
|
||||
});
|
||||
} else if (conf.page_table) {
|
||||
} else {
|
||||
// Use page table
|
||||
ASSERT(conf.page_table);
|
||||
const auto dest_ptr = EmitVAddrLookup(code, ctx, bitsize, *abort, vaddr);
|
||||
EmitWriteMemoryMov<bitsize>(code, dest_ptr, value_idx, ordered);
|
||||
|
||||
@@ -193,8 +210,6 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
EmitCheckMemoryAbort(ctx, inst, end);
|
||||
code.jmp(*end, code.T_NEAR);
|
||||
});
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
code.L(*end);
|
||||
}
|
||||
@@ -234,8 +249,8 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
if (ordered) {
|
||||
code.mfence();
|
||||
}
|
||||
code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, u128& ret) {
|
||||
ret = conf.global_monitor->ReadAndMark<u128>(conf.processor_id, vaddr, [&]() -> u128 {
|
||||
code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& ret) {
|
||||
ret = conf.global_monitor->ReadAndMark<Vector>(conf.processor_id, vaddr, [&]() -> Vector {
|
||||
return (conf.callbacks->*callback)(vaddr);
|
||||
});
|
||||
});
|
||||
@@ -286,8 +301,8 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||
ctx.reg_alloc.AllocStackSpace(code, 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
||||
code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, u128& value) -> u32 {
|
||||
return conf.global_monitor->DoExclusiveOperation<u128>(conf.processor_id, vaddr, [&](u128 expected) -> bool {
|
||||
code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& value) -> u32 {
|
||||
return conf.global_monitor->DoExclusiveOperation<Vector>(conf.processor_id, vaddr, [&](Vector expected) -> bool {
|
||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||
}) ? 0 : 1;
|
||||
});
|
||||
|
||||
@@ -135,16 +135,10 @@ template<>
|
||||
if (unused_top_bits == 0) {
|
||||
code.mov(tmp, vaddr);
|
||||
code.shr(tmp, int(page_table_const_bits));
|
||||
if (ctx.conf.page_table_log2_stride > 3) {
|
||||
code.shl(tmp, int(ctx.conf.page_table_log2_stride));
|
||||
code.mov(page, qword[r14 + tmp.cvt64()]);
|
||||
} else {
|
||||
code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]);
|
||||
}
|
||||
} else if (ctx.conf.silently_mirror_page_table) {
|
||||
if (valid_page_index_bits >= 32) {
|
||||
if (code.HasHostFeature(HostFeature::BMI2)) {
|
||||
auto const bit_count = ctx.reg_alloc.ScratchGpr(code);
|
||||
const Xbyak::Reg64 bit_count = ctx.reg_alloc.ScratchGpr(code);
|
||||
code.mov(bit_count, unused_top_bits);
|
||||
code.bzhi(tmp, vaddr, bit_count);
|
||||
code.shr(tmp, int(page_table_const_bits));
|
||||
@@ -159,31 +153,19 @@ template<>
|
||||
code.shr(tmp, int(page_table_const_bits));
|
||||
code.and_(tmp, u32((1 << valid_page_index_bits) - 1));
|
||||
}
|
||||
if (ctx.conf.page_table_log2_stride > 3) {
|
||||
code.shl(tmp, int(ctx.conf.page_table_log2_stride));
|
||||
code.mov(page, qword[r14 + tmp.cvt64()]);
|
||||
} else {
|
||||
code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]);
|
||||
}
|
||||
} else {
|
||||
// Common VA sizes: 39 - 12 => 27, 42 - 12 => 30
|
||||
// Check if bits outside of VA space are non-zero
|
||||
ASSERT(valid_page_index_bits < 32);
|
||||
code.mov(tmp, vaddr);
|
||||
if (ctx.conf.check_halt_on_memory_access) {
|
||||
auto const tmp2 = ctx.reg_alloc.ScratchGpr(code);
|
||||
code.mov(tmp2, u64(-(1ull << valid_page_index_bits) << page_table_const_bits));
|
||||
code.test(tmp, tmp2);
|
||||
code.jnz(abort, code.T_NEAR);
|
||||
ctx.reg_alloc.Release(tmp2);
|
||||
}
|
||||
code.shr(tmp, int(page_table_const_bits));
|
||||
if (ctx.conf.page_table_log2_stride > 3) {
|
||||
code.shl(tmp, int(ctx.conf.page_table_log2_stride));
|
||||
code.mov(page, qword[r14 + tmp.cvt64()]);
|
||||
} else {
|
||||
code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]);
|
||||
}
|
||||
code.test(tmp, u32(-(1 << valid_page_index_bits)));
|
||||
code.jnz(abort, code.T_NEAR);
|
||||
}
|
||||
|
||||
if (ctx.conf.page_table_log2_stride > 3) {
|
||||
code.shl(tmp, int(ctx.conf.page_table_log2_stride));
|
||||
code.mov(page, qword[r14 + tmp.cvt64()]);
|
||||
} else {
|
||||
code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]);
|
||||
}
|
||||
|
||||
// check for marked bit, use as unmapped if marked
|
||||
@@ -211,7 +193,7 @@ template<>
|
||||
return page + vaddr;
|
||||
}
|
||||
code.mov(tmp, vaddr);
|
||||
code.and_(tmp, u32(page_table_const_mask));
|
||||
code.and_(tmp, static_cast<u32>(page_table_const_mask));
|
||||
return page + tmp;
|
||||
}
|
||||
|
||||
|
||||
@@ -761,9 +761,6 @@ void EmulatedController::StartMotionCalibration() {
|
||||
}
|
||||
|
||||
void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, Common::UUID uuid) {
|
||||
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
|
||||
if (index >= controller.button_values.size()) {
|
||||
return;
|
||||
}
|
||||
@@ -916,21 +913,10 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_connected) {
|
||||
if (npad_type == NpadStyleIndex::Handheld) {
|
||||
if (npad_id_type == NpadIdType::Handheld) {
|
||||
Connect();
|
||||
controller_connected[player_index] = true;
|
||||
}
|
||||
} else if (npad_type != NpadStyleIndex::Handheld) {
|
||||
if (npad_id_type == NpadIdType::Player1) {
|
||||
Connect();
|
||||
controller_connected[player_index] = true;
|
||||
} else if (player.connected && !controller_connected[player_index]) {
|
||||
Connect();
|
||||
controller_connected[player_index] = true;
|
||||
}
|
||||
}
|
||||
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (player.connected) {
|
||||
Connect();
|
||||
}
|
||||
|
||||
TriggerOnChange(ControllerTriggerType::Button, true);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "common/settings.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "hid_core/frontend/motion_input.h"
|
||||
#include "hid_core/hid_core.h"
|
||||
#include "hid_core/hid_types.h"
|
||||
#include "hid_core/irsensor/irs_types.h"
|
||||
|
||||
@@ -585,7 +584,6 @@ private:
|
||||
std::array<VibrationValue, 2> last_vibration_value{DEFAULT_VIBRATION_VALUE,
|
||||
DEFAULT_VIBRATION_VALUE};
|
||||
std::array<std::chrono::steady_clock::time_point, 2> last_vibration_timepoint{};
|
||||
std::array<bool, HIDCore::available_controllers> controller_connected{};
|
||||
|
||||
// Atomically synched values
|
||||
std::atomic<HID::NpadStyleIndex> npad_type{HID::NpadStyleIndex::None};
|
||||
|
||||
Reference in New Issue
Block a user