Add arch/OS enums to avoid hard-coding the platform detection patch

Signed-off-by: Graham <gpe@openrs2.org>
bzip2
Graham 4 years ago
parent 80957aeca0
commit 3091409f82
  1. 10
      patcher/src/main/kotlin/org/openrs2/patcher/Architecture.kt
  2. 17
      patcher/src/main/kotlin/org/openrs2/patcher/OperatingSystem.kt
  3. 70
      patcher/src/main/kotlin/org/openrs2/patcher/Resource.kt
  4. 132
      patcher/src/main/kotlin/org/openrs2/patcher/transform/PlatformDetectionTransformer.kt

@ -0,0 +1,10 @@
package org.openrs2.patcher
public enum class Architecture(
public val needles: List<String>
) {
I386(listOf("i386", "x86")),
AMD64(listOf("amd64", "x86_64"));
public val id: String = name.toLowerCase()
}

@ -0,0 +1,17 @@
package org.openrs2.patcher
import org.openrs2.patcher.Architecture.AMD64
import org.openrs2.patcher.Architecture.I386
public enum class OperatingSystem(
public val needle: String,
public val architectures: List<Architecture>,
public val glLibraries: List<String>
) {
// AMD64 must be before I386 as x86 is a substring of x86_64
WINDOWS("win", listOf(AMD64, I386), listOf("jaggl.dll")),
MAC("mac", listOf(AMD64, I386), listOf("libjaggl.dylib")),
LINUX("linux", listOf(AMD64, I386), listOf("libjaggl.so", "libjaggl_dri.so"));
public val id: String = name.toLowerCase()
}

@ -85,43 +85,43 @@ public class Resource(
return compress(source, destination, uncompressed)
}
public fun compressGlNatives(): List<List<Resource>> = listOf(
// Windows i386
listOf(
compressNative("jaggl_0_0.lib", "jaggl.dll", "windows-i386/jaggl.dll")
),
// Windows amd64
listOf(
compressNative("jaggl_1_0.lib", "jaggl.dll", "windows-amd64/jaggl.dll")
),
// macOS i386
listOf(
compressNative("jaggl_2_0.lib", "libjaggl.dylib", "mac-i386/libjaggl.dylib")
),
// macOS amd64
listOf(
compressNative("jaggl_3_0.lib", "libjaggl.dylib", "mac-amd64/libjaggl.dylib")
),
// Linux i386
listOf(
compressNative("jaggl_4_0.lib", "libjaggl.so", "linux-i386/libjaggl.so"),
compressNative("jaggl_4_1.lib", "libjaggl_dri.so", "linux-i386/libjaggl_dri.so")
),
// Linux amd64
listOf(
compressNative("jaggl_5_0.lib", "libjaggl.so", "linux-amd64/libjaggl.so"),
compressNative("jaggl_5_1.lib", "libjaggl_dri.so", "linux-amd64/libjaggl_dri.so")
)
public fun compressGlNatives(): List<List<Resource>> {
val platforms = mutableListOf<List<Resource>>()
var i = 0
for (os in OperatingSystem.values()) {
for (arch in os.architectures) {
val resources = mutableListOf<Resource>()
for ((j, library) in os.glLibraries.withIndex()) {
resources += compressNative(
source = "jaggl_${i}_$j.lib",
destination = library,
resource = "${os.id}-${arch.id}/$library"
)
}
platforms += resources
i++
}
}
public fun compressMiscNatives(): List<Resource> = listOf(
compressNative("jagmisc_0.lib", "jagmisc.dll", "windows-i386/jagmisc.dll"),
compressNative("jagmisc_1.lib", "jagmisc.dll", "windows-amd64/jagmisc.dll")
return platforms
}
public fun compressMiscNatives(): List<Resource> {
val os = OperatingSystem.WINDOWS
val resources = mutableListOf<Resource>()
for ((i, arch) in os.architectures.withIndex()) {
resources += compressNative(
source = "jagmisc_$i.lib",
destination = "jagmisc.dll",
resource = "${os.id}-${arch.id}/jagmisc.dll"
)
}
return resources
}
}
}

