From 8a906c45f824e5af0668d28588ab8f0a586853b6 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 4 Aug 2026 13:21:26 -0700 Subject: [PATCH] Add configurable gameplay rates --- Source/GameCoreManager.swift | 4 ++++ Source/OEGameCoreHelper.swift | 7 +++++++ Source/OpenEmuHelperApp.swift | 32 +++++++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Source/GameCoreManager.swift b/Source/GameCoreManager.swift index a661c91..8d068f6 100644 --- a/Source/GameCoreManager.swift +++ b/Source/GameCoreManager.swift @@ -80,6 +80,10 @@ extension GameCoreManager: OEGameCoreHelper { public func setVolume(_ value: Float) { gameCoreHelper?.setVolume(value) } + + public func setGameplayRate(_ normalRate: Float, fastForwardRate: Float) { + gameCoreHelper?.setGameplayRate(normalRate, fastForwardRate: fastForwardRate) + } public func setPauseEmulation(_ pauseEmulation: Bool) { gameCoreHelper?.setPauseEmulation(pauseEmulation) diff --git a/Source/OEGameCoreHelper.swift b/Source/OEGameCoreHelper.swift index 0bc4e80..c9d1adf 100644 --- a/Source/OEGameCoreHelper.swift +++ b/Source/OEGameCoreHelper.swift @@ -43,6 +43,13 @@ import AudioToolbox /// /// - Parameter value: The new volume level, from @c [0,1.0] func setVolume(_ value: Float) + + /// Sets the rates used for normal gameplay and fast-forwarding. + /// + /// - Parameters: + /// - normalRate: The multiplier used during normal gameplay. + /// - fastForwardRate: The multiplier used while fast-forward is active. + func setGameplayRate(_ normalRate: Float, fastForwardRate: Float) /** * Manage the paused status of the core. diff --git a/Source/OpenEmuHelperApp.swift b/Source/OpenEmuHelperApp.swift index 64b4a31..0c12c95 100644 --- a/Source/OpenEmuHelperApp.swift +++ b/Source/OpenEmuHelperApp.swift @@ -89,6 +89,10 @@ extension OSLog { var _handleKeyboardEvents: Bool = false var loadedRom = false + + private var normalGameplayRate: Float = 1.0 + private var fastForwardGameplayRate: Float = 5.0 + private var isFastForwarding = false // frame rate debugging var previous = CFTimeInterval() @@ -143,6 +147,19 @@ extension OSLog { self._shaderParameters = nil } } + + private func applyGameplayRate() { + let rate = isFastForwarding ? fastForwardGameplayRate : normalGameplayRate + + // nextDrawable() otherwise limits cores running faster than the display refresh rate. + // Fixes: https://github.com/OpenEmu/OpenEmu/issues/4780 + _videoLayer?.displaySyncEnabled = rate <= 1.0 + + gameCore.perform { + guard !self.gameCore.isEmulationPaused else { return } + self.gameCore.rate = rate + } + } // MARK: - Core Video and Generic Video @@ -361,10 +378,20 @@ extension OSLog { self._gameAudio.volume = volume } } + + public func setGameplayRate(_ normalRate: Float, fastForwardRate: Float) { + normalGameplayRate = normalRate + fastForwardGameplayRate = fastForwardRate + applyGameplayRate() + } public func setPauseEmulation(_ paused: Bool) { + let rate = isFastForwarding ? fastForwardGameplayRate : normalGameplayRate gameCore.perform { self.gameCore.setPauseEmulation(paused) + if !paused { + self.gameCore.rate = rate + } } } @@ -828,9 +855,8 @@ extension OSLog { } public func fastForwardGameplay(_ enable: Bool) { - // Required so that _videoLayer.nextDrawable() vends frames faster than the display refresh rate - // Fixes: https://github.com/OpenEmu/OpenEmu/issues/4780 - _videoLayer.displaySyncEnabled = !enable + isFastForwarding = enable + applyGameplayRate() gameCoreOwner.fastForwardGameplay(enable) }