diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt index 7f9863b74a..57729390c7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt @@ -10,7 +10,7 @@ val disableAdsPatch = bytecodePatch( "Disable ads", ) { // 6.55.3 and higher can show ads after each exercise. - compatibleWith("com.duolingo"("6.54.5")) + compatibleWith("com.duolingo") execute { // Couple approaches to remove ads exist: diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt index bec800f50c..d8229abd81 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt @@ -2,7 +2,10 @@ package app.revanced.patches.duolingo.energy import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.bytecodePatch -import app.revanced.util.findFieldFromToString +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.StringReference @Suppress("unused") val skipEnergyRechargeAdsPatch = bytecodePatch( @@ -15,8 +18,38 @@ val skipEnergyRechargeAdsPatch = bytecodePatch( initializeEnergyConfigFingerprint .match(energyConfigToStringFingerprint.classDef) .method.apply { - val energyField = energyConfigToStringFingerprint.method - .findFieldFromToString("energy=") + val toStringMethod = energyConfigToStringFingerprint.method + val instructions = toStringMethod.implementation!!.instructions.toList() + + var energyField: String? = null + + // Search for the string "energy=" and get the preceding IGET instruction. + for (i in instructions.indices) { + val instr = instructions[i] + val ref = (instr as? ReferenceInstruction)?.reference + + if (ref is StringReference && ref.string.contains("energy=")) { + // Search backwards for the field getter (IGET) + for (j in i downTo 0) { + val prevInstr = instructions[j] + if (prevInstr.opcode == Opcode.IGET) { + val fieldRef = (prevInstr as ReferenceInstruction).reference as FieldReference + // Construct the full valid Smali field reference: Lclass;->name:type + energyField = "${fieldRef.definingClass}->${fieldRef.name}:${fieldRef.type}" + break + } + } + break + } + } + + // Fallback: The first IGET instruction is guaranteed to be the 'energy' property. + if (energyField == null) { + val fallbackInstr = instructions.first { it.opcode == Opcode.IGET } + val fieldRef = (fallbackInstr as ReferenceInstruction).reference as FieldReference + energyField = "${fieldRef.definingClass}->${fieldRef.name}:${fieldRef.type}" + } + val insertIndex = initializeEnergyConfigFingerprint.patternMatch!!.startIndex addInstructions(