diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt index 4562f93b..c01f935a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt @@ -13,11 +13,11 @@ import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.shared.settings.preference.impl.InputType import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.TextPreference +import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility import app.revanced.patches.youtube.misc.videobuffer.fingerprints.MaxBufferFingerprint import app.revanced.patches.youtube.misc.videobuffer.fingerprints.PlaybackBufferFingerprint @@ -78,60 +78,101 @@ class CustomVideoBufferPatch : BytecodePatch( StringResource("revanced_custom_video_buffer_summary", "Custom settings for video buffer") ) ) + BufferType.values().forEach { type -> + type.hook(context) + } - execMaxBuffer() - execPlaybackBuffer() - execReBuffer() return PatchResultSuccess() } - private fun execMaxBuffer() { - val (method, result) = MaxBufferFingerprint.unwrap(true, -1) - val (index, register) = result + /** + * The type of buffer. + * + * @param patchInfo The corresponding information to patch the buffer type. + * @param preparation Optional preparation before patching. + */ + private enum class BufferType( + private val patchInfo: PatchInfo, + private val preparation: (BytecodeContext.() -> Unit)? = null, + ) { - method.addInstructions( - index + 1, """ - invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getMaxBuffer()I - move-result v$register - """ - ) - } + PLAYBACK(PatchInfo(PlaybackBufferFingerprint, "getPlaybackBuffer")), + RE(PatchInfo(ReBufferFingerprint, "getReBuffer")), + MAX( + PatchInfo( + MaxBufferFingerprint, + "getMaxBuffer", + PatchInfo.UnwrapInfo(true, -1) + ) + ); - private fun execPlaybackBuffer() { - val (method, result) = PlaybackBufferFingerprint.unwrap() - val (index, register) = result + /** + * Information about a patch. + * + * @param fingerprint The corresponding [MethodFingerprint] for the patch. + * @param integrationsMethodName The corresponding name of the hooking method. + * @param unwrapInfo Optional information on how to treat the [MethodFingerprint]. + */ + private class PatchInfo( + val fingerprint: MethodFingerprint, + val integrationsMethodName: String, + val unwrapInfo: UnwrapInfo? = null + ) { + /** + * Information on how to treat a [MethodFingerprint]. + * + * @param forEndIndex Whether to retrieve information from the [MethodFingerprint] + * from the end or start index of its pattern scan result. + * @param offset An additional offset to [forEndIndex]. + */ + class UnwrapInfo(val forEndIndex: Boolean = false, val offset: Int = 0) + } - method.addInstructions( - index + 1, """ - invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getPlaybackBuffer()I - move-result v$register - """ - ) - } + fun hook(context: BytecodeContext) { + /** + * The resulting instruction info for unwrapping [MethodFingerprint]. + * + * @param index The index of the instruction. + * @param register The register of the instruction. + */ + data class InstructionResult(val index: Int, val register: Int) - private fun execReBuffer() { - val (method, result) = ReBufferFingerprint.unwrap() - val (index, register) = result + /*** + * The result of unwrapping [MethodFingerprint]. + * + * @param method The method which was retrieved from the [MethodFingerprint]. + * @param instructionResult The resulting instruction info for unwrapping [MethodFingerprint]. + */ + data class UnwrapResult(val method: MutableMethod, val instructionResult: InstructionResult) - method.addInstructions( - index + 1, """ - invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getReBuffer()I - move-result v$register - """ - ) - } + fun MethodFingerprint.unwrap(unwrapInfo: PatchInfo.UnwrapInfo? = null): UnwrapResult { + val result = this.result!! + val method = result.mutableMethod + val scanResult = result.scanResult.patternScanResult!! + val index = ( + if (unwrapInfo?.forEndIndex == true) + scanResult.endIndex + else + scanResult.startIndex + ) + (unwrapInfo?.offset ?: 0) - private fun MethodFingerprint.unwrap( - forEndIndex: Boolean = false, - offset: Int = 0 - ): Pair> { - val result = this.result!! - val method = result.mutableMethod - val scanResult = result.scanResult.patternScanResult!! - val index = (if (forEndIndex) scanResult.endIndex else scanResult.startIndex) + offset + val register = (method.instruction(index) as OneRegisterInstruction).registerA - val register = (method.instruction(index) as OneRegisterInstruction).registerA + return UnwrapResult(method, InstructionResult(index, register)) + } - return method to (index to register) + preparation?.invoke(context) + + val (method, result) = patchInfo.fingerprint.unwrap(patchInfo.unwrapInfo) + val (index, register) = result + + method.addInstructions( + index + 1, + """ + invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->${patchInfo.integrationsMethodName}()I + move-result v$register + """ + ) + } } }