diff --git a/cache/src/main/java/net/runelite/cache/IndexType.java b/cache/src/main/java/net/runelite/cache/IndexType.java index 551865fa0d..866304efd5 100644 --- a/cache/src/main/java/net/runelite/cache/IndexType.java +++ b/cache/src/main/java/net/runelite/cache/IndexType.java @@ -27,8 +27,8 @@ package net.runelite.cache; public enum IndexType { - // names from https://github.com/im-frizzy/OpenRS/blob/master/source/net/openrs/cache/type/CacheIndex.java - SKINS(1), + FRAMES(0), + FRAMEMAPS(1), CONFIGS(2), INTERFACES(3), SOUNDEFFECTS(4), diff --git a/cache/src/main/java/net/runelite/cache/definitions/FrameDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/FrameDefinition.java new file mode 100644 index 0000000000..2b68a02e87 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/FrameDefinition.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +public class FrameDefinition +{ + public FramemapDefinition framemap; + public int[] translator_x; + public int[] translator_y; + public int[] translator_z; + public int field1310 = -1; + public int[] indexFrameIds; + public boolean field1315; +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/FramemapDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/FramemapDefinition.java new file mode 100644 index 0000000000..05e06635d8 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/FramemapDefinition.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +public class FramemapDefinition +{ + public int id; + public int[] field1456; + public int[][] field1457; + public int length; +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/FrameLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/FrameLoader.java new file mode 100644 index 0000000000..bfef12669b --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/FrameLoader.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.FrameDefinition; +import net.runelite.cache.definitions.FramemapDefinition; +import net.runelite.cache.io.InputStream; + +public class FrameLoader +{ + public FrameDefinition load(FramemapDefinition framemap, byte[] b) + { + FrameDefinition def = new FrameDefinition(); + InputStream in = new InputStream(b); + InputStream data = new InputStream(b); + + def.framemap = framemap; + + int framemapArchiveIndex = in.readUnsignedShort(); + int length = in.readUnsignedByte(); + + data.skip(3 + length); // framemapArchiveIndex + length + data + + int[] indexFrameIds = new int[500]; + int[] scratchTranslatorX = new int[500]; + int[] scratchTranslatorY = new int[500]; + int[] scratchTranslatorZ = new int[500]; + + int lastI = -1; + int index = 0; + for (int i = 0; i < length; ++i) + { + int var9 = in.readUnsignedByte(); + + if (var9 <= 0) + { + continue; + } + + if (def.framemap.field1456[i] != 0) + { + for (int var10 = i - 1; var10 > lastI; --var10) + { + if (def.framemap.field1456[var10] == 0) + { + indexFrameIds[index] = var10; + scratchTranslatorX[index] = 0; + scratchTranslatorY[index] = 0; + scratchTranslatorZ[index] = 0; + ++index; + break; + } + } + } + + indexFrameIds[index] = i; + short var11 = 0; + if (def.framemap.field1456[i] == 3) + { + var11 = 128; + } + + if ((var9 & 1) != 0) + { + scratchTranslatorX[index] = data.readShortSmart(); + } + else + { + scratchTranslatorX[index] = var11; + } + + if ((var9 & 2) != 0) + { + scratchTranslatorY[index] = data.readShortSmart(); + } + else + { + scratchTranslatorY[index] = var11; + } + + if ((var9 & 4) != 0) + { + scratchTranslatorZ[index] = data.readShortSmart(); + } + else + { + scratchTranslatorZ[index] = var11; + } + + lastI = i; + ++index; + if (def.framemap.field1456[i] == 5) + { + def.field1315 = true; + } + } + + if (data.getOffset() != b.length) + { + throw new RuntimeException(); + } + + def.field1310 = index; + def.indexFrameIds = new int[index]; + def.translator_x = new int[index]; + def.translator_y = new int[index]; + def.translator_z = new int[index]; + + for (int i = 0; i < index; ++i) + { + def.indexFrameIds[i] = indexFrameIds[i]; + def.translator_x[i] = scratchTranslatorX[i]; + def.translator_y[i] = scratchTranslatorY[i]; + def.translator_z[i] = scratchTranslatorZ[i]; + } + + return def; + } +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/FramemapLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/FramemapLoader.java new file mode 100644 index 0000000000..ba2038c44f --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/FramemapLoader.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.FramemapDefinition; +import net.runelite.cache.io.InputStream; + +public class FramemapLoader +{ + public FramemapDefinition load(int id, byte[] b) + { + FramemapDefinition def = new FramemapDefinition(); + InputStream in = new InputStream(b); + + def.id = id; + + def.length = in.readUnsignedByte(); + def.field1456 = new int[def.length]; + def.field1457 = new int[def.length][]; + + for (int i = 0; i < def.length; ++i) + { + def.field1456[i] = in.readUnsignedByte(); + } + + for (int i = 0; i < def.length; ++i) + { + def.field1457[i] = new int[in.readUnsignedByte()]; + } + + for (int i = 0; i < def.length; ++i) + { + for (int j = 0; j < def.field1457[i].length; ++j) + { + def.field1457[i][j] = in.readUnsignedByte(); + } + } + + return def; + } +} diff --git a/cache/src/test/java/net/runelite/cache/FrameDumper.java b/cache/src/test/java/net/runelite/cache/FrameDumper.java new file mode 100644 index 0000000000..8b8781154c --- /dev/null +++ b/cache/src/test/java/net/runelite/cache/FrameDumper.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import com.google.common.io.Files; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import net.runelite.cache.definitions.FrameDefinition; +import net.runelite.cache.definitions.FramemapDefinition; +import net.runelite.cache.definitions.loaders.FrameLoader; +import net.runelite.cache.definitions.loaders.FramemapLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.File; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Store; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FrameDumper +{ + private static final Logger logger = LoggerFactory.getLogger(FrameDumper.class); + + @Rule + public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); + + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + //@Test + public void extract() throws IOException + { + java.io.File base = StoreLocation.LOCATION, + outDir = folder.newFolder(); + + int count = 0; + + try (Store store = new Store(base)) + { + store.load(); + + Index frameIndex = store.getIndex(IndexType.FRAMES); + Index framemapIndex = store.getIndex(IndexType.FRAMEMAPS); + + for (Archive archive : frameIndex.getArchives()) + { + List frames = new ArrayList<>(); + + for (File file : archive.getFiles()) + { + byte[] contents = file.getContents(); + + int framemapArchiveId = (contents[0] & 0xff) << 8 | contents[1] & 0xff; + + Archive framemapArchive = framemapIndex.getArchives().get(framemapArchiveId); + assert framemapArchive.getFiles().size() == 1; + File framemapFile = framemapArchive.getFiles().get(0); + + FramemapLoader fmloader = new FramemapLoader(); + FramemapDefinition framemap = fmloader.load(framemapFile.getFileId(), framemapFile.getContents()); + + FrameLoader frameLoader = new FrameLoader(); + FrameDefinition frame = frameLoader.load(framemap, contents); + + frames.add(frame); + } + + Files.write(gson.toJson(frames), new java.io.File(outDir, archive.getArchiveId() + ".json"), Charset.defaultCharset()); + ++count; + } + } + + logger.info("Dumped {} frames to {}", count, outDir); + } +} diff --git a/cache/src/test/java/net/runelite/cache/FramemapDumper.java b/cache/src/test/java/net/runelite/cache/FramemapDumper.java new file mode 100644 index 0000000000..e2cfb1a882 --- /dev/null +++ b/cache/src/test/java/net/runelite/cache/FramemapDumper.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import com.google.common.io.Files; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.IOException; +import java.nio.charset.Charset; +import net.runelite.cache.definitions.FramemapDefinition; +import net.runelite.cache.definitions.loaders.FramemapLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.File; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Store; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FramemapDumper +{ + private static final Logger logger = LoggerFactory.getLogger(FramemapDumper.class); + + @Rule + public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); + + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + @Test + public void extract() throws IOException + { + java.io.File base = StoreLocation.LOCATION, + outDir = folder.newFolder(); + + int count = 0; + + try (Store store = new Store(base)) + { + store.load(); + + Index index = store.getIndex(IndexType.FRAMEMAPS); + for (Archive archive : index.getArchives()) + { + assert archive.getFiles().size() == 1; + File file = archive.getFiles().get(0); + + FramemapLoader loader = new FramemapLoader(); + FramemapDefinition framemap = loader.load(file.getFileId(), file.getContents()); + + Files.write(gson.toJson(framemap), new java.io.File(outDir, file.getFileId() + ".json"), Charset.defaultCharset()); + ++count; + } + } + + logger.info("Dumped {} framemaps to {}", count, outDir); + } +}