cache: add switch instruction
This commit is contained in:
@@ -24,14 +24,9 @@
|
|||||||
*/
|
*/
|
||||||
grammar rs2asm;
|
grammar rs2asm;
|
||||||
|
|
||||||
prog: (attr NEWLINE)* (line NEWLINE)+ ;
|
prog: (line NEWLINE)+ ;
|
||||||
|
|
||||||
attr: '.attr ' attr_idx ' ' attr_key ' ' attr_value ;
|
line: instruction | label | switch_lookup ;
|
||||||
attr_idx: INT ;
|
|
||||||
attr_key: INT ;
|
|
||||||
attr_value: INT ;
|
|
||||||
|
|
||||||
line: instruction | label ;
|
|
||||||
instruction: instruction_name instruction_operand ;
|
instruction: instruction_name instruction_operand ;
|
||||||
label: 'LABEL' INT ':' ;
|
label: 'LABEL' INT ':' ;
|
||||||
|
|
||||||
@@ -44,6 +39,10 @@ operand_int: INT ;
|
|||||||
operand_qstring: QSTRING ;
|
operand_qstring: QSTRING ;
|
||||||
operand_label: 'LABEL' INT ;
|
operand_label: 'LABEL' INT ;
|
||||||
|
|
||||||
|
switch_lookup: switch_key ':' switch_value ;
|
||||||
|
switch_key: INT ;
|
||||||
|
switch_value: 'LABEL' INT ;
|
||||||
|
|
||||||
NEWLINE: '\n'+ ;
|
NEWLINE: '\n'+ ;
|
||||||
INT: '-'? [0-9]+ ;
|
INT: '-'? [0-9]+ ;
|
||||||
QSTRING: '"' (~('"' | '\\' | '\r' | '\n') | '\\' ('"' | '\\'))* '"' ;
|
QSTRING: '"' (~('"' | '\\' | '\r' | '\n') | '\\' ('"' | '\\'))* '"' ;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class ScriptDefinition
|
|||||||
private int localStringCount;
|
private int localStringCount;
|
||||||
private int stringStackCount;
|
private int stringStackCount;
|
||||||
private int localIntCount;
|
private int localIntCount;
|
||||||
private Map<Integer, Integer>[] attributes;
|
private Map<Integer, Integer>[] switches;
|
||||||
|
|
||||||
public int getId()
|
public int getId()
|
||||||
{
|
{
|
||||||
@@ -118,13 +118,13 @@ public class ScriptDefinition
|
|||||||
this.localIntCount = localIntCount;
|
this.localIntCount = localIntCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, Integer>[] getAttributes()
|
public Map<Integer, Integer>[] getSwitches()
|
||||||
{
|
{
|
||||||
return attributes;
|
return switches;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttributes(Map<Integer, Integer>[] attributes)
|
public void setSwitches(Map<Integer, Integer>[] switches)
|
||||||
{
|
{
|
||||||
this.attributes = attributes;
|
this.switches = switches;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,23 +48,23 @@ public class ScriptLoader
|
|||||||
int intStackCount = in.readUnsignedShort();
|
int intStackCount = in.readUnsignedShort();
|
||||||
int stringStackCount = in.readUnsignedShort();
|
int stringStackCount = in.readUnsignedShort();
|
||||||
|
|
||||||
int attributeCount = in.readUnsignedByte();
|
int numSwitches = in.readUnsignedByte();
|
||||||
if (attributeCount > 0)
|
if (numSwitches > 0)
|
||||||
{
|
{
|
||||||
Map<Integer, Integer>[] attributes = new Map[attributeCount];
|
Map<Integer, Integer>[] switches = new Map[numSwitches];
|
||||||
def.setAttributes(attributes);
|
def.setSwitches(switches);
|
||||||
|
|
||||||
for (int i = 0; i < attributeCount; ++i)
|
for (int i = 0; i < numSwitches; ++i)
|
||||||
{
|
{
|
||||||
attributes[i] = new HashMap<>();
|
switches[i] = new HashMap<>();
|
||||||
|
|
||||||
int count = in.readUnsignedShort();
|
int count = in.readUnsignedShort();
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
{
|
{
|
||||||
int key = in.readInt();
|
int key = in.readInt(); // int from stack is compared to this
|
||||||
int value = in.readInt();
|
int pcOffset = in.readInt(); // pc jumps by this
|
||||||
|
|
||||||
attributes[i].put(key, value);
|
switches[i].put(key, pcOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public class Instructions
|
|||||||
add(46, 2, 0);
|
add(46, 2, 0);
|
||||||
add(47, 0, 0, 0, 1);
|
add(47, 0, 0, 0, 1);
|
||||||
add(48, 0, 0, 1, 0);
|
add(48, 0, 0, 1, 0);
|
||||||
|
add(Opcodes.SWITCH, "switch", 1, 0);
|
||||||
add(100, 3, 0);
|
add(100, 3, 0);
|
||||||
add(101, 0, 0);
|
add(101, 0, 0);
|
||||||
add(102, 1, 0);
|
add(102, 1, 0);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class Opcodes
|
|||||||
public static final int POP_INT = 38;
|
public static final int POP_INT = 38;
|
||||||
public static final int POP_STRING = 39;
|
public static final int POP_STRING = 39;
|
||||||
//public static final int INVOKE = 40;
|
//public static final int INVOKE = 40;
|
||||||
|
public static final int SWITCH = 60;
|
||||||
public static final int WIDGET_PUT_HIDDEN = 1003;
|
public static final int WIDGET_PUT_HIDDEN = 1003;
|
||||||
public static final int WIDGET_PUT_SCROLL = 1100;
|
public static final int WIDGET_PUT_SCROLL = 1100;
|
||||||
public static final int WIDGET_PUT_TEXTCOLOR = 1101;
|
public static final int WIDGET_PUT_TEXTCOLOR = 1101;
|
||||||
|
|||||||
@@ -24,31 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.cache.script.assembler;
|
package net.runelite.cache.script.assembler;
|
||||||
|
|
||||||
public class Attribute
|
public class LookupCase
|
||||||
{
|
{
|
||||||
private int idx;
|
|
||||||
private int key;
|
|
||||||
private int value;
|
private int value;
|
||||||
|
private int offset;
|
||||||
public int getIdx()
|
|
||||||
{
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIdx(int idx)
|
|
||||||
{
|
|
||||||
this.idx = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKey()
|
|
||||||
{
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(int key)
|
|
||||||
{
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValue()
|
public int getValue()
|
||||||
{
|
{
|
||||||
@@ -59,4 +38,14 @@ public class Attribute
|
|||||||
{
|
{
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getOffset()
|
||||||
|
{
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffset(int offset)
|
||||||
|
{
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
38
cache/src/main/java/net/runelite/cache/script/assembler/LookupSwitch.java
vendored
Normal file
38
cache/src/main/java/net/runelite/cache/script/assembler/LookupSwitch.java
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public class LookupSwitch
|
||||||
|
{
|
||||||
|
private final List<LookupCase> cases = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<LookupCase> getCases()
|
||||||
|
{
|
||||||
|
return cases;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import net.runelite.cache.definitions.ScriptDefinition;
|
import net.runelite.cache.definitions.ScriptDefinition;
|
||||||
import net.runelite.cache.script.Instruction;
|
import net.runelite.cache.script.Instruction;
|
||||||
import net.runelite.cache.script.Instructions;
|
import net.runelite.cache.script.Instructions;
|
||||||
@@ -44,45 +45,13 @@ public class ScriptWriter extends rs2asmBaseListener
|
|||||||
private List<Integer> opcodes = new ArrayList<>();
|
private List<Integer> opcodes = new ArrayList<>();
|
||||||
private List<Integer> iops = new ArrayList<>();
|
private List<Integer> iops = new ArrayList<>();
|
||||||
private List<String> sops = new ArrayList<>();
|
private List<String> sops = new ArrayList<>();
|
||||||
private List<Attribute> attrs = new ArrayList<>();
|
private List<LookupSwitch> switches = new ArrayList<>();
|
||||||
|
|
||||||
public ScriptWriter(LabelVisitor labelVisitor)
|
public ScriptWriter(LabelVisitor labelVisitor)
|
||||||
{
|
{
|
||||||
this.labelVisitor = labelVisitor;
|
this.labelVisitor = labelVisitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAttr_idx(rs2asmParser.Attr_idxContext ctx)
|
|
||||||
{
|
|
||||||
String text = ctx.getText();
|
|
||||||
int idx = Integer.parseInt(text);
|
|
||||||
|
|
||||||
Attribute attr = new Attribute();
|
|
||||||
attr.setIdx(idx);
|
|
||||||
|
|
||||||
attrs.add(attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAttr_key(rs2asmParser.Attr_keyContext ctx)
|
|
||||||
{
|
|
||||||
String text = ctx.getText();
|
|
||||||
int key = Integer.parseInt(text);
|
|
||||||
|
|
||||||
Attribute attr = attrs.get(attrs.size() - 1);
|
|
||||||
attr.setKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exitAttr_value(rs2asmParser.Attr_valueContext ctx)
|
|
||||||
{
|
|
||||||
String text = ctx.getText();
|
|
||||||
int value = Integer.parseInt(text);
|
|
||||||
|
|
||||||
Attribute attr = attrs.get(attrs.size() - 1);
|
|
||||||
attr.setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exitInstruction(rs2asmParser.InstructionContext ctx)
|
public void exitInstruction(rs2asmParser.InstructionContext ctx)
|
||||||
{
|
{
|
||||||
@@ -117,10 +86,12 @@ public class ScriptWriter extends rs2asmBaseListener
|
|||||||
assert opcodes.size() == pos;
|
assert opcodes.size() == pos;
|
||||||
assert iops.size() == pos;
|
assert iops.size() == pos;
|
||||||
assert sops.size() == pos;
|
assert sops.size() == pos;
|
||||||
|
assert switches.size() == pos;
|
||||||
|
|
||||||
opcodes.add(opcode);
|
opcodes.add(opcode);
|
||||||
iops.add(null);
|
iops.add(null);
|
||||||
sops.add(null);
|
sops.add(null);
|
||||||
|
switches.add(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -153,6 +124,54 @@ public class ScriptWriter extends rs2asmBaseListener
|
|||||||
iops.set(pos, target);
|
iops.set(pos, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterSwitch_lookup(rs2asmParser.Switch_lookupContext ctx)
|
||||||
|
{
|
||||||
|
if (switches.get(pos - 1) != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LookupSwitch ls = new LookupSwitch();
|
||||||
|
switches.set(pos - 1, ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitSwitch_key(rs2asmParser.Switch_keyContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
int key = Integer.parseInt(text);
|
||||||
|
|
||||||
|
LookupSwitch ls = switches.get(pos - 1);
|
||||||
|
assert ls != null;
|
||||||
|
|
||||||
|
LookupCase scase = new LookupCase();
|
||||||
|
scase.setValue(key);
|
||||||
|
|
||||||
|
ls.getCases().add(scase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitSwitch_value(rs2asmParser.Switch_valueContext ctx)
|
||||||
|
{
|
||||||
|
String text = ctx.getText();
|
||||||
|
Integer instruction = labelVisitor.getInstructionForLabel(text);
|
||||||
|
if (instruction == null)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("reference to unknown label " + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
int target = instruction // target instruction index
|
||||||
|
- (pos - 1) // pos is already at the instruction after the switch, so - 1
|
||||||
|
- 1; // to go to the instruction prior to target
|
||||||
|
|
||||||
|
LookupSwitch ls = switches.get(pos - 1);
|
||||||
|
assert ls != null;
|
||||||
|
|
||||||
|
LookupCase scase = ls.getCases().get(ls.getCases().size() - 1);
|
||||||
|
scase.setOffset(target);
|
||||||
|
}
|
||||||
|
|
||||||
public ScriptDefinition buildScript()
|
public ScriptDefinition buildScript()
|
||||||
{
|
{
|
||||||
ScriptDefinition script = new ScriptDefinition();
|
ScriptDefinition script = new ScriptDefinition();
|
||||||
@@ -162,28 +181,34 @@ public class ScriptWriter extends rs2asmBaseListener
|
|||||||
.mapToInt(Integer::valueOf)
|
.mapToInt(Integer::valueOf)
|
||||||
.toArray());
|
.toArray());
|
||||||
script.setStringOperands(sops.toArray(new String[0]));
|
script.setStringOperands(sops.toArray(new String[0]));
|
||||||
script.setAttributes(buildAttributes());
|
script.setSwitches(buildSwitches());
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Integer, Integer>[] buildAttributes()
|
private Map<Integer, Integer>[] buildSwitches()
|
||||||
{
|
{
|
||||||
if (attrs == null || attrs.isEmpty())
|
int count = (int) switches.stream().filter(Objects::nonNull).count();
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Integer, Integer>[] maps = new Map[attrs.stream().map(attr -> attr.getIdx()).max(Integer::compare).get() + 1];
|
int index = 0;
|
||||||
for (Attribute attr : attrs)
|
Map<Integer, Integer>[] maps = new Map[count];
|
||||||
|
for (LookupSwitch lswitch : switches)
|
||||||
{
|
{
|
||||||
Map<Integer, Integer> map = maps[attr.getIdx()];
|
if (lswitch == null)
|
||||||
if (map == null)
|
|
||||||
{
|
{
|
||||||
map = new HashMap<>();
|
continue;
|
||||||
maps[attr.getIdx()] = map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
map.put(attr.getKey(), attr.getValue());
|
Map<Integer, Integer> map = maps[index++] = new HashMap<>();
|
||||||
|
|
||||||
|
for (LookupCase scase : lswitch.getCases())
|
||||||
|
{
|
||||||
|
map.put(scase.getValue(), scase.getOffset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return maps;
|
return maps;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,12 +58,29 @@ public class Disassembler
|
|||||||
private boolean[] needLabel(ScriptDefinition script)
|
private boolean[] needLabel(ScriptDefinition script)
|
||||||
{
|
{
|
||||||
int[] instructions = script.getInstructions();
|
int[] instructions = script.getInstructions();
|
||||||
int[] iop = script.getIntOperands();
|
int[] iops = script.getIntOperands();
|
||||||
|
Map<Integer, Integer>[] switches = script.getSwitches();
|
||||||
|
|
||||||
boolean[] jumped = new boolean[instructions.length];
|
boolean[] jumped = new boolean[instructions.length];
|
||||||
|
|
||||||
for (int i = 0; i < instructions.length; ++i)
|
for (int i = 0; i < instructions.length; ++i)
|
||||||
{
|
{
|
||||||
int opcode = instructions[i];
|
int opcode = instructions[i];
|
||||||
|
int iop = iops[i];
|
||||||
|
|
||||||
|
if (opcode == Opcodes.SWITCH)
|
||||||
|
{
|
||||||
|
Map<Integer, Integer> switchMap = switches[iop];
|
||||||
|
|
||||||
|
for (Entry<Integer, Integer> entry : switchMap.entrySet())
|
||||||
|
{
|
||||||
|
int offset = entry.getValue();
|
||||||
|
|
||||||
|
int to = i + offset + 1;
|
||||||
|
assert to >= 0 && to < instructions.length;
|
||||||
|
jumped[to] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isJump(opcode))
|
if (!isJump(opcode))
|
||||||
{
|
{
|
||||||
@@ -73,7 +90,7 @@ public class Disassembler
|
|||||||
// + 1 because the jumps go to the instructions prior to the
|
// + 1 because the jumps go to the instructions prior to the
|
||||||
// one you really want, because the pc is incremented on the
|
// one you really want, because the pc is incremented on the
|
||||||
// next loop
|
// next loop
|
||||||
int to = i + iop[i] + 1;
|
int to = i + iop + 1;
|
||||||
assert to >= 0 && to < instructions.length;
|
assert to >= 0 && to < instructions.length;
|
||||||
|
|
||||||
jumped[to] = true;
|
jumped[to] = true;
|
||||||
@@ -86,11 +103,10 @@ public class Disassembler
|
|||||||
{
|
{
|
||||||
StringBuilder writer = new StringBuilder();
|
StringBuilder writer = new StringBuilder();
|
||||||
|
|
||||||
writeAttributes(script, writer);
|
|
||||||
|
|
||||||
int[] instructions = script.getInstructions();
|
int[] instructions = script.getInstructions();
|
||||||
int[] iops = script.getIntOperands();
|
int[] iops = script.getIntOperands();
|
||||||
String[] sops = script.getStringOperands();
|
String[] sops = script.getStringOperands();
|
||||||
|
Map<Integer, Integer>[] switches = script.getSwitches();
|
||||||
|
|
||||||
assert iops.length == instructions.length;
|
assert iops.length == instructions.length;
|
||||||
assert sops.length == instructions.length;
|
assert sops.length == instructions.length;
|
||||||
@@ -127,7 +143,7 @@ public class Disassembler
|
|||||||
|
|
||||||
writer.append(String.format(" %-22s", name));
|
writer.append(String.format(" %-22s", name));
|
||||||
|
|
||||||
if (iop != 0 || opcode == Opcodes.LOAD_INT)
|
if (shouldWriteIntOperand(opcode, iop))
|
||||||
{
|
{
|
||||||
if (isJump(opcode))
|
if (isJump(opcode))
|
||||||
{
|
{
|
||||||
@@ -143,34 +159,36 @@ public class Disassembler
|
|||||||
{
|
{
|
||||||
writer.append(" \"").append(sop).append("\"");
|
writer.append(" \"").append(sop).append("\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opcode == Opcodes.SWITCH)
|
||||||
|
{
|
||||||
|
Map<Integer, Integer> switchMap = switches[iop];
|
||||||
|
|
||||||
|
for (Entry<Integer, Integer> entry : switchMap.entrySet())
|
||||||
|
{
|
||||||
|
int value = entry.getKey();
|
||||||
|
int jump = entry.getValue();
|
||||||
|
|
||||||
|
writer.append("\n");
|
||||||
|
writer.append(" ").append(value).append(": LABEL").append(i + jump + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writer.append("\n");
|
writer.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return writer.toString();
|
return writer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAttributes(ScriptDefinition script, StringBuilder writer)
|
private boolean shouldWriteIntOperand(int opcode, int operand)
|
||||||
{
|
{
|
||||||
Map<Integer, Integer>[] attributes = script.getAttributes();
|
if (opcode == Opcodes.SWITCH)
|
||||||
if (attributes == null)
|
|
||||||
{
|
{
|
||||||
return;
|
// table follows instruction
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = -1;
|
// Write if operand != 0 or if the instruction is specifically to load int
|
||||||
for (Map<Integer, Integer> map : attributes)
|
return operand != 0 || opcode == Opcodes.LOAD_INT;
|
||||||
{
|
|
||||||
++index;
|
|
||||||
|
|
||||||
if (map == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Entry<Integer, Integer> entry : map.entrySet())
|
|
||||||
{
|
|
||||||
writer.append(".attr ").append(index).append(" ").append(entry.getKey()).append(" ").append(entry.getValue()).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,17 +30,34 @@ import net.runelite.cache.script.disassembler.Disassembler;
|
|||||||
import org.apache.commons.compress.utils.IOUtils;
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameter;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
public class AssemblerTest
|
public class AssemblerTest
|
||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AssemblerTest.class);
|
private static final Logger logger = LoggerFactory.getLogger(AssemblerTest.class);
|
||||||
|
|
||||||
|
@Parameter
|
||||||
|
public String script;
|
||||||
|
|
||||||
|
@Parameters
|
||||||
|
public static String[] scripts()
|
||||||
|
{
|
||||||
|
return new String[]
|
||||||
|
{
|
||||||
|
"395.rs2asm", "91.rs2asm"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAssemble() throws Exception
|
public void testAssemble() throws Exception
|
||||||
{
|
{
|
||||||
InputStream in = AssemblerTest.class.getResourceAsStream("395.rs2asm");
|
InputStream in = AssemblerTest.class.getResourceAsStream(script);
|
||||||
Assert.assertNotNull(in);
|
Assert.assertNotNull(in);
|
||||||
|
|
||||||
Assembler assembler = new Assembler();
|
Assembler assembler = new Assembler();
|
||||||
@@ -50,7 +67,7 @@ public class AssemblerTest
|
|||||||
Disassembler disassembler = new Disassembler();
|
Disassembler disassembler = new Disassembler();
|
||||||
String out = disassembler.disassemble(script);
|
String out = disassembler.disassemble(script);
|
||||||
|
|
||||||
in = AssemblerTest.class.getResourceAsStream("395.rs2asm");
|
in = AssemblerTest.class.getResourceAsStream(this.script);
|
||||||
Assert.assertNotNull(in);
|
Assert.assertNotNull(in);
|
||||||
|
|
||||||
String original = new String(IOUtils.toByteArray(in));
|
String original = new String(IOUtils.toByteArray(in));
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
.attr 4 8 15
|
|
||||||
.attr 16 23 42
|
|
||||||
033
|
033
|
||||||
get_boostedskilllevels
|
get_boostedskilllevels
|
||||||
int_to_string
|
int_to_string
|
||||||
|
|||||||
117
cache/src/test/resources/net/runelite/cache/script/assembler/91.rs2asm
vendored
Normal file
117
cache/src/test/resources/net/runelite/cache/script/assembler/91.rs2asm
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
033
|
||||||
|
switch
|
||||||
|
3: LABEL20
|
||||||
|
5: LABEL54
|
||||||
|
6: LABEL54
|
||||||
|
7: LABEL3
|
||||||
|
jump LABEL84
|
||||||
|
LABEL3:
|
||||||
|
033 1
|
||||||
|
042 175
|
||||||
|
if_icmplt LABEL7
|
||||||
|
jump LABEL9
|
||||||
|
LABEL7:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL9:
|
||||||
|
035
|
||||||
|
string_remove_html
|
||||||
|
3623
|
||||||
|
load_int 1
|
||||||
|
if_icmpeq LABEL15
|
||||||
|
jump LABEL17
|
||||||
|
LABEL15:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL17:
|
||||||
|
load_int 1
|
||||||
|
return
|
||||||
|
jump LABEL84
|
||||||
|
LABEL20:
|
||||||
|
033 1
|
||||||
|
042 175
|
||||||
|
if_icmplt LABEL24
|
||||||
|
jump LABEL26
|
||||||
|
LABEL24:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL26:
|
||||||
|
035
|
||||||
|
string_remove_html
|
||||||
|
3623
|
||||||
|
load_int 1
|
||||||
|
if_icmpeq LABEL32
|
||||||
|
jump LABEL34
|
||||||
|
LABEL32:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL34:
|
||||||
|
5005
|
||||||
|
load_int 0
|
||||||
|
if_icmpeq LABEL38
|
||||||
|
jump LABEL40
|
||||||
|
LABEL38:
|
||||||
|
load_int 1
|
||||||
|
return
|
||||||
|
LABEL40:
|
||||||
|
5005
|
||||||
|
load_int 1
|
||||||
|
if_icmpeq LABEL44
|
||||||
|
jump LABEL51
|
||||||
|
LABEL44:
|
||||||
|
035
|
||||||
|
3609
|
||||||
|
load_int 1
|
||||||
|
if_icmpeq LABEL49
|
||||||
|
jump LABEL51
|
||||||
|
LABEL49:
|
||||||
|
load_int 1
|
||||||
|
return
|
||||||
|
LABEL51:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
jump LABEL84
|
||||||
|
LABEL54:
|
||||||
|
033 1
|
||||||
|
042 175
|
||||||
|
if_icmplt LABEL58
|
||||||
|
jump LABEL60
|
||||||
|
LABEL58:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL60:
|
||||||
|
033
|
||||||
|
load_int 5
|
||||||
|
if_icmpeq LABEL64
|
||||||
|
jump LABEL76
|
||||||
|
LABEL64:
|
||||||
|
025 1627
|
||||||
|
load_int 0
|
||||||
|
if_icmpeq LABEL68
|
||||||
|
jump LABEL76
|
||||||
|
LABEL68:
|
||||||
|
get_gamecycle
|
||||||
|
033 1
|
||||||
|
isub
|
||||||
|
load_int 500
|
||||||
|
if_icmpge LABEL74
|
||||||
|
jump LABEL76
|
||||||
|
LABEL74:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL76:
|
||||||
|
5005
|
||||||
|
load_int 2
|
||||||
|
if_icmpne LABEL80
|
||||||
|
jump LABEL82
|
||||||
|
LABEL80:
|
||||||
|
load_int 1
|
||||||
|
return
|
||||||
|
LABEL82:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
LABEL84:
|
||||||
|
load_int 0
|
||||||
|
return
|
||||||
|
load_int -1
|
||||||
|
return
|
||||||
Reference in New Issue
Block a user