feat(youtube/custom-playback-speed): change to abstract patch

This commit is contained in:
inotia00 2023-09-17 23:15:02 +09:00
parent 907bcb9107
commit ec1ac206fe
5 changed files with 125 additions and 112 deletions

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.customspeed.fingerprints package app.revanced.patches.shared.fingerprints.customspeed
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.customspeed.fingerprints package app.revanced.patches.shared.fingerprints.customspeed
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
@ -11,10 +11,8 @@ object SpeedLimiterFallBackFingerprint : MethodFingerprint(
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes = listOf(
Opcode.CONST_HIGH16, Opcode.CONST_HIGH16,
Opcode.GOTO,
Opcode.CONST_HIGH16, Opcode.CONST_HIGH16,
Opcode.CONST_HIGH16, Opcode.INVOKE_STATIC
Opcode.INVOKE_STATIC,
), ),
strings = listOf("Playback rate: %f") strings = listOf("Playback rate: %f")
) )

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.customspeed.fingerprints package app.revanced.patches.shared.fingerprints.customspeed
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
@ -10,11 +10,6 @@ object SpeedLimiterFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("F"), parameters = listOf("F"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.CONST_HIGH16,
Opcode.GOTO,
Opcode.CONST_HIGH16, Opcode.CONST_HIGH16,
Opcode.CONST_HIGH16, Opcode.CONST_HIGH16,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,

View File

@ -0,0 +1,116 @@
package app.revanced.patches.shared.patch.customspeed
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.shared.fingerprints.customspeed.SpeedArrayGeneratorFingerprint
import app.revanced.patches.shared.fingerprints.customspeed.SpeedLimiterFallBackFingerprint
import app.revanced.patches.shared.fingerprints.customspeed.SpeedLimiterFingerprint
import com.android.tools.smali.dexlib2.Opcode
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.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
abstract class AbstractCustomPlaybackSpeedPatch(
private val descriptor: String,
private val maxSpeed: Float
) : BytecodePatch(
listOf(
SpeedArrayGeneratorFingerprint,
SpeedLimiterFallBackFingerprint
)
) {
override fun execute(context: BytecodeContext) {
SpeedArrayGeneratorFingerprint.result?.let { result ->
result.mutableMethod.apply {
val targetIndex = result.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $descriptor->getLength(I)I
move-result v$targetRegister
"""
)
val targetInstruction = implementation!!.instructions
for ((index, instruction) in targetInstruction.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_INTERFACE) continue
val sizeInstruction = getInstruction<Instruction35c>(index)
if ((sizeInstruction.reference as MethodReference).name != "size") continue
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
addInstructions(
index + 2, """
invoke-static {v$register}, $descriptor->getSize(I)I
move-result v$register
"""
)
break
}
for ((index, instruction) in targetInstruction.withIndex()) {
if (instruction.opcode != Opcode.SGET_OBJECT) continue
val targetReference =
getInstruction<ReferenceInstruction>(index).reference.toString()
if (targetReference.endsWith(":[F")) {
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
index + 1, """
invoke-static {v$register}, $descriptor->getArray([F)[F
move-result-object v$register
"""
)
break
}
}
}
} ?: throw SpeedArrayGeneratorFingerprint.exception
val speedLimiterParentResult = SpeedLimiterFallBackFingerprint.result
?: throw SpeedLimiterFallBackFingerprint.exception
SpeedLimiterFingerprint.resolve(context, speedLimiterParentResult.classDef)
val speedLimiterResult = SpeedLimiterFingerprint.result
?: throw SpeedLimiterFingerprint.exception
arrayOf(
speedLimiterParentResult,
speedLimiterResult
).forEach { result ->
result.mutableMethod.apply {
val limiterMinConstIndex =
implementation!!.instructions.indexOfFirst { (it as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() }
val limiterMaxConstIndex =
implementation!!.instructions.indexOfFirst { (it as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() }
val limiterMinConstDestination =
getInstruction<OneRegisterInstruction>(limiterMinConstIndex).registerA
val limiterMaxConstDestination =
getInstruction<OneRegisterInstruction>(limiterMaxConstIndex).registerA
replaceInstruction(
limiterMinConstIndex,
"const/high16 v$limiterMinConstDestination, 0x0"
)
replaceInstruction(
limiterMaxConstIndex,
"const/high16 v$limiterMaxConstDestination, ${maxSpeed.toRawBits()}"
)
}
}
}
}

View File

@ -1,28 +1,15 @@
package app.revanced.patches.youtube.video.customspeed.patch package app.revanced.patches.youtube.video.customspeed.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.patch.customspeed.AbstractCustomPlaybackSpeedPatch
import app.revanced.patches.youtube.flyoutpanel.oldspeedlayout.patch.OldSpeedLayoutPatch import app.revanced.patches.youtube.flyoutpanel.oldspeedlayout.patch.OldSpeedLayoutPatch
import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility
import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch
import app.revanced.patches.youtube.video.customspeed.fingerprints.SpeedArrayGeneratorFingerprint
import app.revanced.patches.youtube.video.customspeed.fingerprints.SpeedLimiterFallBackFingerprint
import app.revanced.patches.youtube.video.customspeed.fingerprints.SpeedLimiterFingerprint
import app.revanced.util.integrations.Constants.VIDEO_PATH import app.revanced.util.integrations.Constants.VIDEO_PATH
import com.android.tools.smali.dexlib2.Opcode
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.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch @Patch
@Name("Custom playback speed") @Name("Custom playback speed")
@ -34,94 +21,12 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
] ]
) )
@YouTubeCompatibility @YouTubeCompatibility
class CustomPlaybackSpeedPatch : BytecodePatch( class CustomPlaybackSpeedPatch : AbstractCustomPlaybackSpeedPatch(
listOf( "$VIDEO_PATH/CustomPlaybackSpeedPatch;",
SpeedArrayGeneratorFingerprint, 10.0f
SpeedLimiterFallBackFingerprint,
SpeedLimiterFingerprint
)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SpeedArrayGeneratorFingerprint.result?.let { result -> super.execute(context)
result.mutableMethod.apply {
val targetIndex = result.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $VIDEO_PATH/CustomPlaybackSpeedPatch;->getLength(I)I
move-result v$targetRegister
"""
)
val targetInstruction = implementation!!.instructions
for ((index, instruction) in targetInstruction.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_INTERFACE) continue
val sizeInstruction = getInstruction<Instruction35c>(index)
if ((sizeInstruction.reference as MethodReference).name != "size") continue
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
addInstructions(
index + 2, """
invoke-static {v$register}, $VIDEO_PATH/CustomPlaybackSpeedPatch;->getSize(I)I
move-result v$register
"""
)
break
}
for ((index, instruction) in targetInstruction.withIndex()) {
if (instruction.opcode != Opcode.SGET_OBJECT) continue
val targetReference =
getInstruction<ReferenceInstruction>(index).reference.toString()
if (targetReference.contains("PlayerConfigModel;") && targetReference.endsWith("[F")) {
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
index + 1, """
invoke-static {v$register}, $VIDEO_PATH/CustomPlaybackSpeedPatch;->getArray([F)[F
move-result-object v$register
"""
)
break
}
}
}
} ?: throw SpeedArrayGeneratorFingerprint.exception
arrayOf(
SpeedLimiterFallBackFingerprint,
SpeedLimiterFingerprint
).forEach { fingerprint ->
fingerprint.result?.let { result ->
result.mutableMethod.apply {
val limiterMinConstIndex =
implementation!!.instructions.indexOfFirst { (it as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() }
val limiterMaxConstIndex =
implementation!!.instructions.indexOfFirst { (it as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() }
val limiterMinConstDestination =
getInstruction<OneRegisterInstruction>(limiterMinConstIndex).registerA
val limiterMaxConstDestination =
getInstruction<OneRegisterInstruction>(limiterMaxConstIndex).registerA
replaceInstruction(
limiterMinConstIndex,
"const/high16 v$limiterMinConstDestination, 0x0"
)
replaceInstruction(
limiterMaxConstIndex,
"const/high16 v$limiterMaxConstDestination, 0x41200000 # 10.0f"
)
}
} ?: throw fingerprint.exception
}
/** /**
* Add settings * Add settings
@ -134,6 +39,5 @@ class CustomPlaybackSpeedPatch : BytecodePatch(
) )
SettingsPatch.updatePatchStatus("custom-playback-speed") SettingsPatch.updatePatchStatus("custom-playback-speed")
} }
} }