diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java index 00d74d8c5..287ed6992 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/player/PlayerPatch.java @@ -518,6 +518,12 @@ public class PlayerPatch { return SPEED_OVERLAY_VALUE; } + public static float speedOverlayRelativeValue(float original) { + return SPEED_OVERLAY_VALUE != 2.0f + ? 0f + : original; + } + public static boolean hideChannelWatermark(boolean original) { return !Settings.HIDE_CHANNEL_WATERMARK.get() && original; } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt index a36f776ab..303b05170 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/Fingerprints.kt @@ -88,6 +88,8 @@ internal val speedOverlayFingerprint = legacyFingerprint( literals = listOf(SPEED_OVERLAY_FEATURE_FLAG), ) +internal const val SPEED_OVERLAY_LEGACY_FEATURE_FLAG = 45411328L + /** * This value is the key for the playback speed overlay value. * Deprecated in YouTube v19.18.41+. @@ -97,7 +99,7 @@ internal val speedOverlayFloatValueFingerprint = legacyFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, opcodes = listOf(Opcode.DOUBLE_TO_FLOAT), - literals = listOf(45411328L), + literals = listOf(SPEED_OVERLAY_LEGACY_FEATURE_FLAG), ) internal val speedOverlayTextValueFingerprint = legacyFingerprint( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt index 8cc9ce104..81d9579d5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt @@ -24,9 +24,11 @@ import app.revanced.patches.youtube.utils.engagement.engagementPanelIdRegister import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH +import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch +import app.revanced.patches.youtube.utils.playservice.is_19_18_or_greater import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater @@ -45,23 +47,27 @@ import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.util.Utils.printWarn import app.revanced.util.findMethodOrThrow +import app.revanced.util.findMutableMethodOf import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall import app.revanced.util.fingerprint.injectLiteralInstructionViewCall import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.mutableClassOrThrow -import app.revanced.util.fingerprint.resolvable import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstLiteralInstructionOrThrow +import app.revanced.util.or +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference @@ -70,7 +76,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference private val speedOverlayPatch = bytecodePatch( description = "speedOverlayPatch" ) { - dependsOn(sharedResourceIdPatch) + dependsOn( + sharedExtensionPatch, + sharedResourceIdPatch, + versionCheckPatch, + ) execute { fun MutableMethod.hookSpeedOverlay( @@ -87,11 +97,19 @@ private val speedOverlayPatch = bytecodePatch( ) } - val resolvable = restoreSlideToSeekBehaviorFingerprint.resolvable() && - speedOverlayFingerprint.resolvable() && - speedOverlayFloatValueFingerprint.resolvable() + fun MutableMethod.hookRelativeSpeedValue(startIndex: Int) { + val relativeIndex = indexOfFirstInstructionOrThrow(startIndex, Opcode.CMPL_FLOAT) + val relativeRegister = getInstruction(relativeIndex).registerB - if (resolvable) { + addInstructions( + relativeIndex, """ + invoke-static {v$relativeRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayRelativeValue(F)F + move-result v$relativeRegister + """ + ) + } + + if (!is_19_18_or_greater) { // Used on YouTube 18.29.38 ~ YouTube 19.17.41 // region patch for Disable speed overlay (Enable slide to seek) @@ -110,17 +128,51 @@ private val speedOverlayPatch = bytecodePatch( // region patch for Custom speed overlay float value - speedOverlayFloatValueFingerprint.matchOrThrow().let { - it.method.apply { - val index = it.patternMatch!!.startIndex - val register = getInstruction(index).registerA + val speedFieldReference = with (speedOverlayFloatValueFingerprint.methodOrThrow()) { + val literalIndex = indexOfFirstLiteralInstructionOrThrow(SPEED_OVERLAY_LEGACY_FEATURE_FLAG) + val floatIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.DOUBLE_TO_FLOAT) + val floatRegister = getInstruction(floatIndex).registerA - addInstructions( - index + 1, """ - invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F - move-result v$register + addInstructions( + floatIndex + 1, """ + invoke-static {v$floatRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F + move-result v$floatRegister """ - ) + ) + + val speedFieldIndex = indexOfFirstInstructionOrThrow(literalIndex) { + opcode == Opcode.IPUT && + getReference()?.type == "F" + } + + getInstruction(speedFieldIndex).reference.toString() + } + + fun indexOfFirstSpeedFieldInstruction(method: Method) = + method.indexOfFirstInstruction { + opcode == Opcode.IGET && + getReference()?.toString() == speedFieldReference + } + + val isSyntheticMethod: Method.() -> Boolean = { + name == "run" && + accessFlags == AccessFlags.PUBLIC or AccessFlags.FINAL && + parameterTypes.isEmpty() && + indexOfFirstSpeedFieldInstruction(this) >= 0 && + indexOfFirstInstruction(Opcode.CMPL_FLOAT) >= 0 + } + + classes.forEach { classDef -> + classDef.methods.forEach { method -> + if (method.isSyntheticMethod()) { + proxy(classDef) + .mutableClass + .findMutableMethodOf(method) + .apply { + val speedFieldIndex = indexOfFirstSpeedFieldInstruction(this) + hookRelativeSpeedValue(speedFieldIndex) + } + } } } @@ -241,6 +293,8 @@ private val speedOverlayPatch = bytecodePatch( move-result v$speedOverlayFloatValueRegister """ ) + + hookRelativeSpeedValue(speedOverlayFloatValueIndex) } // Removed in YouTube 20.03+ diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt index bb4baa8da..97966f6b9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt @@ -31,6 +31,8 @@ var is_19_16_or_greater = false private set var is_19_17_or_greater = false private set +var is_19_18_or_greater = false + private set var is_19_23_or_greater = false private set var is_19_25_or_greater = false @@ -97,6 +99,7 @@ val versionCheckPatch = resourcePatch( is_19_15_or_greater = 241602000 <= playStoreServicesVersion is_19_16_or_greater = 241702000 <= playStoreServicesVersion is_19_17_or_greater = 241802000 <= playStoreServicesVersion + is_19_18_or_greater = 241902000 <= playStoreServicesVersion is_19_23_or_greater = 242402000 <= playStoreServicesVersion is_19_25_or_greater = 242599000 <= playStoreServicesVersion is_19_26_or_greater = 242705000 <= playStoreServicesVersion