diff --git a/src/main/kotlin/app/revanced/patches/nova/prime/annotations/UnlockPrimeCompatibility.kt b/src/main/kotlin/app/revanced/patches/nova/prime/annotations/UnlockPrimeCompatibility.kt new file mode 100644 index 00000000..de55cf94 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/nova/prime/annotations/UnlockPrimeCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.nova.prime.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [ + Package("com.teslacoilsw.launcher") + ] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class UnlockPrimeCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/nova/prime/fingerprints/UnlockPrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/nova/prime/fingerprints/UnlockPrimeFingerprint.kt new file mode 100644 index 00000000..69d2902a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/nova/prime/fingerprints/UnlockPrimeFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.nova.prime.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object UnlockPrimeFingerprint : MethodFingerprint( + "V", + opcodes = listOf( + Opcode.IPUT_OBJECT, + Opcode.CONST_STRING, + Opcode.CONST_4, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT + ), + strings = listOf("1") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/nova/prime/patch/UnlockPrimePatch.kt b/src/main/kotlin/app/revanced/patches/nova/prime/patch/UnlockPrimePatch.kt new file mode 100644 index 00000000..0b6ae48e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/nova/prime/patch/UnlockPrimePatch.kt @@ -0,0 +1,50 @@ +package app.revanced.patches.nova.prime.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.nova.prime.annotations.UnlockPrimeCompatibility +import app.revanced.patches.nova.prime.fingerprints.UnlockPrimeFingerprint +import org.jf.dexlib2.builder.instruction.BuilderInstruction11x + +@Patch +@Name("unlock-prime") +@Description("Unlocks Nova Prime and all functions of the app.") +@UnlockPrimeCompatibility +@Version("0.0.1") +class UnlockPrimePatch : BytecodePatch( + listOf( + UnlockPrimeFingerprint + ) +) { + private companion object { + // Any value except 0 unlocks prime, but 512 is needed for a protection mechanism + // which would reset the preferences if the value on disk had changed after a restart. + const val PRIME_STATUS: Int = 512 + } + + override fun execute(context: BytecodeContext): PatchResult { + UnlockPrimeFingerprint.result?.apply { + val insertIndex = scanResult.patternScanResult!!.endIndex + 1 + + val primeStatusRegister = + (mutableMethod.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA + + mutableMethod.addInstruction( + insertIndex, + """ + const/16 v$primeStatusRegister, $PRIME_STATUS + """ + ) + } ?: UnlockPrimeFingerprint.toErrorResult() + + return PatchResultSuccess() + } +}