early-access version 3241

This commit is contained in:
pineappleEA 2022-12-22 22:10:29 +01:00
parent 3b9e1ccd4b
commit 7c2fb8c0da
9 changed files with 77 additions and 44 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3240. This is the source code for early-access 3241.
## Legal Notice ## Legal Notice

BIN
dist/yuzu.ico vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 25 KiB

2
dist/yuzu.svg vendored
View file

@ -1 +1 @@
<svg id="svg815" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 614.4 682.67"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#ff3c28;}.cls-4{fill:#0ab9e6;}</style><clipPath id="clip-path"><rect class="cls-1" x="-43" y="-46.67" width="699.6" height="777.33"/></clipPath></defs><title>Artboard 1</title><g id="g823"><g id="right"><g class="cls-2"><g id="g827"><g id="g833"><path id="path835" class="cls-3" d="M340.81,138V682.08c150.26,0,272.06-121.81,272.06-272.06S491.07,138,340.81,138M394,197.55a219.06,219.06,0,0,1,0,424.94V197.55"/></g></g></g></g><g id="left"><g class="cls-2"><g id="g839"><g id="g845"><path id="path847" class="cls-4" d="M272.79,1.92C122.53,1.92.73,123.73.73,274s121.8,272.07,272.06,272.07ZM219.65,61.51v425A219,219,0,0,1,118,119.18,217.51,217.51,0,0,1,219.65,61.51"/></g></g></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612.15 680.17"><defs><style>.cls-1{fill:#c6c6c6;}.cls-2{fill:#ffdc00;}</style></defs><title>newAsset 7</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><g id="g823"><g id="right"><g id="g827"><g id="g833"><path id="path835" class="cls-1" d="M340.08,136V680.17c150.26,0,272.07-121.81,272.07-272.07S490.34,136,340.08,136m53.14,59.6a219.06,219.06,0,0,1,0,424.94V195.63"/></g></g></g><g id="left"><g id="g839"><g id="g845"><path id="path847" class="cls-2" d="M272.07,0C121.81,0,0,121.81,0,272.07S121.81,544.13,272.07,544.13ZM218.93,59.6V484.54A219,219,0,0,1,117.26,117.26,217.44,217.44,0,0,1,218.93,59.6"/></g></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 889 B

After

Width:  |  Height:  |  Size: 717 B

View file

@ -49,6 +49,7 @@ struct SteadyClockContext {
static_assert(sizeof(SteadyClockContext) == 0x18, "SteadyClockContext is incorrect size"); static_assert(sizeof(SteadyClockContext) == 0x18, "SteadyClockContext is incorrect size");
static_assert(std::is_trivially_copyable_v<SteadyClockContext>, static_assert(std::is_trivially_copyable_v<SteadyClockContext>,
"SteadyClockContext must be trivially copyable"); "SteadyClockContext must be trivially copyable");
using StandardSteadyClockTimePointType = SteadyClockContext;
struct SystemClockContext { struct SystemClockContext {
s64 offset; s64 offset;

View file

@ -26,23 +26,24 @@ void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id,
const Clock::SteadyClockContext context{ const Clock::SteadyClockContext context{
static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds), static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
clock_source_id}; clock_source_id};
shared_memory_format.standard_steady_clock_timepoint.StoreData( StoreToLockFreeAtomicType(&GetFormat()->standard_steady_clock_timepoint, context);
system.Kernel().GetTimeSharedMem().GetPointer(), context);
} }
void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) { void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) {
shared_memory_format.standard_local_system_clock_context.StoreData( StoreToLockFreeAtomicType(&GetFormat()->standard_local_system_clock_context, context);
system.Kernel().GetTimeSharedMem().GetPointer(), context);
} }
void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) { void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) {
shared_memory_format.standard_network_system_clock_context.StoreData( StoreToLockFreeAtomicType(&GetFormat()->standard_network_system_clock_context, context);
system.Kernel().GetTimeSharedMem().GetPointer(), context);
} }
void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) { void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) {
shared_memory_format.standard_user_system_clock_automatic_correction.StoreData( StoreToLockFreeAtomicType(
system.Kernel().GetTimeSharedMem().GetPointer(), is_enabled); &GetFormat()->is_standard_user_system_clock_automatic_correction_enabled, is_enabled);
}
SharedMemory::Format* SharedMemory::GetFormat() {
return reinterpret_cast<SharedMemory::Format*>(system.Kernel().GetTimeSharedMem().GetPointer());
} }
} // namespace Service::Time } // namespace Service::Time

View file

