diff --git a/src/main/kotlin/app/revanced/patches/layout/CreateButtonRemover.kt b/src/main/kotlin/app/revanced/patches/layout/CreateButtonRemover.kt index dea467dd5..5a0c6ae73 100644 --- a/src/main/kotlin/app/revanced/patches/layout/CreateButtonRemover.kt +++ b/src/main/kotlin/app/revanced/patches/layout/CreateButtonRemover.kt @@ -13,7 +13,7 @@ class CreateButtonRemover : Patch("create-button-remover") { // Hide the button view via proxy by passing it to the hideCreateButton method map.method.implementation!!.addInstruction( map.scanData.endIndex, - "invoke-static { v6 }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".asInstruction() + "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".asInstruction() ) return PatchResultSuccess() diff --git a/src/main/kotlin/app/revanced/patches/layout/HideReels.kt b/src/main/kotlin/app/revanced/patches/layout/HideReels.kt index 3d524a74f..6e1242884 100644 --- a/src/main/kotlin/app/revanced/patches/layout/HideReels.kt +++ b/src/main/kotlin/app/revanced/patches/layout/HideReels.kt @@ -8,12 +8,13 @@ import app.revanced.patcher.smali.asInstruction class HideReels : Patch("hide-reels") { override fun execute(cache: Cache): PatchResult { - val implementation = cache.methodMap["hide-reel-patch"].method.implementation!! + val map = cache.methodMap["hide-reel-patch"] + val implementation = map.method.implementation!! // HideReel will hide the reel view before it is being used, // so we pass the view to the HideReel method implementation.addInstruction( - 22, + map.scanData.endIndex - 1, "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".asInstruction() ) diff --git a/src/main/kotlin/app/revanced/patches/layout/HideSuggestions.kt b/src/main/kotlin/app/revanced/patches/layout/HideSuggestions.kt index 4c17bfa02..9338c4e2a 100644 --- a/src/main/kotlin/app/revanced/patches/layout/HideSuggestions.kt +++ b/src/main/kotlin/app/revanced/patches/layout/HideSuggestions.kt @@ -7,10 +7,17 @@ import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.signature.MethodSignature import app.revanced.patcher.smali.asInstructions import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction22c +import org.jf.dexlib2.builder.instruction.BuilderInstruction35c +import org.jf.dexlib2.iface.instruction.formats.Instruction22c +import org.jf.dexlib2.iface.instruction.formats.Instruction35c +import org.jf.dexlib2.immutable.ImmutableMethod +import org.jf.dexlib2.immutable.ImmutableMethodImplementation class HideSuggestions : Patch("hide-suggestions") { override fun execute(cache: Cache): PatchResult { @@ -30,16 +37,75 @@ class HideSuggestions : Patch("hide-suggestions") { ) ) ?: return PatchResultError("Parent method hide-suggestions-method has not been found") - // Proxy the first parameter by passing it to the RemoveSuggestions method - map.method.implementation!!.addInstructions( + // deep clone the method in order to add a new register + // TODO: replace by a mutable method implementation with settable register count when available + val originalMethod = map.immutableMethod + val originalImplementation = originalMethod.implementation!! + val clonedMethod = ImmutableMethod( + originalMethod.returnType, + originalMethod.name, + originalMethod.parameters, + originalMethod.returnType, + originalMethod.accessFlags, + originalMethod.annotations, + originalMethod.hiddenApiRestrictions, + ImmutableMethodImplementation( + originalImplementation.registerCount + 1, // additional register for the boolean + originalImplementation.instructions, + originalImplementation.tryBlocks, + originalImplementation.debugItems, + ) + ).toMutable() // create mutable clone out of the immutable method clone + + val clonedImplementation = clonedMethod.implementation!! + + // fix the instructions registers + clonedImplementation.instructions.forEachIndexed { index, it -> + val opcode = it.opcode + // increment all registers (instance register and object register) by 1 + // due to adding a new virtual register for the boolean value + clonedImplementation.replaceInstruction( + index, + when (it) { + is Instruction22c -> BuilderInstruction22c( + opcode, + it.registerA + 1, // increment register + it.registerB + 1, // increment register + it.reference + ) + is Instruction35c -> BuilderInstruction35c( + opcode, + 1, + it.registerC + 1, // increment register + 0, + 0, + 0, + 0, + it.reference + ) + else -> return@forEachIndexed + } + ) + } + + // resolve the class proxy + val clazz = map.definingClassProxy.resolve() + + // remove the old method & add the clone with our additional register + clazz.methods.remove(originalMethod) + clazz.methods.add(clonedMethod) + + // Proxy the first parameter of our clone by passing it to the RemoveSuggestions method + // TODO: this crashes, find out why + clonedImplementation.addInstructions( 0, """ - invoke-static { p1 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean; + invoke-static/range { v2 .. v2 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean; move-result-object v0 invoke-static { v0 }, Lfi/razerman/youtube/XAdRemover;->RemoveSuggestions(Ljava/lang/Boolean;)Ljava/lang/Boolean; move-result-object v0 - invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z - move-result v0 + invoke-virtual/range { v0 .. v0 }, Ljava/lang/Boolean;->booleanValue()Z + move-result v2 """.trimIndent().asInstructions() ) return PatchResultSuccess() diff --git a/src/main/kotlin/app/revanced/patches/layout/OldQualityLayout.kt b/src/main/kotlin/app/revanced/patches/layout/OldQualityLayout.kt index 6d7435028..ab52b323b 100644 --- a/src/main/kotlin/app/revanced/patches/layout/OldQualityLayout.kt +++ b/src/main/kotlin/app/revanced/patches/layout/OldQualityLayout.kt @@ -1,13 +1,14 @@ package app.revanced.patches.layout import app.revanced.patcher.cache.Cache +import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.signature.MethodSignature -import app.revanced.patcher.smali.asInstruction +import app.revanced.patcher.smali.asInstructions import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode import org.jf.dexlib2.builder.instruction.BuilderInstruction21t @@ -38,12 +39,12 @@ class OldQualityLayout : Patch("old-quality-restore") { val jmpInstruction = BuilderInstruction21t(Opcode.IF_NEZ, 0, implementation.instructions[5].location.labels.first()) implementation.addInstruction(0, jmpInstruction) - implementation.addInstruction( + implementation.addInstructions( 0, """ invoke-static { }, Lfi/razerman/youtube/XGlobals;->useOldStyleQualitySettings()Z move-result v0 - """.trimIndent().asInstruction() + """.trimIndent().asInstructions() ) return PatchResultSuccess()