cache: add assembler and split scriptdumper test into disassembler/disassemblertest
This commit is contained in:
23
cache/pom.xml
vendored
23
cache/pom.xml
vendored
@@ -36,6 +36,10 @@
|
|||||||
<artifactId>cache</artifactId>
|
<artifactId>cache</artifactId>
|
||||||
<name>Cache</name>
|
<name>Cache</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<antlr4.version>4.6</antlr4.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.runelite</groupId>
|
<groupId>net.runelite</groupId>
|
||||||
@@ -78,6 +82,11 @@
|
|||||||
<artifactId>netty-all</artifactId>
|
<artifactId>netty-all</artifactId>
|
||||||
<version>4.1.0.Final</version>
|
<version>4.1.0.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr4-runtime</artifactId>
|
||||||
|
<version>${antlr4.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
@@ -92,7 +101,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>2.16</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<enableAssertions>true</enableAssertions>
|
<enableAssertions>true</enableAssertions>
|
||||||
<argLine>-Xmx2048m</argLine>
|
<argLine>-Xmx2048m</argLine>
|
||||||
@@ -115,6 +123,19 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr4-maven-plugin</artifactId>
|
||||||
|
<version>${antlr4.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>process-resources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr4</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
46
cache/src/main/antlr4/net/runelite/cache/script/assembler/rs2asm.g4
vendored
Normal file
46
cache/src/main/antlr4/net/runelite/cache/script/assembler/rs2asm.g4
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
grammar rs2asm;
|
||||||
|
|
||||||
|
prog: (line NEWLINE)+ ;
|
||||||
|
line: instruction | label ;
|
||||||
|
instruction: instruction_name instruction_operand ;
|
||||||
|
label: 'LABEL' INT ':' ;
|
||||||
|
|
||||||
|
instruction_name: name_string | name_opcode ;
|
||||||
|
name_string: INSTRUCTION ;
|
||||||
|
name_opcode: INT ;
|
||||||
|
|
||||||
|
instruction_operand: operand_int | operand_qstring | operand_label | ;
|
||||||
|
operand_int: INT ;
|
||||||
|
operand_qstring: QSTRING ;
|
||||||
|
operand_label: 'LABEL' INT ;
|
||||||
|
|
||||||
|
NEWLINE: '\n'+ ;
|
||||||
|
INT: '-'? [0-9]+ ;
|
||||||
|
QSTRING: '"' (~('"' | '\\' | '\r' | '\n') | '\\' ('"' | '\\'))* '"' ;
|
||||||
|
INSTRUCTION: [a-z0-9_]+ ;
|
||||||
|
|
||||||
|
WS: (' ' | '\t')+ -> channel(HIDDEN) ;
|
||||||
@@ -30,6 +30,7 @@ import java.util.Map;
|
|||||||
public class Instructions
|
public class Instructions
|
||||||
{
|
{
|
||||||
private static final Map<Integer, Instruction> instructions = new HashMap<>();
|
private static final Map<Integer, Instruction> instructions = new HashMap<>();
|
||||||
|
private static final Map<String, Instruction> instructionsByName = new HashMap<>();
|
||||||
|
|
||||||
public static void init()
|
public static void init()
|
||||||
{
|
{
|
||||||
@@ -443,6 +444,12 @@ public class Instructions
|
|||||||
|
|
||||||
assert instructions.containsKey(opcode) == false;
|
assert instructions.containsKey(opcode) == false;
|
||||||
instructions.put(opcode, i);
|
instructions.put(opcode, i);
|
||||||
|
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
assert instructionsByName.containsKey(name) == false;
|
||||||
|
instructionsByName.put(name, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void add(int opcode, int ipops, int ipushes)
|
private static void add(int opcode, int ipops, int ipushes)
|
||||||
@@ -464,4 +471,9 @@ public class Instructions
|
|||||||
{
|
{
|
||||||
return instructions.get(opcode);
|
return instructions.get(opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Instruction find(String name)
|
||||||
|
{
|
||||||
|
return instructionsByName.get(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
74
cache/src/main/java/net/runelite/cache/script/assembler/Assembler.java
vendored
Normal file
74
cache/src/main/java/net/runelite/cache/script/assembler/Assembler.java
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.script.assembler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import net.runelite.cache.definitions.ScriptDefinition;
|
||||||
|
import net.runelite.cache.script.Instructions;
|
||||||
|
import net.runelite.cache.script.assembler.rs2asmParser.ProgContext;
|
||||||
|
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||||
|
|
||||||
|
public class Assembler
|
||||||
|
{
|
||||||
|
public ScriptDefinition assemble(InputStream in) throws IOException
|
||||||
|
{
|
||||||
|
Instructions.init();
|
||||||
|
|
||||||
|
// Get our lexer
|
||||||
|
rs2asmLexer lexer = new rs2asmLexer(new ANTLRInputStream(in));
|
||||||
|
|
||||||
|
LexerErrorListener errorListener = new LexerErrorListener();
|
||||||
|
lexer.addErrorListener(errorListener);
|
||||||
|
|
||||||
|
// Get a list of matched tokens
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
|
||||||
|
// Pass the tokens to the parser
|
||||||
|
rs2asmParser parser = new rs2asmParser(tokens);
|
||||||
|
|
||||||
|
// Specify our entry point
|
||||||
|
ProgContext progContext = parser.prog();
|
||||||
|
|
||||||
|
if (errorListener.getErrors() > 0)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("syntax error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk it and attach our listener
|
||||||
|
ParseTreeWalker walker = new ParseTreeWalker();
|
||||||
|
|
||||||
|
// walk through first and resolve labels
|
||||||
|
LabelVisitor labelVisitor = new LabelVisitor();
|
||||||
|
walker.walk(labelVisitor, progContext);
|
||||||
|
|
||||||
|
ScriptWriter listener = new ScriptWriter(labelVisitor);
|
||||||
|
walker.walk(listener, progContext);
|
||||||
|
|
||||||
|
return listener.buildScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
60
cache/src/main/java/net/runelite/cache/script/assembler/LabelVisitor.java
vendored
Normal file
60
cache/src/main/java/net/runelite/cache/script/assembler/LabelVisitor.java
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.script.assembler;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class LabelVisitor extends rs2asmBaseListener
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(LabelVisitor.class);
|
||||||
|
|
||||||
|
private int pos;
|
||||||
|
private final Map<String, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitInstruction(rs2asmParser.InstructionContext ctx)
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterLabel(rs2asmParser.LabelContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
text = text.substring(0, text.length() - 1); // remove trailing :
|
||||||
|
|
||||||
|
logger.debug("Label {} is on instruction {}", text, pos);
|
||||||
|
|
||||||
|
map.put(text, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getInstructionForLabel(String label)
|
||||||
|
{
|
||||||
|
return map.get(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
cache/src/main/java/net/runelite/cache/script/assembler/LexerErrorListener.java
vendored
Normal file
46
cache/src/main/java/net/runelite/cache/script/assembler/LexerErrorListener.java
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.script.assembler;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.BaseErrorListener;
|
||||||
|
import org.antlr.v4.runtime.RecognitionException;
|
||||||
|
import org.antlr.v4.runtime.Recognizer;
|
||||||
|
|
||||||
|
public class LexerErrorListener extends BaseErrorListener
|
||||||
|
{
|
||||||
|
private int errors;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
|
||||||
|
{
|
||||||
|
++errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getErrors()
|
||||||
|
{
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
132
cache/src/main/java/net/runelite/cache/script/assembler/ScriptWriter.java
vendored
Normal file
132
cache/src/main/java/net/runelite/cache/script/assembler/ScriptWriter.java
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.script.assembler;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import net.runelite.cache.definitions.ScriptDefinition;
|
||||||
|
import net.runelite.cache.script.Instruction;
|
||||||
|
import net.runelite.cache.script.Instructions;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ScriptWriter extends rs2asmBaseListener
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ScriptWriter.class);
|
||||||
|
|
||||||
|
private final LabelVisitor labelVisitor;
|
||||||
|
|
||||||
|
private int pos;
|
||||||
|
private List<Integer> opcodes = new ArrayList<>();
|
||||||
|
private List<Integer> iops = new ArrayList<>();
|
||||||
|
private List<String> sops = new ArrayList<>();
|
||||||
|
|
||||||
|
public ScriptWriter(LabelVisitor labelVisitor)
|
||||||
|
{
|
||||||
|
this.labelVisitor = labelVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitInstruction(rs2asmParser.InstructionContext ctx)
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterName_string(rs2asmParser.Name_stringContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
Instruction i = Instructions.find(text);
|
||||||
|
if (i == null)
|
||||||
|
{
|
||||||
|
logger.warn("Unknown instruction {}", text);
|
||||||
|
throw new RuntimeException("Unknown instruction " + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
int opcode = i.getOpcode();
|
||||||
|
addOpcode(opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterName_opcode(rs2asmParser.Name_opcodeContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
int opcode = Integer.parseInt(text);
|
||||||
|
addOpcode(opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addOpcode(int opcode)
|
||||||
|
{
|
||||||
|
assert opcodes.size() == pos;
|
||||||
|
assert iops.size() == pos;
|
||||||
|
assert sops.size() == pos;
|
||||||
|
|
||||||
|
opcodes.add(opcode);
|
||||||
|
iops.add(null);
|
||||||
|
sops.add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterOperand_int(rs2asmParser.Operand_intContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
int value = Integer.parseInt(text);
|
||||||
|
iops.set(pos, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterOperand_qstring(rs2asmParser.Operand_qstringContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
text = text.substring(1, text.length() - 1);
|
||||||
|
sops.set(pos, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterOperand_label(rs2asmParser.Operand_labelContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
Integer instruction = labelVisitor.getInstructionForLabel(text);
|
||||||
|
if (instruction == null)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("reference to unknown label " + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
int target = instruction - pos - 1; // -1 to go to the instruction prior
|
||||||
|
iops.set(pos, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptDefinition buildScript()
|
||||||
|
{
|
||||||
|
ScriptDefinition script = new ScriptDefinition();
|
||||||
|
script.setInstructions(opcodes.stream().mapToInt(Integer::valueOf).toArray());
|
||||||
|
script.setIntOperands(iops.stream()
|
||||||
|
.map(i -> i == null ? 0 : i)
|
||||||
|
.mapToInt(Integer::valueOf)
|
||||||
|
.toArray());
|
||||||
|
script.setStringOperands(sops.toArray(new String[0]));
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
}
|
||||||
147
cache/src/main/java/net/runelite/cache/script/disassembler/Disassembler.java
vendored
Normal file
147
cache/src/main/java/net/runelite/cache/script/disassembler/Disassembler.java
vendored
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.script.disassembler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import net.runelite.cache.definitions.ScriptDefinition;
|
||||||
|
import net.runelite.cache.script.Instruction;
|
||||||
|
import net.runelite.cache.script.Instructions;
|
||||||
|
import net.runelite.cache.script.Opcodes;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Disassembler
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Disassembler.class);
|
||||||
|
|
||||||
|
private boolean isJump(int opcode)
|
||||||
|
{
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case Opcodes.JUMP:
|
||||||
|
case Opcodes.IF_ICMPEQ:
|
||||||
|
case Opcodes.IF_ICMPGE:
|
||||||
|
case Opcodes.IF_ICMPGT:
|
||||||
|
case Opcodes.IF_ICMPLE:
|
||||||
|
case Opcodes.IF_ICMPLT:
|
||||||
|
case Opcodes.IF_ICMPNE:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean[] needLabel(ScriptDefinition script)
|
||||||
|
{
|
||||||
|
int[] instructions = script.getInstructions();
|
||||||
|
int[] iop = script.getIntOperands();
|
||||||
|
boolean[] jumped = new boolean[instructions.length];
|
||||||
|
|
||||||
|
for (int i = 0; i < instructions.length; ++i)
|
||||||
|
{
|
||||||
|
int opcode = instructions[i];
|
||||||
|
|
||||||
|
if (!isJump(opcode))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// + 1 because the jumps go to the instructions prior to the
|
||||||
|
// one you really want, because the pc is incremented on the
|
||||||
|
// next loop
|
||||||
|
int to = i + iop[i] + 1;
|
||||||
|
assert to >= 0 && to < instructions.length;
|
||||||
|
|
||||||
|
jumped[to] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return jumped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String disassemble(ScriptDefinition script) throws IOException
|
||||||
|
{
|
||||||
|
StringBuilder writer = new StringBuilder();
|
||||||
|
|
||||||
|
int[] instructions = script.getInstructions();
|
||||||
|
int[] iops = script.getIntOperands();
|
||||||
|
String[] sops = script.getStringOperands();
|
||||||
|
|
||||||
|
assert iops.length == instructions.length;
|
||||||
|
assert sops.length == instructions.length;
|
||||||
|
|
||||||
|
boolean[] jumps = needLabel(script);
|
||||||
|
|
||||||
|
for (int i = 0; i < instructions.length; ++i)
|
||||||
|
{
|
||||||
|
int opcode = instructions[i];
|
||||||
|
int iop = iops[i];
|
||||||
|
String sop = sops[i];
|
||||||
|
|
||||||
|
Instruction ins = Instructions.find(opcode);
|
||||||
|
if (ins == null)
|
||||||
|
{
|
||||||
|
logger.warn("Unknown instruction {} in script {}", opcode, script.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jumps[i])
|
||||||
|
{
|
||||||
|
// something jumps here
|
||||||
|
writer.append("LABEL").append(i).append(":\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
String name;
|
||||||
|
if (ins != null && ins.getName() != null)
|
||||||
|
{
|
||||||
|
name = ins.getName();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = String.format("%03d", opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.append(String.format(" %-22s", name));
|
||||||
|
|
||||||
|
if (iop != 0 || opcode == Opcodes.LOAD_INT)
|
||||||
|
{
|
||||||
|
if (isJump(opcode))
|
||||||
|
{
|
||||||
|
writer.append(" LABEL").append(i + iop + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.append(" ").append(iop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sop != null)
|
||||||
|
{
|
||||||
|
writer.append(" \"").append(sop).append("\"");
|
||||||
|
}
|
||||||
|
writer.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
73
cache/src/test/java/net/runelite/cache/script/assembler/AssemblerTest.java
vendored
Normal file
73
cache/src/test/java/net/runelite/cache/script/assembler/AssemblerTest.java
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* 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.script.assembler;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import net.runelite.cache.definitions.ScriptDefinition;
|
||||||
|
import net.runelite.cache.script.disassembler.Disassembler;
|
||||||
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.slf4j.impl.SimpleLogger;
|
||||||
|
|
||||||
|
public class AssemblerTest
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AssemblerTest.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before()
|
||||||
|
{
|
||||||
|
System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAssemble() throws Exception
|
||||||
|
{
|
||||||
|
InputStream in = AssemblerTest.class.getResourceAsStream("395.rs2asm");
|
||||||
|
Assert.assertNotNull(in);
|
||||||
|
|
||||||
|
Assembler assembler = new Assembler();
|
||||||
|
ScriptDefinition script = assembler.assemble(in);
|
||||||
|
|
||||||
|
// compare with disassembler
|
||||||
|
Disassembler disassembler = new Disassembler();
|
||||||
|
String out = disassembler.disassemble(script);
|
||||||
|
|
||||||
|
in = AssemblerTest.class.getResourceAsStream("395.rs2asm");
|
||||||
|
Assert.assertNotNull(in);
|
||||||
|
|
||||||
|
String original = new String(IOUtils.toByteArray(in));
|
||||||
|
|
||||||
|
logger.debug(original);
|
||||||
|
logger.debug("-----------------------");
|
||||||
|
logger.debug(out);
|
||||||
|
|
||||||
|
Assert.assertEquals(original, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,29 +22,28 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.cache;
|
package net.runelite.cache.script.disassembler;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import com.google.common.io.Files;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import net.runelite.cache.IndexType;
|
||||||
|
import net.runelite.cache.StoreLocation;
|
||||||
import net.runelite.cache.definitions.ScriptDefinition;
|
import net.runelite.cache.definitions.ScriptDefinition;
|
||||||
import net.runelite.cache.definitions.loaders.ScriptLoader;
|
import net.runelite.cache.definitions.loaders.ScriptLoader;
|
||||||
import net.runelite.cache.fs.Archive;
|
import net.runelite.cache.fs.Archive;
|
||||||
import net.runelite.cache.fs.File;
|
import net.runelite.cache.fs.File;
|
||||||
import net.runelite.cache.fs.Index;
|
import net.runelite.cache.fs.Index;
|
||||||
import net.runelite.cache.fs.Store;
|
import net.runelite.cache.fs.Store;
|
||||||
import net.runelite.cache.script.Instruction;
|
|
||||||
import net.runelite.cache.script.Instructions;
|
import net.runelite.cache.script.Instructions;
|
||||||
import net.runelite.cache.script.Opcodes;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class ScriptDumperTest
|
public class DisassemblerTest
|
||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ScriptDumperTest.class);
|
private static final Logger logger = LoggerFactory.getLogger(DisassemblerTest.class);
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public TemporaryFolder folder = StoreLocation.getTemporaryFolder();
|
public TemporaryFolder folder = StoreLocation.getTemporaryFolder();
|
||||||
@@ -74,7 +73,11 @@ public class ScriptDumperTest
|
|||||||
ScriptDefinition script = loader.load(file.getFileId(), contents);
|
ScriptDefinition script = loader.load(file.getFileId(), contents);
|
||||||
|
|
||||||
java.io.File outFile = new java.io.File(outDir, archive.getArchiveId() + ".rs2asm");
|
java.io.File outFile = new java.io.File(outDir, archive.getArchiveId() + ".rs2asm");
|
||||||
writeScript(outFile, script);
|
|
||||||
|
Disassembler disassembler = new Disassembler();
|
||||||
|
String out = disassembler.disassemble(script);
|
||||||
|
|
||||||
|
Files.write(out.getBytes(), outFile);
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
@@ -82,112 +85,4 @@ public class ScriptDumperTest
|
|||||||
|
|
||||||
logger.info("Dumped {} scripts to {}", count, outDir);
|
logger.info("Dumped {} scripts to {}", count, outDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isJump(int opcode)
|
|
||||||
{
|
|
||||||
switch (opcode)
|
|
||||||
{
|
|
||||||
case Opcodes.JUMP:
|
|
||||||
case Opcodes.IF_ICMPEQ:
|
|
||||||
case Opcodes.IF_ICMPGE:
|
|
||||||
case Opcodes.IF_ICMPGT:
|
|
||||||
case Opcodes.IF_ICMPLE:
|
|
||||||
case Opcodes.IF_ICMPLT:
|
|
||||||
case Opcodes.IF_ICMPNE:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean[] needLabel(ScriptDefinition script)
|
|
||||||
{
|
|
||||||
int[] instructions = script.getInstructions();
|
|
||||||
int[] iop = script.getIntOperands();
|
|
||||||
boolean[] jumped = new boolean[instructions.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < instructions.length; ++i)
|
|
||||||
{
|
|
||||||
int opcode = instructions[i];
|
|
||||||
|
|
||||||
if (!isJump(opcode))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// + 1 because the jumps go to the instructions prior to the
|
|
||||||
// one you really want, because the pc is incremented on the
|
|
||||||
// next loop
|
|
||||||
int to = i + iop[i] + 1;
|
|
||||||
assert to >= 0 && to < instructions.length;
|
|
||||||
|
|
||||||
jumped[to] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jumped;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeScript(java.io.File file, ScriptDefinition script) throws IOException
|
|
||||||
{
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file)))
|
|
||||||
{
|
|
||||||
int[] instructions = script.getInstructions();
|
|
||||||
int[] iops = script.getIntOperands();
|
|
||||||
String[] sops = script.getStringOperands();
|
|
||||||
|
|
||||||
assert iops.length == instructions.length;
|
|
||||||
assert sops.length == instructions.length;
|
|
||||||
|
|
||||||
boolean[] jumps = needLabel(script);
|
|
||||||
|
|
||||||
for (int i = 0; i < instructions.length; ++i)
|
|
||||||
{
|
|
||||||
int opcode = instructions[i];
|
|
||||||
int iop = iops[i];
|
|
||||||
String sop = sops[i];
|
|
||||||
|
|
||||||
Instruction ins = Instructions.find(opcode);
|
|
||||||
if (ins == null)
|
|
||||||
{
|
|
||||||
logger.warn("Unknown instruction {} in script {}", opcode, script.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
String name;
|
|
||||||
if (ins != null && ins.getName() != null)
|
|
||||||
{
|
|
||||||
name = ins.getName();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
name = String.format("%03d", opcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jumps[i])
|
|
||||||
{
|
|
||||||
// something jumps here
|
|
||||||
writer.write("LABEL" + i + ":\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.write(String.format(" %-22s", name));
|
|
||||||
|
|
||||||
if (iop != 0 || opcode == Opcodes.LOAD_INT)
|
|
||||||
{
|
|
||||||
if (isJump(opcode))
|
|
||||||
{
|
|
||||||
writer.write(" LABEL" + (i + iop + 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writer.write(" " + iop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sop != null)
|
|
||||||
{
|
|
||||||
writer.write(" \"" + sop + "\"");
|
|
||||||
}
|
|
||||||
writer.write("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
99
cache/src/test/resources/net/runelite/cache/script/assembler/395.rs2asm
vendored
Normal file
99
cache/src/test/resources/net/runelite/cache/script/assembler/395.rs2asm
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
033
|
||||||
|
get_boostedskilllevels
|
||||||
|
int_to_string
|
||||||
|
1112
|
||||||
|
033
|
||||||
|
get_realskilllevels
|
||||||
|
034 3
|
||||||
|
033 3
|
||||||
|
int_to_string
|
||||||
|
1112 1
|
||||||
|
033
|
||||||
|
get_skillexperiences
|
||||||
|
034 4
|
||||||
|
load_string ","
|
||||||
|
036 1
|
||||||
|
035
|
||||||
|
load_string " XP:"
|
||||||
|
037 2
|
||||||
|
036 2
|
||||||
|
033 4
|
||||||
|
035 1
|
||||||
|
040 46
|
||||||
|
036 3
|
||||||
|
load_int 0
|
||||||
|
034 5
|
||||||
|
025 4181
|
||||||
|
load_int 0
|
||||||
|
if_icmpeq LABEL29
|
||||||
|
jump LABEL60
|
||||||
|
LABEL29:
|
||||||
|
033 3
|
||||||
|
load_int 99
|
||||||
|
if_icmplt LABEL33
|
||||||
|
jump LABEL59
|
||||||
|
LABEL33:
|
||||||
|
load_int 105
|
||||||
|
load_int 105
|
||||||
|
load_int 256
|
||||||
|
033 3
|
||||||
|
load_int 1
|
||||||
|
iadd
|
||||||
|
3408
|
||||||
|
034 5
|
||||||
|
035 2
|
||||||
|
load_string "|Next level at:|Remaining XP:"
|
||||||
|
concat_string
|
||||||
|
036 2
|
||||||
|
035 3
|
||||||
|
load_string "|"
|
||||||
|
033 5
|
||||||
|
035 1
|
||||||
|
040 46
|
||||||
|
load_string "|"
|
||||||
|
033 5
|
||||||
|
033 4
|
||||||
|
isub
|
||||||
|
035 1
|
||||||
|
040 46
|
||||||
|
037 4
|
||||||
|
concat_string
|
||||||
|
036 3
|
||||||
|
LABEL59:
|
||||||
|
jump LABEL78
|
||||||
|
LABEL60:
|
||||||
|
035 2
|
||||||
|
load_string "|Next level at:"
|
||||||
|
concat_string
|
||||||
|
036 2
|
||||||
|
035 3
|
||||||
|
load_string "|"
|
||||||
|
load_int 105
|
||||||
|
load_int 105
|
||||||
|
load_int 256
|
||||||
|
033 3
|
||||||
|
load_int 1
|
||||||
|
iadd
|
||||||
|
3408
|
||||||
|
035 1
|
||||||
|
040 46
|
||||||
|
037 2
|
||||||
|
concat_string
|
||||||
|
036 3
|
||||||
|
LABEL78:
|
||||||
|
load_int 992
|
||||||
|
load_int -2147483645
|
||||||
|
load_int -1
|
||||||
|
033 2
|
||||||
|
035 2
|
||||||
|
035 3
|
||||||
|
load_int 495
|
||||||
|
load_int 25
|
||||||
|
load_int 5
|
||||||
|
idiv
|
||||||
|
load_string "IiIssfi"
|
||||||
|
033 1
|
||||||
|
2412
|
||||||
|
load_int 0
|
||||||
|
043 2
|
||||||
|
return
|
||||||
Reference in New Issue
Block a user