cache: add script attrs to assembler and disassembler

This commit is contained in:
Adam
2017-05-07 15:34:27 -04:00
parent e210cf6f1e
commit b96619e2d8
6 changed files with 161 additions and 12 deletions

View File

@@ -24,7 +24,13 @@
*/ */
grammar rs2asm; grammar rs2asm;
prog: (line NEWLINE)+ ; prog: (attr NEWLINE)* (line NEWLINE)+ ;
attr: '.attr ' attr_idx ' ' attr_key ' ' attr_value ;
attr_idx: INT ;
attr_key: INT ;
attr_value: INT ;
line: instruction | label ; line: instruction | label ;
instruction: instruction_name instruction_operand ; instruction: instruction_name instruction_operand ;
label: 'LABEL' INT ':' ; label: 'LABEL' INT ':' ;

View File

@@ -0,0 +1,62 @@
/*
* 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;
public class Attribute
{
private int idx;
private int key;
private int value;
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()
{
return value;
}
public void setValue(int value)
{
this.value = value;
}
}

View File

@@ -25,7 +25,9 @@
package net.runelite.cache.script.assembler; package net.runelite.cache.script.assembler;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
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;
@@ -42,12 +44,45 @@ 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<>();
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)
{ {
@@ -127,6 +162,29 @@ 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());
return script; return script;
} }
private Map<Integer, Integer>[] buildAttributes()
{
if (attrs == null || attrs.isEmpty())
{
return null;
}
Map<Integer, Integer>[] maps = new Map[attrs.stream().map(attr -> attr.getIdx()).max(Integer::compare).get() + 1];
for (Attribute attr : attrs)
{
Map<Integer, Integer> map = maps[attr.getIdx()];
if (map == null)
{
map = new HashMap<>();
maps[attr.getIdx()] = map;
}
map.put(attr.getKey(), attr.getValue());
}
return maps;
}
} }

View File

@@ -25,6 +25,8 @@
package net.runelite.cache.script.disassembler; package net.runelite.cache.script.disassembler;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
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;
@@ -84,6 +86,8 @@ 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();
@@ -144,4 +148,29 @@ public class Disassembler
return writer.toString(); return writer.toString();
} }
private void writeAttributes(ScriptDefinition script, StringBuilder writer)
{
Map<Integer, Integer>[] attributes = script.getAttributes();
if (attributes == null)
{
return;
}
int index = -1;
for (Map<Integer, Integer> map : attributes)
{
++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");
}
}
}
} }

View File

@@ -30,21 +30,13 @@ 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.Before;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.slf4j.impl.SimpleLogger;
public class AssemblerTest public class AssemblerTest
{ {
private static final Logger logger = LoggerFactory.getLogger(AssemblerTest.class); private static final Logger logger = LoggerFactory.getLogger(AssemblerTest.class);
@Before
public void before()
{
System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG");
}
@Test @Test
public void testAssemble() throws Exception public void testAssemble() throws Exception
{ {
@@ -63,9 +55,9 @@ public class AssemblerTest
String original = new String(IOUtils.toByteArray(in)); String original = new String(IOUtils.toByteArray(in));
logger.debug(original); logger.info(original);
logger.debug("-----------------------"); logger.info("-----------------------");
logger.debug(out); logger.info(out);
Assert.assertEquals(original, out); Assert.assertEquals(original, out);
} }

View File

@@ -1,3 +1,5 @@
.attr 4 8 15
.attr 16 23 42
033 033
get_boostedskilllevels get_boostedskilllevels
int_to_string int_to_string