mirror of
https://github.com/ovrport/app.git
synced 2026-10-26 19:19:56 -04:00
Release 1.2.2 (#28)
* Fix version detection edge case * Fix VrApi detection * Delete empty icon file * Remove leftover code * Animate icon and label on patch switching * Fix forced replace icon/label patch * Rename patch * Create Unity stub if UE4 smali is present only * Remove unused VrApi after patching * Add line breaks for appends * Add OculusXRPlugin binary patch and improve binary patching * Mark frida cleanup patch as not recommended * Change frida cleanup behavior * Filter version with existing directories * Show cover if selected * Remove VrApi library patch * Android XR metadata * Huawei VR metadata * More metadata * Uses-library for Android XR * Bump version * Rename patch
This commit is contained in:
1 parent
c50c431a7e
commit
474f7bf12a
20 files changed
+236
-82
No files matched your search
@@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "moe.crx"
|
||||
version = "1.2.1"
|
||||
version = "1.2.2"
|
||||
|
||||
dependencies {
|
||||
implementation(libs.android.tools.build)
|
||||
|
||||
@@ -6,16 +6,6 @@ import moe.crx.overport.utils.named
|
||||
import moe.crx.overport.utils.takeNodesEach
|
||||
|
||||
val PATCH_CLEAN_UP_FRIDA = Patch("patch_clean_up_frida") {
|
||||
selectLibrary("libfrda.so") {
|
||||
file.delete()
|
||||
}
|
||||
selectLibrary("libfrda.config.so") {
|
||||
file.delete()
|
||||
}
|
||||
selectLibrary("libscript.so") {
|
||||
file.delete()
|
||||
}
|
||||
|
||||
selectManifestJson {
|
||||
takeNodesEach({ named("manifest") }) {
|
||||
takeNodesEach({ named("application") }) {
|
||||
|
||||
@@ -9,8 +9,8 @@ val PATCH_COPY_OVRPLUGIN_VRAPI = Patch("patch_copy_ovrplugin_vrapi") {
|
||||
val arch = getLibraries().resolve("lib/${archDirectory.name}")
|
||||
|
||||
if (arch.exists()) {
|
||||
val hasVrApi = arch.listFiles().find { it.name.lowercase() == "libvrapi.so" } != null
|
||||
if (hasVrApi) {
|
||||
val vrApi = archDirectory.listFiles().find { it.name.lowercase() == "libvrapi.so" }
|
||||
if (vrApi != null) {
|
||||
arch.listFiles().filter { it.name == "libOVRPlugin.so" }.forEach { library ->
|
||||
library.copyTo(File(archDirectory, library.name), true)
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@ package moe.crx.overport.patches
|
||||
import moe.crx.overport.patching.Patch
|
||||
|
||||
val PATCH_FIX_UNREAL_CRASH = Patch("patch_fix_unreal_crash") {
|
||||
createSmali("com/unity3d/player/UnityPlayer") {
|
||||
if (readText().isBlank()) {
|
||||
append(".class public Lcom/unity3d/player/UnityPlayer;")
|
||||
append(".super Ljava/lang/Object;")
|
||||
append(".field public static currentActivity:Landroid/app/Activity;")
|
||||
}
|
||||
}
|
||||
|
||||
selectSmali("com/epicgames/ue4/GameActivity") {
|
||||
replace(
|
||||
"sput-object (\\w+), Lcom\\/epicgames\\/ue4\\/GameActivity;->\\w+:Lcom\\/epicgames\\/ue4\\/GameActivity;",
|
||||
"$0\nsput-object $1, Lcom/unity3d/player/UnityPlayer;->currentActivity:Landroid/app/Activity;"
|
||||
)
|
||||
|
||||
createSmali("com/unity3d/player/UnityPlayer") {
|
||||
if (readText().isBlank()) {
|
||||
appendLine(".class public Lcom/unity3d/player/UnityPlayer;")
|
||||
appendLine(".super Ljava/lang/Object;")
|
||||
appendLine(".field public static currentActivity:Landroid/app/Activity;")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ val PATCH_LAUNCHER_ENTRY = Patch("patch_launcher_entry") {
|
||||
.put(createCategory("android.intent.category.LAUNCHER"))
|
||||
.put(createCategory("com.oculus.intent.category.VR"))
|
||||
.put(createCategory("com.yvr.intent.category.VR"))
|
||||
.put(createCategory("org.khronos.openxr.intent.category.IMMERSIVE_HMD"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,15 @@ val PATCH_OCULUS_UNITY = Patch("patch_oculus_unity") {
|
||||
"(getIsOnOculusHardware\\(\\)Z.*?)return (\\w+)", "$1\nconst/4 $2, 0x1\nreturn $2"
|
||||
)
|
||||
}
|
||||
|
||||
selectLibrary("libOculusXRPlugin.so") {
|
||||
replaceHex(
|
||||
"1F 1C 00 72 ?? ?? ?? ?? E9 07 9F 1A C0 00 80 52 20 00 A0 72 ?? ?? ?? ??",
|
||||
"1F 1C 00 72 ?? ?? ?? ?? 29 00 80 52 C0 00 80 52 20 00 A0 72 ?? ?? ?? ??"
|
||||
)
|
||||
replaceHex(
|
||||
"00 28 18 BF 01 20 ?? ?? 08 70 06 20 C0 F2 01 00",
|
||||
"01 20 00 BF 00 BF ?? ?? 08 70 06 20 C0 F2 01 00"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package moe.crx.overport.patches
|
||||
|
||||
import moe.crx.overport.patching.Patch
|
||||
import moe.crx.overport.utils.nameAttribute
|
||||
import moe.crx.overport.utils.named
|
||||
import moe.crx.overport.utils.takeNodesEach
|
||||
|
||||
@@ -8,8 +9,12 @@ val PATCH_REMOVE_USES_LIBRARY = Patch("patch_remove_uses_library") {
|
||||
selectManifestJson {
|
||||
takeNodesEach({ named("manifest") }) {
|
||||
takeNodesEach({ named("application") }) {
|
||||
takeNodesEach({ named("uses-library") }) { null }
|
||||
takeNodesEach({ named("uses-native-library") }) { null }
|
||||
takeNodesEach({ named("uses-library") }) {
|
||||
if (nameAttribute() != "libopenxr.google.so") null else this
|
||||
}
|
||||
takeNodesEach({ named("uses-native-library") }) {
|
||||
if (nameAttribute() != "libopenxr.google.so") null else this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package moe.crx.overport.patches
|
||||
|
||||
import moe.crx.overport.patching.Patch
|
||||
|
||||
val PATCH_REMOVE_VRAPI = Patch("patch_remove_vrapi", false) {
|
||||
selectWorkspace {
|
||||
file.resolve("root/lib").listFiles()?.forEach { archDirectory ->
|
||||
val arch = getLibraries().resolve("lib/${archDirectory.name}")
|
||||
|
||||
if (arch.exists()) {
|
||||
val vrApi = archDirectory.listFiles().find { it.name.lowercase() == "libvrapi.so" }
|
||||
vrApi?.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,12 @@ val PATCH_REPLACE_ICON_LABEL = Patch("patch_replace_icon_label") { arguments ->
|
||||
}
|
||||
}
|
||||
|
||||
if (!iconDownloaded) {
|
||||
selectFile("root/res/drawable/custom_icon_ovrp.png") {
|
||||
delete()
|
||||
}
|
||||
}
|
||||
|
||||
if (iconDownloaded) {
|
||||
selectPackageBlock {
|
||||
getOrCreate("", "drawable", "custom_icon_ovrp").apply {
|
||||
|
||||
@@ -22,10 +22,100 @@ fun createMetadata(name: String, value: String): JSONObject {
|
||||
)
|
||||
}
|
||||
|
||||
fun createMetadataFloat(name: String, value: Float): JSONObject {
|
||||
return JSONObject().put("node_type", "element").put("name", "meta-data").put(
|
||||
"attributes", JSONArray().put(
|
||||
JSONObject().put("name", "name").put("id", 16842755)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "STRING").put("data", name)
|
||||
).put(
|
||||
JSONObject().put("name", "value").put("id", 16842788)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "FLOAT").put("data", value)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createUsesFeature(name: String, required: Boolean): JSONObject {
|
||||
return JSONObject().put("node_type", "element").put("name", "uses-feature").put(
|
||||
"attributes", JSONArray().put(
|
||||
JSONObject().put("name", "name").put("id", 16842755)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "STRING").put("data", name)
|
||||
).put(
|
||||
JSONObject().put("name", "required").put("id", 16843406)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "BOOLEAN").put("data", required)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createUsesLibrary(name: String, required: Boolean): JSONObject {
|
||||
return JSONObject().put("node_type", "element").put("name", "uses-library").put(
|
||||
"attributes", JSONArray().put(
|
||||
JSONObject().put("name", "name").put("id", 16842755)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "STRING").put("data", name)
|
||||
).put(
|
||||
JSONObject().put("name", "required").put("id", 16843406)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "BOOLEAN").put("data", required)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createUsesPermission(name: String): JSONObject {
|
||||
return JSONObject().put("node_type", "element").put("name", "uses-permission").put(
|
||||
"attributes", JSONArray().put(
|
||||
JSONObject().put("name", "name").put("id", 16842755)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "STRING").put("data", name)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createProperty(key: String, value: String): JSONObject {
|
||||
return JSONObject().put("node_type", "element").put("name", "property").put(
|
||||
"attributes", JSONArray().put(
|
||||
JSONObject().put("name", "name").put("id", 16842755)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "STRING").put("data", key)
|
||||
).put(
|
||||
JSONObject().put("name", "value").put("id", 16842788)
|
||||
.put("uri", "http://schemas.android.com/apk/res/android").put("prefix", "android")
|
||||
.put("value_type", "STRING").put("data", value)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val PATCH_VR_METADATA = Patch("patch_vr_metadata") {
|
||||
selectManifestJson {
|
||||
takeNodesEach({ named("manifest") }) {
|
||||
takeNodesEach({ named("application") }) {
|
||||
takeNodesEach({ named("activity") }) {
|
||||
takeNodes {
|
||||
this?.put(
|
||||
createProperty(
|
||||
"android.window.PROPERTY_XR_ACTIVITY_START_MODE",
|
||||
"XR_ACTIVITY_START_MODE_FULL_SPACE_UNMANAGED"
|
||||
)
|
||||
)?.put(
|
||||
createProperty(
|
||||
"android.window.PROPERTY_XR_BOUNDARY_TYPE_RECOMMENDED",
|
||||
"XR_BOUNDARY_TYPE_LARGE"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
takeNodes {
|
||||
this?.put(createUsesFeature("android.software.xr.api.openxr", true))
|
||||
this?.put(createUsesFeature("android.software.xr.api.spatial", true))
|
||||
this?.put(createUsesLibrary("libopenxr.google.so", false))
|
||||
this?.put(createUsesFeature("android.software.xr.input.controller", false))
|
||||
?.put(createUsesPermission("org.khronos.openxr.permission.OPENXR"))
|
||||
?.put(createUsesPermission("org.khronos.openxr.permission.OPENXR_SYSTEM"))
|
||||
?.put(createUsesPermission("com.huawei.android.permission.VR"))
|
||||
}
|
||||
takeNodesEach({ named("meta-data") }) {
|
||||
if (nameAttribute() == "com.oculus.supportedDevices") null else this
|
||||
}
|
||||
@@ -33,6 +123,14 @@ val PATCH_VR_METADATA = Patch("patch_vr_metadata") {
|
||||
this?.put(createMetadata("pvr.app.type", "vr"))
|
||||
?.put(createMetadata("com.yvr.intent.category.VR", "vr_only"))
|
||||
?.put(createMetadata("com.oculus.supportedDevices", "all"))
|
||||
?.put(createMetadata("com.huawei.android.vr.application.mode", "vr_only"))
|
||||
?.put(createMetadata("com.huawei.android.vr.application.type", "game"))
|
||||
?.put(createMetadata("com.huawei.vr.application.freeDegree", "3dof|6dof"))
|
||||
?.put(createMetadataFloat("android.max_aspect", 2.1f))
|
||||
?.put(createMetadata("minWaveSDKVersion", "1"))
|
||||
?.put(createMetadata("com.htc.vr.content.NumController", "1,2"))
|
||||
?.put(createMetadata("com.htc.vr.content.NumDoFController", "3,6DoF"))
|
||||
?.put(createMetadata("com.htc.vr.content.NumDoFHmd", "3,6DoF"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ class FileTransformer(val file: File) {
|
||||
file.writeText(Regex(input, RegexOption.DOT_MATCHES_ALL).replace(file.readText(), output))
|
||||
}
|
||||
|
||||
fun delete(): Boolean {
|
||||
return file.deleteRecursively()
|
||||
}
|
||||
|
||||
fun readText(): String {
|
||||
return file.readText()
|
||||
}
|
||||
@@ -16,6 +20,11 @@ class FileTransformer(val file: File) {
|
||||
file.appendText(line)
|
||||
}
|
||||
|
||||
fun appendLine(line: String) {
|
||||
append(line)
|
||||
append("\n")
|
||||
}
|
||||
|
||||
fun readJson(): JSONObject? {
|
||||
return runCatching { JSONObject(file.readText()) }.getOrNull()
|
||||
}
|
||||
@@ -35,6 +44,10 @@ class FileTransformer(val file: File) {
|
||||
fun replaceHex(input: String, output: String) {
|
||||
val bytes = file.readBytes()
|
||||
val inputBytes = input.split(' ')
|
||||
val outputBytes = output.split(' ')
|
||||
var startIndex = -1
|
||||
|
||||
check(inputBytes.size == outputBytes.size)
|
||||
|
||||
for (i in 0..<bytes.size - inputBytes.size + 1) {
|
||||
var matches = true
|
||||
@@ -52,12 +65,22 @@ class FileTransformer(val file: File) {
|
||||
}
|
||||
|
||||
if (matches) {
|
||||
val replaced = bytes.slice(0..<i) +
|
||||
output.split(' ').map { it.toUByte(16).toByte() } +
|
||||
bytes.slice(i + inputBytes.size..<bytes.size)
|
||||
file.writeBytes(replaced.toByteArray())
|
||||
return
|
||||
startIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
if (startIndex == -1) {
|
||||
return
|
||||
}
|
||||
|
||||
for (i in 0..<inputBytes.size) {
|
||||
if (outputBytes[i] != "??") {
|
||||
bytes[i + startIndex] = outputBytes[i].toUByte(16).toByte()
|
||||
} else if (inputBytes[i] != "??") {
|
||||
bytes[i + startIndex] = inputBytes[i].toUByte(16).toByte()
|
||||
}
|
||||
}
|
||||
|
||||
file.writeBytes(bytes)
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ object PatchStore {
|
||||
register(PATCH_META_XR_AUDIO)
|
||||
register(PATCH_MARK_AS_DEBUGGABLE)
|
||||
register(PATCH_MARK_ALLOW_BACKUP)
|
||||
register(PATCH_REMOVE_VRAPI)
|
||||
register(PATCH_REMOVE_UNREAL_FORCE_QUIT)
|
||||
register(PATCH_FORCE_PASSTHROUGH)
|
||||
register(PATCH_DISABLE_SPACE_WARP)
|
||||
|
||||
@@ -10,7 +10,7 @@ class VersionManager(val workingDirectory: File) {
|
||||
|
||||
companion object {
|
||||
val json = Json { ignoreUnknownKeys = true }
|
||||
const val VERSION = "1.2.1"
|
||||
const val VERSION = "1.2.2"
|
||||
|
||||
private fun isVersionLower(left: String, right: String): Boolean {
|
||||
val (lY, lM, lD) = left.substringBeforeLast('-').split('.').map { it.toInt() }
|
||||
@@ -80,6 +80,7 @@ class VersionManager(val workingDirectory: File) {
|
||||
if (installedEntry != null) {
|
||||
val librariesDir = workingDirectory.resolve("libraries/${installedEntry.version}")
|
||||
if (librariesDir.isDirectory) {
|
||||
appendInstalled(installedEntry)
|
||||
return installedEntry.version
|
||||
}
|
||||
}
|
||||
@@ -132,7 +133,7 @@ class VersionManager(val workingDirectory: File) {
|
||||
o2.version
|
||||
)
|
||||
) 1 else -1
|
||||
})
|
||||
}).filter { workingDirectory.resolve("libraries/${it.version}").isDirectory }
|
||||
}
|
||||
|
||||
return listOf()
|
||||
|
||||
Reference in new issue
Block a user