@ -10,45 +10,68 @@
namespace Service::Time { namespace Service::Time {
// Note: this type is not safe for concurrent writes.
template <typename T>
struct LockFreeAtomicType {
u32 counter_;
std::array<T, 2> value_;
};
template <typename T>
static inline void StoreToLockFreeAtomicType(LockFreeAtomicType<T>* p, const T& value) {
// Get the current counter.
auto counter = p->counter_;
// Increment the counter.
++counter;
// Store the updated value.
p->value_[counter % 2] = value;
// Fence memory.
std::atomic_thread_fence(std::memory_order_release);
// Set the updated counter.
p->counter_ = counter;
}
template <typename T>
static inline T LoadFromLockFreeAtomicType(const LockFreeAtomicType<T>* p) {
while (true) {
// Get the counter.
auto counter = p->counter_;
// Get the value.
auto value = p->value_[counter % 2];
// Fence memory.
std::atomic_thread_fence(std::memory_order_acquire);
// Check that the counter matches.
if (counter == p->counter_) {
return value;
}
}
}
class SharedMemory final { class SharedMemory final {
public: public:
explicit SharedMemory(Core::System& system_); explicit SharedMemory(Core::System& system_);
~SharedMemory(); ~SharedMemory();
// TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this?
template <typename T, std::size_t Offset>
struct MemoryBarrier {
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
u32_le read_attempt{};
std::array<T, 2> data{};
// These are not actually memory barriers at the moment as we don't have multicore and all
// HLE is mutexed. This will need to properly be implemented when we start updating the time
// points on threads. As of right now, we'll be updated both values synchronously and just
// incrementing the read_attempt to indicate that we waited.
void StoreData(u8* shared_memory, T data_to_store) {
std::memcpy(this, shared_memory + Offset, sizeof(*this));
read_attempt++;
data[read_attempt & 1] = data_to_store;
std::memcpy(shared_memory + Offset, this, sizeof(*this));
}
// For reading we're just going to read the last stored value. If there was no value stored
// it will just end up reading an empty value as intended.
T ReadData(u8* shared_memory) {
std::memcpy(this, shared_memory + Offset, sizeof(*this));
return data[(read_attempt - 1) & 1];
}
};
// Shared memory format // Shared memory format
struct Format { struct Format {
MemoryBarrier<Clock::SteadyClockContext, 0x0> standard_steady_clock_timepoint; LockFreeAtomicType<Clock::StandardSteadyClockTimePointType> standard_steady_clock_timepoint;
MemoryBarrier<Clock::SystemClockContext, 0x38> standard_local_system_clock_context; LockFreeAtomicType<Clock::SystemClockContext> standard_local_system_clock_context;
MemoryBarrier<Clock::SystemClockContext, 0x80> standard_network_system_clock_context; LockFreeAtomicType<Clock::SystemClockContext> standard_network_system_clock_context;
MemoryBarrier<bool, 0xc8> standard_user_system_clock_automatic_correction; LockFreeAtomicType<bool> is_standard_user_system_clock_automatic_correction_enabled;
u32_le format_version; u32 format_version;
}; };
static_assert(offsetof(Format, standard_steady_clock_timepoint) == 0x0);
static_assert(offsetof(Format, standard_local_system_clock_context) == 0x38);
static_assert(offsetof(Format, standard_network_system_clock_context) == 0x80);
static_assert(offsetof(Format, is_standard_user_system_clock_automatic_correction_enabled) ==
0xc8);
static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); static_assert(sizeof(Format) == 0xd8, "Format is an invalid size");
void SetupStandardSteadyClock(const Common::UUID& clock_source_id, void SetupStandardSteadyClock(const Common::UUID& clock_source_id,
@ -56,10 +79,10 @@ public:
void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context); void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context);
void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context); void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context);
void SetAutomaticCorrectionEnabled(bool is_enabled); void SetAutomaticCorrectionEnabled(bool is_enabled);
Format* GetFormat();
private: private:
Core::System& system; Core::System& system;
Format shared_memory_format{};
}; };
} // namespace Service::Time } // namespace Service::Time

View file

@ -78,7 +78,6 @@ void EmuThread::run() {
gpu.Start(); gpu.Start();
m_system.GetCpuManager().OnGpuReady(); m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([this] { m_stop_source.request_stop(); });
if (m_system.DebuggerEnabled()) { if (m_system.DebuggerEnabled()) {
m_system.InitializeDebugger(); m_system.InitializeDebugger();

View file

@ -38,7 +38,7 @@ void DiscordImpl::Update() {
system.GetAppLoader().ReadTitle(title); system.GetAppLoader().ReadTitle(title);
} }
DiscordRichPresence presence{}; DiscordRichPresence presence{};
presence.largeImageKey = "yuzu_logo"; presence.largeImageKey = "yuzu_logo_ea";
presence.largeImageText = "yuzu is an emulator for the Nintendo Switch"; presence.largeImageText = "yuzu is an emulator for the Nintendo Switch";
if (system.IsPoweredOn()) { if (system.IsPoweredOn()) {
presence.state = title.c_str(); presence.state = title.c_str();

View file

@ -1710,6 +1710,11 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
system->RegisterExecuteProgramCallback( system->RegisterExecuteProgramCallback(
[this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); }); [this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); });
system->RegisterExitCallback([this] {
emu_thread->ForceStop();
render_window->Exit();
});
connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity); connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity);
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
@ -4177,6 +4182,10 @@ bool GMainWindow::ConfirmForceLockedExit() {
} }
void GMainWindow::RequestGameExit() { void GMainWindow::RequestGameExit() {
if (!system->IsPoweredOn()) {
return;
}
auto& sm{system->ServiceManager()}; auto& sm{system->ServiceManager()};
auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");