diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index d1cbadde44..f4416f5b2b 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 9b22397db7..3828cf272a 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;