@@ -24,9 +24,11 @@ import app.revanced.patches.youtube.utils.engagement.engagementPanelIdRegister
24
24
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
25
25
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
26
26
import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH
27
+ import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
27
28
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch
28
29
import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS
29
30
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
31
+ import app.revanced.patches.youtube.utils.playservice.is_19_18_or_greater
30
32
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
31
33
import app.revanced.patches.youtube.utils.playservice.is_20_03_or_greater
32
34
import app.revanced.patches.youtube.utils.playservice.is_20_05_or_greater
@@ -45,23 +47,27 @@ import app.revanced.patches.youtube.video.information.videoInformationPatch
45
47
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
46
48
import app.revanced.util.Utils.printWarn
47
49
import app.revanced.util.findMethodOrThrow
50
+ import app.revanced.util.findMutableMethodOf
48
51
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
49
52
import app.revanced.util.fingerprint.injectLiteralInstructionViewCall
50
53
import app.revanced.util.fingerprint.matchOrThrow
51
54
import app.revanced.util.fingerprint.methodOrThrow
52
55
import app.revanced.util.fingerprint.mutableClassOrThrow
53
- import app.revanced.util.fingerprint.resolvable
54
56
import app.revanced.util.getReference
55
57
import app.revanced.util.getWalkerMethod
56
58
import app.revanced.util.indexOfFirstInstruction
57
59
import app.revanced.util.indexOfFirstInstructionOrThrow
58
60
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
59
61
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
62
+ import app.revanced.util.or
63
+ import com.android.tools.smali.dexlib2.AccessFlags
60
64
import com.android.tools.smali.dexlib2.Opcode
65
+ import com.android.tools.smali.dexlib2.iface.Method
61
66
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
62
67
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
63
68
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
64
69
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
70
+ import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstruction
65
71
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
66
72
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
67
73
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@@ -70,7 +76,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
70
76
private val speedOverlayPatch = bytecodePatch(
71
77
description = " speedOverlayPatch"
72
78
) {
73
- dependsOn(sharedResourceIdPatch)
79
+ dependsOn(
80
+ sharedExtensionPatch,
81
+ sharedResourceIdPatch,
82
+ versionCheckPatch,
83
+ )
74
84
75
85
execute {
76
86
fun MutableMethod.hookSpeedOverlay (
@@ -87,11 +97,19 @@ private val speedOverlayPatch = bytecodePatch(
87
97
)
88
98
}
89
99
90
- val resolvable = restoreSlideToSeekBehaviorFingerprint.resolvable() &&
91
- speedOverlayFingerprint.resolvable() &&
92
- speedOverlayFloatValueFingerprint.resolvable()
100
+ fun MutableMethod. hookRelativeSpeedValue ( startIndex : Int ) {
101
+ val relativeIndex = indexOfFirstInstructionOrThrow(startIndex, Opcode . CMPL_FLOAT )
102
+ val relativeRegister = getInstruction< ThreeRegisterInstruction >(relativeIndex).registerB
93
103
94
- if (resolvable) {
104
+ addInstructions(
105
+ relativeIndex, """
106
+ invoke-static {v$relativeRegister }, $PLAYER_CLASS_DESCRIPTOR ->speedOverlayRelativeValue(F)F
107
+ move-result v$relativeRegister
108
+ """
109
+ )
110
+ }
111
+
112
+ if (! is_19_18_or_greater) {
95
113
// Used on YouTube 18.29.38 ~ YouTube 19.17.41
96
114
97
115
// region patch for Disable speed overlay (Enable slide to seek)
@@ -110,17 +128,51 @@ private val speedOverlayPatch = bytecodePatch(
110
128
111
129
// region patch for Custom speed overlay float value
112
130
113
- speedOverlayFloatValueFingerprint.matchOrThrow(). let {
114
- it.method. apply {
115
- val index = it.patternMatch !! .startIndex
116
- val register = getInstruction<TwoRegisterInstruction >(index ).registerA
131
+ val speedFieldReference = with ( speedOverlayFloatValueFingerprint.methodOrThrow()) {
132
+ val literalIndex = indexOfFirstLiteralInstructionOrThrow( SPEED_OVERLAY_LEGACY_FEATURE_FLAG )
133
+ val floatIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode . DOUBLE_TO_FLOAT )
134
+ val floatRegister = getInstruction<TwoRegisterInstruction >(floatIndex ).registerA
117
135
118
- addInstructions(
119
- index + 1 , """
120
- invoke-static {v$register }, $PLAYER_CLASS_DESCRIPTOR ->speedOverlayValue(F)F
121
- move-result v$register
136
+ addInstructions(
137
+ floatIndex + 1 , """
138
+ invoke-static {v$floatRegister }, $PLAYER_CLASS_DESCRIPTOR ->speedOverlayValue(F)F
139
+ move-result v$floatRegister
122
140
"""
123
- )
141
+ )
142
+
143
+ val speedFieldIndex = indexOfFirstInstructionOrThrow(literalIndex) {
144
+ opcode == Opcode .IPUT &&
145
+ getReference<FieldReference >()?.type == " F"
146
+ }
147
+
148
+ getInstruction<ReferenceInstruction >(speedFieldIndex).reference.toString()
149
+ }
150
+
151
+ fun indexOfFirstSpeedFieldInstruction (method : Method ) =
152
+ method.indexOfFirstInstruction {
153
+ opcode == Opcode .IGET &&
154
+ getReference<FieldReference >()?.toString() == speedFieldReference
155
+ }
156
+
157
+ val isSyntheticMethod: Method .() -> Boolean = {
158
+ name == " run" &&
159
+ accessFlags == AccessFlags .PUBLIC or AccessFlags .FINAL &&
160
+ parameterTypes.isEmpty() &&
161
+ indexOfFirstSpeedFieldInstruction(this ) >= 0 &&
162
+ indexOfFirstInstruction(Opcode .CMPL_FLOAT ) >= 0
163
+ }
164
+
165
+ classes.forEach { classDef ->
166
+ classDef.methods.forEach { method ->
167
+ if (method.isSyntheticMethod()) {
168
+ proxy(classDef)
169
+ .mutableClass
170
+ .findMutableMethodOf(method)
171
+ .apply {
172
+ val speedFieldIndex = indexOfFirstSpeedFieldInstruction(this )
173
+ hookRelativeSpeedValue(speedFieldIndex)
174
+ }
175
+ }
124
176
}
125
177
}
126
178
@@ -241,6 +293,8 @@ private val speedOverlayPatch = bytecodePatch(
241
293
move-result v$speedOverlayFloatValueRegister
242
294
"""
243
295
)
296
+
297
+ hookRelativeSpeedValue(speedOverlayFloatValueIndex)
244
298
}
245
299
246
300
// Removed in YouTube 20.03+
0 commit comments