summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/core_timing.cpp42
-rw-r--r--src/core/core_timing.h9
-rw-r--r--src/core/debugger/gdbstub.cpp26
-rw-r--r--src/core/hle/kernel/k_hardware_timer.cpp6
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp8
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h2
-rw-r--r--src/core/memory.cpp4
7 files changed, 60 insertions, 37 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 0e7b5f943..6bac6722f 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -142,16 +142,24 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
}
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
- std::uintptr_t user_data) {
- std::scoped_lock scope{basic_lock};
- const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
- return e.type.lock().get() == event_type.get() && e.user_data == user_data;
- });
-
- // Removing random items breaks the invariant so we have to re-establish it.
- if (itr != event_queue.end()) {
- event_queue.erase(itr, event_queue.end());
- std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
+ std::uintptr_t user_data, bool wait) {
+ {
+ std::scoped_lock lk{basic_lock};
+ const auto itr =
+ std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
+ return e.type.lock().get() == event_type.get() && e.user_data == user_data;
+ });
+
+ // Removing random items breaks the invariant so we have to re-establish it.
+ if (itr != event_queue.end()) {
+ event_queue.erase(itr, event_queue.end());
+ std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
+ }
+ }
+
+ // Force any in-progress events to finish
+ if (wait) {
+ std::scoped_lock lk{advance_lock};
}
}
@@ -190,20 +198,6 @@ u64 CoreTiming::GetClockTicks() const {
return CpuCyclesToClockCycles(ticks);
}
-void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
- std::scoped_lock lock{basic_lock};
-
- const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
- return e.type.lock().get() == event_type.get();
- });
-
- // Removing random items breaks the invariant so we have to re-establish it.
- if (itr != event_queue.end()) {
- event_queue.erase(itr, event_queue.end());
- std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
- }
-}
-
std::optional<s64> CoreTiming::Advance() {
std::scoped_lock lock{advance_lock, basic_lock};
global_timer = GetGlobalTimeNs().count();
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index b5925193c..da366637b 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -98,10 +98,13 @@ public:
const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data = 0, bool absolute_time = false);
- void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data);
+ void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data,
+ bool wait = true);
- /// We only permit one event of each type in the queue at a time.
- void RemoveEvent(const std::shared_ptr<EventType>& event_type);
+ void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type,
+ std::uintptr_t user_data) {
+ UnscheduleEvent(event_type, user_data, false);
+ }
void AddTicks(u64 ticks_to_add);
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index a64a9ac64..9c02b7b31 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -11,6 +11,7 @@
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/debugger/gdbstub.h"
@@ -731,7 +732,25 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
auto* process = system.CurrentProcess();
auto& page_table = process->PageTable();
- if (command_str == "get info") {
+ const char* commands = "Commands:\n"
+ " get fastmem\n"
+ " get info\n"
+ " get mappings\n";
+
+ if (command_str == "get fastmem") {
+ if (Settings::IsFastmemEnabled()) {
+ const auto& impl = page_table.PageTableImpl();
+ const auto region = reinterpret_cast<uintptr_t>(impl.fastmem_arena);
+ const auto region_bits = impl.current_address_space_width_in_bits;
+ const auto region_size = 1ULL << region_bits;
+
+ reply = fmt::format("Region bits: {}\n"
+ "Host address: {:#x} - {:#x}\n",
+ region_bits, region, region + region_size - 1);
+ } else {
+ reply = "Fastmem is not enabled.\n";
+ }
+ } else if (command_str == "get info") {
Loader::AppLoader::Modules modules;
system.GetAppLoader().ReadNSOModules(modules);
@@ -787,9 +806,10 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
cur_addr = next_address;
}
} else if (command_str == "help") {
- reply = "Commands:\n get info\n get mappings\n";
+ reply = commands;
} else {
- reply = "Unknown command.\nCommands:\n get info\n get mappings\n";
+ reply = "Unknown command.\n";
+ reply += commands;
}
std::span<const u8> reply_span{reinterpret_cast<u8*>(&reply.front()), reply.size()};
diff --git a/src/core/hle/kernel/k_hardware_timer.cpp b/src/core/hle/kernel/k_hardware_timer.cpp
index 6bba79ea0..4dcd53821 100644
--- a/src/core/hle/kernel/k_hardware_timer.cpp
+++ b/src/core/hle/kernel/k_hardware_timer.cpp
@@ -18,7 +18,8 @@ void KHardwareTimer::Initialize() {
}
void KHardwareTimer::Finalize() {
- this->DisableInterrupt();
+ m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
+ m_wakeup_time = std::numeric_limits<s64>::max();
m_event_type.reset();
}
@@ -59,7 +60,8 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) {
}
void KHardwareTimer::DisableInterrupt() {
- m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
+ m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type,
+ reinterpret_cast<uintptr_t>(this));
m_wakeup_time = std::numeric_limits<s64>::max();
}
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index d1cbadde4..f4416f5b2 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -312,8 +312,6 @@ void NVFlinger::Compose() {
}
s64 NVFlinger::GetNextTicks() const {
- static constexpr s64 max_hertz = 120LL;
-
const auto& settings = Settings::values;
auto speed_scale = 1.f;
if (settings.use_multi_core.GetValue()) {
@@ -327,9 +325,11 @@ s64 NVFlinger::GetNextTicks() const {
}
}
- const auto next_ticks = ((1000000000 * (1LL << swap_interval)) / max_hertz);
+ // As an extension, treat nonpositive swap interval as framerate multiplier.
+ const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval)
+ : 60.f / static_cast<f32>(swap_interval);
- return static_cast<s64>(speed_scale * static_cast<float>(next_ticks));
+ return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
}
} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 9b22397db..3828cf272 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -133,7 +133,7 @@ private:
/// layers.
u32 next_buffer_queue_id = 1;
- u32 swap_interval = 1;
+ s32 swap_interval = 1;
/// Event that handles screen composition.
std::shared_ptr<Core::Timing::EventType> multi_composition_event;
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index a1e41faff..4e605fae4 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -383,6 +383,10 @@ struct Memory::Impl {
return;
}
+ if (Settings::IsFastmemEnabled()) {
+ system.DeviceMemory().buffer.Protect(vaddr, size, !debug, !debug);
+ }
+
// Iterate over a contiguous CPU address space, marking/unmarking the region.
// The region is at a granularity of CPU pages.