From 3293454c170c5f06ace09cf3b7f24e0e3874e529 Mon Sep 17 00:00:00 2001 From: Graham Date: Tue, 6 Apr 2021 21:46:29 +0100 Subject: [PATCH] Add support for importing keys in binary format Signed-off-by: Graham --- .../openrs2/archive/key/BinaryKeyReader.kt | 65 +++++++++++++++++++ .../org/openrs2/archive/key/KeyImporter.kt | 5 +- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 archive/src/main/kotlin/org/openrs2/archive/key/BinaryKeyReader.kt diff --git a/archive/src/main/kotlin/org/openrs2/archive/key/BinaryKeyReader.kt b/archive/src/main/kotlin/org/openrs2/archive/key/BinaryKeyReader.kt new file mode 100644 index 00000000..2ea8ce63 --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/key/BinaryKeyReader.kt @@ -0,0 +1,65 @@ +package org.openrs2.archive.key + +import io.netty.buffer.ByteBuf +import io.netty.buffer.Unpooled +import org.openrs2.buffer.use +import org.openrs2.crypto.XteaKey +import java.io.InputStream + +public object BinaryKeyReader : KeyReader { + override fun read(input: InputStream): Sequence { + Unpooled.wrappedBuffer(input.readBytes()).use { buf -> + val len = buf.readableBytes() + + if (len == (128 * 128 * 16)) { + val keys = read(buf, 0) + require(XteaKey.ZERO in keys) + return keys.asSequence() + } + + val maybeShort = (len % 18) == 0 + val maybeInt = (len % 20) == 0 + + if (maybeShort && !maybeInt) { + val keys = read(buf, 2) + require(XteaKey.ZERO in keys) + return keys.asSequence() + } else if (!maybeShort && maybeInt) { + val keys = read(buf, 4).asSequence() + require(XteaKey.ZERO in keys) + return keys.asSequence() + } else if (maybeShort && maybeInt) { + val shortKeys = read(buf, 2) + val intKeys = read(buf, 4) + + return if (XteaKey.ZERO in shortKeys && XteaKey.ZERO !in intKeys) { + shortKeys.asSequence() + } else if (XteaKey.ZERO !in shortKeys && XteaKey.ZERO in intKeys) { + intKeys.asSequence() + } else { + throw IllegalArgumentException("Failed to determine if map square IDs are 2 or 4 bytes") + } + } else { + throw IllegalArgumentException( + "Binary XTEA files must be exactly 256 KiB or a multiple of 18 or 20 bytes long" + ) + } + } + } + + private fun read(buf: ByteBuf, mapSquareLen: Int): Set { + val keys = mutableSetOf() + + while (buf.isReadable) { + buf.skipBytes(mapSquareLen) + + val k0 = buf.readInt() + val k1 = buf.readInt() + val k2 = buf.readInt() + val k3 = buf.readInt() + keys += XteaKey(k0, k1, k2, k3) + } + + return keys + } +} diff --git a/archive/src/main/kotlin/org/openrs2/archive/key/KeyImporter.kt b/archive/src/main/kotlin/org/openrs2/archive/key/KeyImporter.kt index 04dbd1dc..96a75cf1 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/key/KeyImporter.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/key/KeyImporter.kt @@ -24,9 +24,12 @@ public class KeyImporter @Inject constructor( val name = file.fileName.toString() val reader = when { + name.endsWith(".bin") -> BinaryKeyReader + name.endsWith(".dat") -> BinaryKeyReader name.endsWith(".hex") -> HexKeyReader - name.endsWith(".txt") -> TextKeyReader name.endsWith(".json") -> jsonKeyReader + name.endsWith(".mcx") -> BinaryKeyReader + name.endsWith(".txt") -> TextKeyReader else -> continue }