mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-12 04:24:36 +02:00
add suport YouTube v18.06.35
This commit is contained in:
parent
9030abe616
commit
8427f28208
@ -3,7 +3,7 @@ package app.revanced.patches.shared.annotation
|
|||||||
import app.revanced.patcher.annotation.Compatibility
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
import app.revanced.patcher.annotation.Package
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.05.40"))])
|
@Compatibility([Package("com.google.android.youtube", arrayOf("18.06.35"))])
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
internal annotation class YouTubeCompatibility
|
internal annotation class YouTubeCompatibility
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package app.revanced.patches.shared.fingerprints
|
package app.revanced.patches.shared.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.AccessFlags
|
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
object MainstreamVideoAdsFingerprint : MethodFingerprint(
|
object MainstreamVideoAdsFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L","Z"),
|
parameters = listOf("L","Z"),
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
Opcode.IGET_OBJECT,
|
Opcode.IGET_OBJECT,
|
||||||
|
@ -10,7 +10,6 @@ import org.jf.dexlib2.Opcode
|
|||||||
object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
|
object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("Z"),
|
|
||||||
customFingerprint = { methodDef ->
|
customFingerprint = { methodDef ->
|
||||||
methodDef.implementation?.instructions?.any {
|
methodDef.implementation?.instructions?.any {
|
||||||
it.opcode.ordinal == Opcode.CONST.ordinal &&
|
it.opcode.ordinal == Opcode.CONST.ordinal &&
|
||||||
|
@ -8,6 +8,7 @@ import app.revanced.patcher.data.toMethodWalker
|
|||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.instruction
|
import app.revanced.patcher.extensions.instruction
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
@ -26,34 +27,30 @@ class GeneralVideoAdsPatch : BytecodePatch(
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val LegacyVideoAdsResult = LegacyVideoAdsFingerprint.result ?: return LegacyVideoAdsFingerprint.toErrorResult()
|
val legacyVideoAdsResult = LegacyVideoAdsFingerprint.result ?: return LegacyVideoAdsFingerprint.toErrorResult()
|
||||||
|
|
||||||
LegacyVideoAdsMethod =
|
legacyVideoAdsMethod =
|
||||||
context.toMethodWalker(LegacyVideoAdsResult.method)
|
context.toMethodWalker(legacyVideoAdsResult.method)
|
||||||
.nextMethod(13, true)
|
.nextMethod(13, true)
|
||||||
.getMethod() as MutableMethod
|
.getMethod() as MutableMethod
|
||||||
|
|
||||||
MainstreamVideoAdsFingerprint.resolve(context, MainstreamVideoAdsParentFingerprint.result!!.classDef)
|
MainstreamVideoAdsParentFingerprint.result?.let { parentResult ->
|
||||||
|
MainstreamVideoAdsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let {
|
||||||
val MainstreamAdsResult = MainstreamVideoAdsFingerprint.result ?: return MainstreamVideoAdsFingerprint.toErrorResult()
|
mainstreamVideoAdsResult = it
|
||||||
|
} ?: return MainstreamVideoAdsFingerprint.toErrorResult()
|
||||||
MainstreamVideoAdsMethod = MainstreamAdsResult.mutableMethod
|
} ?: return MainstreamVideoAdsParentFingerprint.toErrorResult()
|
||||||
|
|
||||||
InsertIndex = MainstreamAdsResult.scanResult.patternScanResult!!.endIndex
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal companion object {
|
internal companion object {
|
||||||
var InsertIndex: Int = 0
|
lateinit var legacyVideoAdsMethod: MutableMethod
|
||||||
|
lateinit var mainstreamVideoAdsResult: MethodFingerprintResult
|
||||||
lateinit var LegacyVideoAdsMethod: MutableMethod
|
|
||||||
lateinit var MainstreamVideoAdsMethod: MutableMethod
|
|
||||||
|
|
||||||
fun injectLegacyAds(
|
fun injectLegacyAds(
|
||||||
descriptor: String
|
descriptor: String
|
||||||
) {
|
) {
|
||||||
LegacyVideoAdsMethod.addInstructions(
|
legacyVideoAdsMethod.addInstructions(
|
||||||
0, """
|
0, """
|
||||||
invoke-static {}, $descriptor
|
invoke-static {}, $descriptor
|
||||||
move-result v1
|
move-result v1
|
||||||
@ -64,13 +61,16 @@ class GeneralVideoAdsPatch : BytecodePatch(
|
|||||||
fun injectMainstreamAds(
|
fun injectMainstreamAds(
|
||||||
descriptor: String
|
descriptor: String
|
||||||
) {
|
) {
|
||||||
MainstreamVideoAdsMethod.addInstructions(
|
val mainstreamVideoAdsMethod = mainstreamVideoAdsResult.mutableMethod
|
||||||
InsertIndex, """
|
val insertIndex = mainstreamVideoAdsResult.scanResult.patternScanResult!!.endIndex
|
||||||
|
|
||||||
|
mainstreamVideoAdsMethod.addInstructions(
|
||||||
|
insertIndex, """
|
||||||
invoke-static {}, $descriptor
|
invoke-static {}, $descriptor
|
||||||
move-result v1
|
move-result v1
|
||||||
if-nez v1, :show_video_ads
|
if-nez v1, :show_video_ads
|
||||||
return-void
|
return-void
|
||||||
""", listOf(ExternalLabel("show_video_ads", MainstreamVideoAdsMethod.instruction(InsertIndex)))
|
""", listOf(ExternalLabel("show_video_ads", mainstreamVideoAdsMethod.instruction(insertIndex)))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,9 @@ import app.revanced.patches.youtube.layout.fullscreen.fullscreenpanels.fingerpri
|
|||||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
||||||
import app.revanced.util.integrations.Constants.FULLSCREEN_LAYOUT
|
import app.revanced.util.integrations.Constants.FULLSCREEN_LAYOUT
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@ -57,6 +59,29 @@ class HideFullscreenPanelsPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
} ?: return FullscreenViewAdderFingerprint.toErrorResult()
|
} ?: return FullscreenViewAdderFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
|
||||||
|
val instructions = method.implementation!!.instructions
|
||||||
|
val registerIndex = instructions.indexOfFirst {
|
||||||
|
it.opcode == Opcode.CONST_STRING &&
|
||||||
|
(it as BuilderInstruction21c).reference.toString() == "1.0x"
|
||||||
|
}
|
||||||
|
val dummyRegister = (instructions[registerIndex] as Instruction21c).registerA
|
||||||
|
|
||||||
|
val invokeIndex = method.implementation!!.instructions.indexOfFirst {
|
||||||
|
it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal &&
|
||||||
|
((it as? BuilderInstruction35c)?.reference.toString() ==
|
||||||
|
"Landroid/widget/FrameLayout;->addView(Landroid/view/View;)V")
|
||||||
|
}
|
||||||
|
|
||||||
|
method.addInstructions(
|
||||||
|
invokeIndex, """
|
||||||
|
invoke-static {}, $FULLSCREEN_LAYOUT->hideFullscreenPanel()Z
|
||||||
|
move-result v$dummyRegister
|
||||||
|
if-nez v$dummyRegister, :hidden
|
||||||
|
""", listOf(ExternalLabel("hidden", method.instruction(invokeIndex + 1)))
|
||||||
|
)
|
||||||
|
} ?: return LayoutConstructorFingerprint.toErrorResult()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add settings
|
* Add settings
|
||||||
*/
|
*/
|
||||||
@ -70,22 +95,6 @@ class HideFullscreenPanelsPatch : BytecodePatch(
|
|||||||
|
|
||||||
SettingsPatch.updatePatchStatus("hide-fullscreen-panels")
|
SettingsPatch.updatePatchStatus("hide-fullscreen-panels")
|
||||||
|
|
||||||
LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
|
|
||||||
val invokeIndex = method.implementation!!.instructions.indexOfFirst {
|
|
||||||
it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal &&
|
|
||||||
((it as? BuilderInstruction35c)?.reference.toString() ==
|
|
||||||
"Landroid/widget/FrameLayout;->addView(Landroid/view/View;)V")
|
|
||||||
}
|
|
||||||
|
|
||||||
method.addInstructions(
|
|
||||||
invokeIndex, """
|
|
||||||
invoke-static {}, $FULLSCREEN_LAYOUT->hideFullscreenPanel()Z
|
|
||||||
move-result v15
|
|
||||||
if-nez v15, :hidden
|
|
||||||
""", listOf(ExternalLabel("hidden", method.instruction(invokeIndex + 1)))
|
|
||||||
)
|
|
||||||
} ?: return LayoutConstructorFingerprint.toErrorResult()
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
|
|
||||||
|
object CrowdfundingBoxFingerprint : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT
|
||||||
|
),
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.implementation?.instructions?.any {
|
||||||
|
it.opcode.ordinal == Opcode.CONST.ordinal &&
|
||||||
|
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.donationCompanionResourceId
|
||||||
|
} == true
|
||||||
|
}
|
||||||
|
)
|
@ -1,76 +1,54 @@
|
|||||||
package app.revanced.patches.youtube.layout.general.crowdfundingbox.patch
|
package app.revanced.patches.youtube.layout.general.crowdfundingbox.patch
|
||||||
|
|
||||||
import app.revanced.extensions.findMutableMethodOf
|
import app.revanced.extensions.toErrorResult
|
||||||
import app.revanced.extensions.injectHideCall
|
|
||||||
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.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.instruction
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
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.annotation.YouTubeCompatibility
|
import app.revanced.patches.shared.annotation.YouTubeCompatibility
|
||||||
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
|
import app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint
|
||||||
|
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
||||||
import org.jf.dexlib2.Opcode
|
import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
|
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("hide-crowdfunding-box")
|
@Name("hide-crowdfunding-box")
|
||||||
@Description("Hides the crowdfunding box between the player and video description.")
|
@Description("Hides the crowdfunding box between the player and video description.")
|
||||||
@DependsOn(
|
@DependsOn(
|
||||||
[
|
[
|
||||||
ResourceMappingPatch::class,
|
SettingsPatch::class,
|
||||||
SettingsPatch::class
|
SharedResourcdIdPatch::class
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@YouTubeCompatibility
|
@YouTubeCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class CrowdfundingBoxPatch : BytecodePatch() {
|
class CrowdfundingBoxPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
// list of resource names to get the id of
|
CrowdfundingBoxFingerprint
|
||||||
private val resourceIds = arrayOf(
|
)
|
||||||
"donation_companion"
|
) {
|
||||||
).map { name ->
|
|
||||||
ResourceMappingPatch.resourceMappings.single { it.name == name }.id
|
|
||||||
}
|
|
||||||
private var patchSuccessArray = Array(resourceIds.size) {false}
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
context.classes.forEach { classDef ->
|
|
||||||
classDef.methods.forEach { method ->
|
|
||||||
with(method.implementation) {
|
|
||||||
this?.instructions?.forEachIndexed { index, instruction ->
|
|
||||||
when (instruction.opcode) {
|
|
||||||
Opcode.CONST -> {
|
|
||||||
when ((instruction as Instruction31i).wideLiteral) {
|
|
||||||
resourceIds[0] -> { // crowdfunding
|
|
||||||
val insertIndex = index + 3
|
|
||||||
val iPutInstruction = instructions.elementAt(insertIndex)
|
|
||||||
if (iPutInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
|
|
||||||
|
|
||||||
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method)
|
CrowdfundingBoxFingerprint.result?.let {
|
||||||
|
with (it.mutableMethod) {
|
||||||
|
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
|
val register = (instruction(insertIndex) as TwoRegisterInstruction).registerA
|
||||||
|
|
||||||
val viewRegister = (iPutInstruction as Instruction22c).registerA
|
addInstruction(
|
||||||
mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "layout/GeneralLayoutPatch", "hideCrowdfundingBox")
|
insertIndex,
|
||||||
patchSuccessArray[0] = true;
|
"invoke-static {v$register}, $GENERAL_LAYOUT->hideCrowdfundingBox(Landroid/view/View;)V"
|
||||||
}
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> return@forEachIndexed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} ?: return CrowdfundingBoxFingerprint.toErrorResult()
|
||||||
|
|
||||||
val errorIndex: Int = patchSuccessArray.indexOf(false)
|
|
||||||
|
|
||||||
if (errorIndex == -1) {
|
|
||||||
/*
|
/*
|
||||||
* Add settings
|
* Add settings
|
||||||
*/
|
*/
|
||||||
@ -84,7 +62,5 @@ class CrowdfundingBoxPatch : BytecodePatch() {
|
|||||||
SettingsPatch.updatePatchStatus("hide-crowdfunding-box")
|
SettingsPatch.updatePatchStatus("hide-crowdfunding-box")
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
} else
|
|
||||||
return PatchResultError("Instruction not found: $errorIndex")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@ import org.jf.dexlib2.Opcode
|
|||||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
|
|
||||||
object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint(
|
object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint(
|
||||||
"V",
|
returnType = "V",
|
||||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
customFingerprint = { methodDef ->
|
customFingerprint = { methodDef ->
|
||||||
methodDef.implementation?.instructions?.any {
|
methodDef.implementation?.instructions?.any {
|
||||||
it.opcode.ordinal == Opcode.CONST.ordinal &&
|
it.opcode.ordinal == Opcode.CONST.ordinal &&
|
||||||
|
@ -9,5 +9,5 @@ object MiniPlayerOverrideFingerprint : MethodFingerprint(
|
|||||||
returnType = "Z",
|
returnType = "Z",
|
||||||
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
parameters = listOf("L"),
|
parameters = listOf("L"),
|
||||||
opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction
|
opcodes = listOf(Opcode.INVOKE_STATIC), // anchor to insert the instruction
|
||||||
)
|
)
|
@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object MiniPlayerOverrideParentFingerprint : MethodFingerprint(
|
||||||
|
returnType = "L",
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
strings = listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT")
|
||||||
|
)
|
@ -5,6 +5,7 @@ import app.revanced.patcher.annotation.Description
|
|||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.data.toMethodWalker
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||||
@ -19,6 +20,7 @@ import app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints
|
|||||||
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
|
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
||||||
import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
|
import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@ -35,31 +37,33 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
|||||||
class TabletMiniPlayerPatch : BytecodePatch(
|
class TabletMiniPlayerPatch : BytecodePatch(
|
||||||
listOf(
|
listOf(
|
||||||
MiniPlayerDimensionsCalculatorFingerprint,
|
MiniPlayerDimensionsCalculatorFingerprint,
|
||||||
MiniPlayerResponseModelSizeCheckFingerprint
|
MiniPlayerResponseModelSizeCheckFingerprint,
|
||||||
|
MiniPlayerOverrideParentFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
|
||||||
MiniPlayerDimensionsCalculatorFingerprint.result?.let { parentResult ->
|
MiniPlayerDimensionsCalculatorFingerprint.result?.let { parentResult ->
|
||||||
// first resolve the fingerprints via the parent fingerprint
|
MiniPlayerOverrideNoContextFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
|
||||||
val miniPlayerClass = parentResult.classDef
|
|
||||||
|
|
||||||
arrayOf(
|
|
||||||
MiniPlayerOverrideNoContextFingerprint,
|
|
||||||
MiniPlayerOverrideFingerprint,
|
|
||||||
MiniPlayerResponseModelSizeCheckFingerprint
|
|
||||||
).map {
|
|
||||||
it to (it.also { it.resolve(context, miniPlayerClass) }.result ?: return it.toErrorResult())
|
|
||||||
}.forEach { (fingerprint, result) ->
|
|
||||||
if (fingerprint == MiniPlayerOverrideNoContextFingerprint) {
|
|
||||||
val (method, _, parameterRegister) = result.addProxyCall()
|
val (method, _, parameterRegister) = result.addProxyCall()
|
||||||
method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister)
|
method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister)
|
||||||
} else {
|
} ?: return MiniPlayerOverrideNoContextFingerprint.toErrorResult()
|
||||||
val (_, _, _) = result.addProxyCall()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ?: return MiniPlayerDimensionsCalculatorFingerprint.toErrorResult()
|
} ?: return MiniPlayerDimensionsCalculatorFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
MiniPlayerOverrideParentFingerprint.result?.let { parentResult ->
|
||||||
|
MiniPlayerOverrideFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
|
||||||
|
(context.toMethodWalker(result.method)
|
||||||
|
.nextMethod(result.scanResult.patternScanResult!!.startIndex, true)
|
||||||
|
.getMethod() as MutableMethod)
|
||||||
|
.instructionProxyCall()
|
||||||
|
} ?: return MiniPlayerOverrideFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
} ?: return MiniPlayerOverrideParentFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
MiniPlayerResponseModelSizeCheckFingerprint.result?.let {
|
||||||
|
val (_, _, _) = it.addProxyCall()
|
||||||
|
} ?: return MiniPlayerResponseModelSizeCheckFingerprint.toErrorResult()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add settings
|
* Add settings
|
||||||
*/
|
*/
|
||||||
@ -94,6 +98,17 @@ class TabletMiniPlayerPatch : BytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun MutableMethod.instructionProxyCall() {
|
||||||
|
val insertInstructions = this.implementation!!.instructions
|
||||||
|
for ((index, instruction) in insertInstructions.withIndex()) {
|
||||||
|
if (instruction.opcode != Opcode.RETURN) continue
|
||||||
|
val parameterRegister = (instruction as OneRegisterInstruction).registerA
|
||||||
|
this.insertOverride(index, parameterRegister)
|
||||||
|
this.insertOverride(insertInstructions.size - 1, parameterRegister)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun MethodFingerprintResult.unwrap(): Triple<MutableMethod, Int, Int> {
|
fun MethodFingerprintResult.unwrap(): Triple<MutableMethod, Int, Int> {
|
||||||
val scanIndex = this.scanResult.patternScanResult!!.endIndex
|
val scanIndex = this.scanResult.patternScanResult!!.endIndex
|
||||||
val method = this.mutableMethod
|
val method = this.mutableMethod
|
||||||
|
@ -17,9 +17,12 @@ import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
|
|||||||
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
|
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
|
||||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
||||||
import app.revanced.util.integrations.Constants.PLAYER_LAYOUT
|
import app.revanced.util.integrations.Constants.PLAYER_LAYOUT
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
|
||||||
import org.jf.dexlib2.iface.instruction.Instruction
|
import org.jf.dexlib2.iface.instruction.Instruction
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference
|
import org.jf.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@ -46,6 +49,12 @@ class HideAutoplayButtonPatch : BytecodePatch(
|
|||||||
|
|
||||||
LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
|
LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
|
||||||
with (method.implementation!!.instructions) {
|
with (method.implementation!!.instructions) {
|
||||||
|
val registerIndex = indexOfFirst {
|
||||||
|
it.opcode == Opcode.CONST_STRING &&
|
||||||
|
(it as BuilderInstruction21c).reference.toString() == "1.0x"
|
||||||
|
}
|
||||||
|
val dummyRegister = (this[registerIndex] as Instruction21c).registerA
|
||||||
|
|
||||||
// where to insert the branch instructions and ...
|
// where to insert the branch instructions and ...
|
||||||
val insertIndex = this.indexOfFirst {
|
val insertIndex = this.indexOfFirst {
|
||||||
(it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId
|
(it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId
|
||||||
@ -60,8 +69,8 @@ class HideAutoplayButtonPatch : BytecodePatch(
|
|||||||
method.addInstructions(
|
method.addInstructions(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
invoke-static {}, $PLAYER_LAYOUT->hideAutoPlayButton()Z
|
invoke-static {}, $PLAYER_LAYOUT->hideAutoPlayButton()Z
|
||||||
move-result v15
|
move-result v$dummyRegister
|
||||||
if-nez v15, :hidden
|
if-nez v$dummyRegister, :hidden
|
||||||
""", listOf(ExternalLabel("hidden", jumpInstruction))
|
""", listOf(ExternalLabel("hidden", jumpInstruction))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ class SharedResourcdIdPatch : ResourcePatch {
|
|||||||
var bottompaneloverlaytextLabelId: Long = -1
|
var bottompaneloverlaytextLabelId: Long = -1
|
||||||
var bottomUiContainerResourceId: Long = -1
|
var bottomUiContainerResourceId: Long = -1
|
||||||
var controlsLayoutStubResourceId: Long = -1
|
var controlsLayoutStubResourceId: Long = -1
|
||||||
|
var donationCompanionResourceId: Long = -1
|
||||||
var educationTextViewResourceId: Long = -1
|
var educationTextViewResourceId: Long = -1
|
||||||
var emptycolorLabelId: Long = -1
|
var emptycolorLabelId: Long = -1
|
||||||
var floatybarQueueLabelId: Long = -1
|
var floatybarQueueLabelId: Long = -1
|
||||||
@ -53,6 +54,7 @@ class SharedResourcdIdPatch : ResourcePatch {
|
|||||||
bottompaneloverlaytextLabelId = findSharedResourceId("id", "bottom_panel_overlay_text")
|
bottompaneloverlaytextLabelId = findSharedResourceId("id", "bottom_panel_overlay_text")
|
||||||
bottomUiContainerResourceId = findSharedResourceId("id", "bottom_ui_container_stub")
|
bottomUiContainerResourceId = findSharedResourceId("id", "bottom_ui_container_stub")
|
||||||
controlsLayoutStubResourceId = findSharedResourceId("id", "controls_layout_stub")
|
controlsLayoutStubResourceId = findSharedResourceId("id", "controls_layout_stub")
|
||||||
|
donationCompanionResourceId = findSharedResourceId("layout", "donation_companion")
|
||||||
educationTextViewResourceId = findSharedResourceId("id", "user_education_text_view")
|
educationTextViewResourceId = findSharedResourceId("id", "user_education_text_view")
|
||||||
emptycolorLabelId = findSharedResourceId("color", "inline_time_bar_colorized_bar_empty_color_dark")
|
emptycolorLabelId = findSharedResourceId("color", "inline_time_bar_colorized_bar_empty_color_dark")
|
||||||
floatybarQueueLabelId = findSharedResourceId("string", "floaty_bar_queue_status")
|
floatybarQueueLabelId = findSharedResourceId("string", "floaty_bar_queue_status")
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.AccessFlags
|
|
||||||
|
|
||||||
object DislikeFingerprint : MethodFingerprint(
|
object DislikeFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
|
|
||||||
strings = listOf("like/dislike")
|
strings = listOf("like/dislike")
|
||||||
)
|
)
|
@ -1,11 +1,8 @@
|
|||||||
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.AccessFlags
|
|
||||||
|
|
||||||
object LikeFingerprint : MethodFingerprint(
|
object LikeFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
|
|
||||||
strings = listOf("like/like")
|
strings = listOf("like/like")
|
||||||
)
|
)
|
@ -1,11 +1,8 @@
|
|||||||
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.AccessFlags
|
|
||||||
|
|
||||||
object RemoveLikeFingerprint : MethodFingerprint(
|
object RemoveLikeFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
|
|
||||||
strings = listOf("like/removelike")
|
strings = listOf("like/removelike")
|
||||||
)
|
)
|
@ -10,6 +10,13 @@ object ShortsTextComponentParentFingerprint : MethodFingerprint(
|
|||||||
access = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
access = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||||
parameters = listOf("L", "L"),
|
parameters = listOf("L", "L"),
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.RETURN_VOID,
|
||||||
Opcode.IGET_OBJECT,
|
Opcode.IGET_OBJECT,
|
||||||
Opcode.CHECK_CAST,
|
Opcode.CHECK_CAST,
|
||||||
Opcode.IGET_BOOLEAN,
|
Opcode.IGET_BOOLEAN,
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
object TextComponentSpecFingerprint : MethodFingerprint(
|
object TextComponentSpecFingerprint : MethodFingerprint(
|
||||||
returnType = "L",
|
returnType = "V",
|
||||||
access = AccessFlags.STATIC.getValue(),
|
access = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
||||||
opcodes = listOf(Opcode.CMPL_FLOAT),
|
parameters = listOf("L"),
|
||||||
customFingerprint = { methodDef ->
|
opcodes = listOf(
|
||||||
methodDef.implementation!!.instructions.any {
|
Opcode.INVOKE_STATIC_RANGE,
|
||||||
((it as? NarrowLiteralInstruction)?.narrowLiteral == 16842907)
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
}
|
Opcode.INVOKE_DIRECT
|
||||||
}
|
)
|
||||||
)
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object TextComponentSpecParentFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
access = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
|
||||||
|
strings = listOf("TextComponent")
|
||||||
|
)
|
@ -7,10 +7,11 @@ import app.revanced.patcher.annotation.Version
|
|||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.data.toMethodWalker
|
import app.revanced.patcher.data.toMethodWalker
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.instruction
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
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
|
||||||
@ -20,7 +21,13 @@ import app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints.*
|
|||||||
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
|
||||||
import app.revanced.patches.youtube.misc.videoid.mainstream.patch.MainstreamVideoIdPatch
|
import app.revanced.patches.youtube.misc.videoid.mainstream.patch.MainstreamVideoIdPatch
|
||||||
import app.revanced.util.integrations.Constants.UTILS_PATH
|
import app.revanced.util.integrations.Constants.UTILS_PATH
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction3rc
|
||||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
import org.jf.dexlib2.iface.reference.FieldReference
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("return-youtube-dislike")
|
@Name("return-youtube-dislike")
|
||||||
@ -39,7 +46,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
LikeFingerprint,
|
LikeFingerprint,
|
||||||
RemoveLikeFingerprint,
|
RemoveLikeFingerprint,
|
||||||
ShortsTextComponentParentFingerprint,
|
ShortsTextComponentParentFingerprint,
|
||||||
TextComponentSpecFingerprint
|
TextComponentSpecParentFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
@ -60,7 +67,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShortsTextComponentParentFingerprint.result?.let {
|
ShortsTextComponentParentFingerprint.result?.let {
|
||||||
with(context
|
with (context
|
||||||
.toMethodWalker(it.method)
|
.toMethodWalker(it.method)
|
||||||
.nextMethod(it.scanResult.patternScanResult!!.endIndex, true)
|
.nextMethod(it.scanResult.patternScanResult!!.endIndex, true)
|
||||||
.getMethod() as MutableMethod
|
.getMethod() as MutableMethod
|
||||||
@ -69,30 +76,57 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
val insertIndex = insertInstructions.size - 1
|
val insertIndex = insertInstructions.size - 1
|
||||||
val insertRegister = (insertInstructions.elementAt(insertIndex) as OneRegisterInstruction).registerA
|
val insertRegister = (insertInstructions.elementAt(insertIndex) as OneRegisterInstruction).registerA
|
||||||
|
|
||||||
|
this.insertShorts(insertIndex, insertRegister)
|
||||||
|
}
|
||||||
|
|
||||||
|
with (it.mutableMethod) {
|
||||||
|
val insertInstructions = this.implementation!!.instructions
|
||||||
|
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||||
|
val insertRegister = (insertInstructions.elementAt(insertIndex - 1) as OneRegisterInstruction).registerA
|
||||||
|
|
||||||
|
this.insertShorts(insertIndex, insertRegister)
|
||||||
|
}
|
||||||
|
} ?: return ShortsTextComponentParentFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
TextComponentSpecParentFingerprint.result?.let { parentResult ->
|
||||||
|
TextComponentSpecFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let {
|
||||||
|
with (it.mutableMethod) {
|
||||||
|
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
|
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
|
|
||||||
|
val dummyRegister = (instruction(startIndex) as BuilderInstruction3rc).registerCount +
|
||||||
|
(instruction(startIndex) as BuilderInstruction3rc).startRegister - 1
|
||||||
|
val targetRegister = (instruction(endIndex) as Instruction35c).registerC
|
||||||
|
|
||||||
|
val instructions = implementation!!.instructions
|
||||||
|
val targetString =
|
||||||
|
((instructions.elementAt(startIndex) as ReferenceInstruction).reference as MethodReference).parameterTypes.first().toString()
|
||||||
|
|
||||||
|
for ((index, instruction) in instructions.withIndex()) {
|
||||||
|
if (instruction.opcode != Opcode.IGET_OBJECT) continue
|
||||||
|
|
||||||
|
val indexReference = (instruction as ReferenceInstruction).reference as FieldReference
|
||||||
|
|
||||||
|
if (indexReference.type != targetString) continue
|
||||||
|
targetReference = indexReference
|
||||||
|
targetIndex = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetIndex == 0) return TextComponentSpecFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
val conversionContextParam = 0
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
insertIndex, """
|
endIndex + 1, """
|
||||||
invoke-static {v$insertRegister}, ${INTEGRATIONS_RYD_CLASS_DESCRIPTOR}->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned;
|
move-object/from16 v$dummyRegister, p$conversionContextParam
|
||||||
move-result-object v$insertRegister
|
iget-object v$dummyRegister, v$dummyRegister, ${definingClass}->${targetReference.name}:${targetReference.type}
|
||||||
|
invoke-static {v$dummyRegister, v$targetRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} ?: return TextComponentSpecFingerprint.toErrorResult()
|
||||||
} ?: return ShortsTextComponentParentFingerprint.toErrorResult()
|
} ?: return TextComponentSpecParentFingerprint.toErrorResult()
|
||||||
|
|
||||||
val createComponentResult = TextComponentSpecFingerprint.result ?: return PatchResultError("Failed to find TextComponentSpecFingerprint method.")
|
|
||||||
val createComponentMethod = createComponentResult.mutableMethod
|
|
||||||
|
|
||||||
val conversionContextParam = 5
|
|
||||||
val textRefParam = createComponentMethod.parameters.size - 2
|
|
||||||
|
|
||||||
createComponentMethod.addInstructions(
|
|
||||||
0,
|
|
||||||
"""
|
|
||||||
move-object/from16 v7, p$conversionContextParam
|
|
||||||
move-object/from16 v8, p$textRefParam
|
|
||||||
invoke-static {v7, v8}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
MainstreamVideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
MainstreamVideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
||||||
|
|
||||||
@ -108,6 +142,9 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
private companion object {
|
private companion object {
|
||||||
const val INTEGRATIONS_RYD_CLASS_DESCRIPTOR =
|
const val INTEGRATIONS_RYD_CLASS_DESCRIPTOR =
|
||||||
"$UTILS_PATH/ReturnYouTubeDislikePatch;"
|
"$UTILS_PATH/ReturnYouTubeDislikePatch;"
|
||||||
|
|
||||||
|
var targetIndex: Int = 0
|
||||||
|
private lateinit var targetReference: FieldReference
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
|
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
|
||||||
@ -119,4 +156,13 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
DISLIKE(-1),
|
DISLIKE(-1),
|
||||||
REMOVE_LIKE(0)
|
REMOVE_LIKE(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun MutableMethod.insertShorts(index: Int, register: Int) {
|
||||||
|
addInstructions(
|
||||||
|
index, """
|
||||||
|
invoke-static {v$register}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned;
|
||||||
|
move-result-object v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,10 @@ package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
|
|||||||
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
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
|
||||||
|
|
||||||
object VideoQualitySetterFingerprint : MethodFingerprint(
|
object VideoQualitySetterFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("[L", "I", "I", "Z", "I"),
|
parameters = listOf("L"),
|
||||||
opcodes = listOf(
|
strings = listOf("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT")
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.IPUT_BOOLEAN,
|
|
||||||
)
|
|
||||||
)
|
)
|
@ -0,0 +1,17 @@
|
|||||||
|
package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object VideoQualitySettingsFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object VideoQualitySettingsParentFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("[L", "I", "Z"),
|
||||||
|
strings = listOf("menu_item_video_quality")
|
||||||
|
)
|
@ -3,16 +3,9 @@ package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
|
|||||||
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
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
|
||||||
|
|
||||||
object VideoUserQualityChangeFingerprint : MethodFingerprint(
|
object VideoUserQualityChangeFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("L","L","I","J"),
|
customFingerprint = { it.name == "onItemClick" }
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.MOVE,
|
|
||||||
Opcode.MOVE_WIDE,
|
|
||||||
Opcode.INVOKE_INTERFACE_RANGE,
|
|
||||||
Opcode.RETURN_VOID
|
|
||||||
)
|
|
||||||
)
|
)
|
@ -13,9 +13,7 @@ import app.revanced.patcher.patch.PatchResultSuccess
|
|||||||
import app.revanced.patcher.patch.annotations.DependsOn
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
import app.revanced.patches.shared.annotation.YouTubeCompatibility
|
import app.revanced.patches.shared.annotation.YouTubeCompatibility
|
||||||
import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch
|
import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch
|
||||||
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoQualityReferenceFingerprint
|
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.*
|
||||||
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoQualitySetterFingerprint
|
|
||||||
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoUserQualityChangeFingerprint
|
|
||||||
import app.revanced.util.integrations.Constants.VIDEO_PATH
|
import app.revanced.util.integrations.Constants.VIDEO_PATH
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import org.jf.dexlib2.iface.reference.FieldReference
|
import org.jf.dexlib2.iface.reference.FieldReference
|
||||||
@ -26,36 +24,44 @@ import org.jf.dexlib2.iface.reference.FieldReference
|
|||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class VideoQualityBytecodePatch : BytecodePatch(
|
class VideoQualityBytecodePatch : BytecodePatch(
|
||||||
listOf(
|
listOf(
|
||||||
VideoQualitySetterFingerprint
|
VideoQualitySetterFingerprint,
|
||||||
|
VideoQualitySettingsParentFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
VideoQualitySetterFingerprint.result?.let { parentResult ->
|
VideoQualitySetterFingerprint.result?.let { parentResult ->
|
||||||
VideoQualityReferenceFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
|
VideoQualityReferenceFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
|
||||||
val instructions = result.method.implementation!!.instructions
|
val instructions = result.method.implementation!!.instructions
|
||||||
val qualityFieldReference =
|
|
||||||
|
qualityFieldReference =
|
||||||
(instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
|
(instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
|
||||||
|
|
||||||
val qIndexMethodName =
|
qIndexMethodName =
|
||||||
context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name
|
context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name
|
||||||
|
|
||||||
parentResult.mutableMethod.addInstructions(
|
|
||||||
0, """
|
|
||||||
iget-object v0, p0, ${result.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type}
|
|
||||||
const-string v1, "$qIndexMethodName"
|
|
||||||
invoke-static {p1, p2, v0, v1}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
|
|
||||||
move-result p2
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
} ?: return VideoQualityReferenceFingerprint.toErrorResult()
|
} ?: return VideoQualityReferenceFingerprint.toErrorResult()
|
||||||
|
|
||||||
VideoUserQualityChangeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstruction(
|
VideoUserQualityChangeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstruction(
|
||||||
0,
|
0,
|
||||||
"invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V"
|
"invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V"
|
||||||
) ?: return VideoUserQualityChangeFingerprint.toErrorResult()
|
) ?: return VideoUserQualityChangeFingerprint.toErrorResult()
|
||||||
|
|
||||||
} ?: return VideoQualitySetterFingerprint.toErrorResult()
|
} ?: return VideoQualitySetterFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
VideoQualitySettingsParentFingerprint.result?.let { parentResult ->
|
||||||
|
VideoQualitySettingsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.let {
|
||||||
|
relayFieldReference = (it.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
|
||||||
|
} ?: return VideoQualitySettingsFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
parentResult.mutableMethod.addInstructions(
|
||||||
|
0, """
|
||||||
|
iget-object v0, p0, ${parentResult.classDef.type}->${relayFieldReference.name}:${relayFieldReference.type}
|
||||||
|
iget-object v1, v0, ${relayFieldReference.type}->${qualityFieldReference.name}:${qualityFieldReference.type}
|
||||||
|
const-string v2, "$qIndexMethodName"
|
||||||
|
invoke-static {p1, p2, v1, v2}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
|
||||||
|
move-result p2
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} ?: return VideoQualitySettingsParentFingerprint.toErrorResult()
|
||||||
|
|
||||||
LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
|
LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
@ -63,5 +69,11 @@ class VideoQualityBytecodePatch : BytecodePatch(
|
|||||||
private companion object {
|
private companion object {
|
||||||
const val INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR =
|
const val INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR =
|
||||||
"$VIDEO_PATH/VideoQualityPatch;"
|
"$VIDEO_PATH/VideoQualityPatch;"
|
||||||
|
|
||||||
|
private lateinit var qIndexMethodName: String
|
||||||
|
|
||||||
|
private lateinit var relayFieldReference: FieldReference
|
||||||
|
private lateinit var qualityFieldReference: FieldReference
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user