@ -5,7 +5,6 @@ import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.InsnList
import org.objectweb.asm.tree.InsnNode
import org.objectweb.asm.tree.JumpInsnNode
import org.objectweb.asm.tree.LabelNode
import org.objectweb.asm.tree.LdcInsnNode
@ -16,9 +15,9 @@ import org.openrs2.asm.InsnMatcher
import org.openrs2.asm.MemberRef
import org.openrs2.asm.classpath.ClassPath
import org.openrs2.asm.classpath.Library
import org.openrs2.asm.intConstant
import org.openrs2.asm.toAbstractInsnNode
import org.openrs2.asm.transform.Transformer
import org.openrs2.patcher.OperatingSystem
import javax.inject.Singleton
@Singleton
@ -32,7 +31,7 @@ public class PlatformDetectionTransformer : Transformer() {
}
override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean {
val match = GL_PLATFORM_DETECTION_MATCHER.match(method).singleOrNull()
var match = GL_PLATFORM_DETECTION_MATCHER.match(method).singleOrNull()
if (match != null) {
// find os.name, os.arch and platform ID variables
val nameStore = match[3] as VarInsnNode
@ -50,14 +49,13 @@ public class PlatformDetectionTransformer : Transformer() {
// generate our own platform detection code
val list = InsnList()
val end = LabelNode()
var platform = 0
for ((index, os) in OS_NAMES.withIndex()) {
val next = LabelNode()
val amd64 = LabelNode()
val i386 = LabelNode()
for (os in OperatingSystem.values()) {
val nextOs = LabelNode()
list.add(VarInsnNode(Opcodes.ALOAD, nameVar))
list.add(LdcInsnNode(os))
list.add(LdcInsnNode(os.needle))
list.add(
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
@ -66,22 +64,16 @@ public class PlatformDetectionTransformer : Transformer() {
STARTS_WITH.desc
)
)
list.add(JumpInsnNode(Opcodes.IFEQ, next))
list.add(JumpInsnNode(Opcodes.IFEQ, nextOs))
list.add(VarInsnNode(Opcodes.ALOAD, archVar))
list.add(LdcInsnNode("amd64"))
list.add(
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
STARTS_WITH.owner,
STARTS_WITH.name,
STARTS_WITH.desc
)
)
list.add(JumpInsnNode(Opcodes.IFNE, amd64))
for ((i, arch) in os.architectures.withIndex()) {
val matchingArch = LabelNode()
val nextArch = LabelNode()
if (i != os.architectures.size - 1) {
for ((j, needle) in arch.needles.withIndex()) {
list.add(VarInsnNode(Opcodes.ALOAD, archVar))
list.add(LdcInsnNode("x86_64"))
list.add(LdcInsnNode(needle))
list.add(
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
@ -90,19 +82,24 @@ public class PlatformDetectionTransformer : Transformer() {
STARTS_WITH.desc
)
)
list.add(JumpInsnNode(Opcodes.IFEQ, i386))
list.add(amd64)
list.add((index * 2 + 1).toAbstractInsnNode())
list.add(VarInsnNode(Opcodes.ISTORE, platformVar))
list.add(JumpInsnNode(Opcodes.GOTO, end))
if (j != arch.needles.size - 1) {
list.add(JumpInsnNode(Opcodes.IFNE, matchingArch))
} else {
list.add(JumpInsnNode(Opcodes.IFEQ, nextArch))
}
}
}
list.add(i386)
list.add((index * 2).toAbstractInsnNode())
list.add(matchingArch)
list.add((platform++).toAbstractInsnNode())
list.add(VarInsnNode(Opcodes.ISTORE, platformVar))
list.add(JumpInsnNode(Opcodes.GOTO, end))
list.add(next)
list.add(nextArch)
}
list.add(nextOs)
}
list.add(unknownOs)
@ -119,28 +116,62 @@ public class PlatformDetectionTransformer : Transformer() {
}
// adjust jagmisc platform IDs to account for the removal of MSJVM support
val miscMatch = MISC_PLATFORM_DETECTION_MATCHER.match(method).filter {
val const1 = it[0].intConstant
if (const1 != 0 && const1 != 2) {
return@filter false
match = MISC_PLATFORM_DETECTION_MATCHER.match(method).singleOrNull()
if (match != null) {
// find os.arch and platform ID variables
val archStore = match[12] as VarInsnNode
val archVar = archStore.`var`
val platformStore = match[match.size - 5] as VarInsnNode
val platformVar = platformStore.`var`
// generate our own platform detection code
val list = InsnList()
val end = LabelNode()
val os = OperatingSystem.WINDOWS
for ((i, arch) in os.architectures.withIndex()) {
val matchingArch = LabelNode()
val nextArch = LabelNode()
if (i != os.architectures.size - 1) {
for ((j, needle) in arch.needles.withIndex()) {
list.add(VarInsnNode(Opcodes.ALOAD, archVar))
list.add(LdcInsnNode(needle))
list.add(
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
STARTS_WITH.owner,
STARTS_WITH.name,
STARTS_WITH.desc
)
)
if (j != arch.needles.size - 1) {
list.add(JumpInsnNode(Opcodes.IFNE, matchingArch))
} else {
list.add(JumpInsnNode(Opcodes.IFEQ, nextArch))
}
}
}
val const2 = it[it.size - 2].intConstant
if (const2 != 0 && const2 != 2) {
return@filter false
list.add(matchingArch)
list.add(i.toAbstractInsnNode())
list.add(VarInsnNode(Opcodes.ISTORE, platformVar))
list.add(JumpInsnNode(Opcodes.GOTO, end))
list.add(nextArch)
}
if (const1 == const2) {
return@filter false
list.add(end)
// replace existing platform detection code with our own
for (i in (13 until match.size - 4)) {
method.instructions.remove(match[i])
}
val store1 = it[1] as VarInsnNode
val store2 = it[it.size - 1] as VarInsnNode
return@filter store1.`var` == store2.`var`
}.singleOrNull()
if (miscMatch != null) {
val iconst = miscMatch.single { it.intConstant == 2 }
method.instructions.set(iconst, InsnNode(Opcodes.ICONST_1))
method.instructions.insert(match[12], list)
miscBlocks++
}
@ -161,9 +192,14 @@ public class PlatformDetectionTransformer : Transformer() {
ICONST ISTORE ILOAD GETSTATIC ILOAD AALOAD ARRAYLENGTH
"""
)
private val MISC_PLATFORM_DETECTION_MATCHER =
InsnMatcher.compile("ICONST ISTORE ((GETSTATIC | ILOAD) IFEQ | GOTO) ICONST ISTORE")
private val OS_NAMES = listOf("win", "mac", "linux")
private val MISC_PLATFORM_DETECTION_MATCHER = InsnMatcher.compile(
"""
LDC INVOKESTATIC INVOKEVIRTUAL ASTORE ALOAD LDC INVOKEVIRTUAL IFNE GOTO
LDC INVOKESTATIC INVOKEVIRTUAL ASTORE
.*
ICONST ISTORE ALOAD ALOAD LDC INVOKEVIRTUAL
"""
)
private val STARTS_WITH = MemberRef("java/lang/String", "startsWith", "(Ljava/lang/String;)Z")
private fun findUnknownOs(match: List<AbstractInsnNode>): InsnList {

Loading…
Cancel
Save