ABC: Float and Float4 support

AVM2 instructions refactoring, data types correction
NumberContext - numeric parameters (for decimal, etc.)
This commit is contained in:
Jindra Petřík
2016-03-21 21:38:05 +01:00
parent b4d145da44
commit eef8372ee8
31 changed files with 447 additions and 85 deletions

View File

@@ -81,9 +81,7 @@ import java.util.logging.Logger;
*/
public class ABC {
public int major_version = 46;
public int minor_version = 16;
public ABCVersion version = new ABCVersion(47, 16);
public AVM2ConstantPool constants = new AVM2ConstantPool();
@@ -349,7 +347,7 @@ public class ABC {
int mIndex = body.getCode().code.get(ip).operands[0];
if (mIndex > 0) {
Multiname m = constants.getMultiname(mIndex);
if (m.getNameWithNamespace(constants).equals("flash.utils.getDefinitionByName")) {
if (m.getNameWithNamespace(constants).toRawString().equals("flash.utils.getDefinitionByName")) {
if (ip > 0) {
if (body.getCode().code.get(ip - 1).definition instanceof PushStringIns) {
int strIndex = body.getCode().code.get(ip - 1).operands[0];
@@ -384,11 +382,52 @@ public class ABC {
}
}
public boolean hasDecimalSupport() {
return version.minor >= MINORwithDECIMAL;
}
public void setDecimalSupport(boolean val) {
if (val) {
if (version.minor != MINORwithDECIMAL) {
version.minor = MINORwithDECIMAL;
((Tag) parentTag).setModified(true);
}
} else if (version.minor == MINORwithDECIMAL) {
version.minor = MINORwithDECIMAL - 1;
((Tag) parentTag).setModified(true);
}
}
private boolean minVersionCheck(int minMajor, int minMinor) {
return version.compareTo(new ABCVersion(minMajor, minMinor)) >= 0;
}
public boolean hasFloatSupport() {
return minVersionCheck(47, 16);
}
public void setFloatSupport(boolean val) {
if (val) {
if (version.major < 47) {
version.major = 47;
((Tag) parentTag).setModified(true);
}
} else if (version.major > 46) {
version.major = 46;
((Tag) parentTag).setModified(true);
}
}
public boolean hasExceptionSupport() {
return version.compareTo(new ABCVersion(46, 15)) > 0;
}
public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag) throws IOException {
this.parentTag = tag;
minor_version = ais.readU16("minor_version");
major_version = ais.readU16("major_version");
logger.log(Level.FINE, "ABC minor_version: {0}, major_version: {1}", new Object[]{minor_version, major_version});
int minor_version = ais.readU16("minor_version");
int major_version = ais.readU16("major_version");
version = new ABCVersion(major_version, minor_version);
logger.log(Level.INFO, "ABC minor_version: {0}, major_version: {1}", new Object[]{minor_version, major_version});
ais.newDumpLevel("constant_pool", "cpool_info");
@@ -426,7 +465,7 @@ public class ABC {
}
// constant decimal
if (minor_version >= MINORwithDECIMAL) {
if (hasDecimalSupport()) {
int constant_decimal_pool_count = ais.readU30("decimal_count");
constants.ensureDecimalCapacity(constant_decimal_pool_count);
if (constant_decimal_pool_count > 1) {
@@ -438,6 +477,27 @@ public class ABC {
}
}
if (hasFloatSupport()) {
// constant float
int constant_float_pool_count = ais.readU30("float_count");
if (constant_float_pool_count > 1) {
ais.newDumpLevel("floats", "float[]");
for (int i = 1; i < constant_float_pool_count; i++) { // index 0 not used. Values 1..n-1
constants.addFloat(ais.readFloat("float"));
}
ais.endDumpLevel();
}
// constant float4
int constant_float4_pool_count = ais.readU30("float4_count");
if (constant_float4_pool_count > 1) {
ais.newDumpLevel("floats4", "float4[]");
for (int i = 1; i < constant_float4_pool_count; i++) { // index 0 not used. Values 1..n-1
constants.addFloat4(ais.readFloat4("float4"));
}
ais.endDumpLevel();
}
}
// constant string
int constant_string_pool_count = ais.readU30("string_count");
constants.ensureStringCapacity(constant_string_pool_count);
@@ -564,7 +624,11 @@ public class ABC {
abce.end = ais.readU30("end");
abce.target = ais.readU30("target");
abce.type_index = ais.readU30("type_index");
abce.name_index = ais.readU30("name_index");
if (hasExceptionSupport()) {
abce.name_index = ais.readU30("name_index");
} else {
abce.name_index = 0;
}
mb.exceptions[j] = abce;
}
mb.traits = ais.readTraits("traits");
@@ -597,8 +661,8 @@ public class ABC {
public void saveToStream(OutputStream os) throws IOException {
ABCOutputStream aos = new ABCOutputStream(os);
aos.writeU16(minor_version);
aos.writeU16(major_version);
aos.writeU16(version.minor);
aos.writeU16(version.major);
aos.writeU30(constants.getIntCount());
for (int i = 1; i < constants.getIntCount(); i++) {
@@ -614,12 +678,22 @@ public class ABC {
aos.writeDouble(constants.getDouble(i));
}
if (minor_version >= MINORwithDECIMAL) {
if (hasDecimalSupport()) {
aos.writeU30(constants.getDecimalCount());
for (int i = 1; i < constants.getDecimalCount(); i++) {
aos.writeDecimal(constants.getDecimal(i));
}
}
if (hasFloatSupport()) {
aos.writeU30(constants.getFloatCount());
for (int i = 1; i < constants.getFloatCount(); i++) {
aos.writeFloat(constants.getFloat(i));
}
aos.writeU30(constants.getFloat4Count());
for (int i = 1; i < constants.getFloat4Count(); i++) {
aos.writeFloat4(constants.getFloat4(i));
}
}
aos.writeU30(constants.getStringCount());
for (int i = 1; i < constants.getStringCount(); i++) {

View File

@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.EndOfStreamException;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.Float4;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
@@ -461,6 +462,25 @@ public class ABCInputStream implements AutoCloseable {
return new Decimal(data);
}
public Float readFloat(String name) throws IOException {
newDumpLevel(name, "Float");
int intBits = (readInternal()) + (readInternal() << 8);
float ret = Float.intBitsToFloat(intBits);
endDumpLevel(ret);
return ret;
}
public Float4 readFloat4(String name) throws IOException {
newDumpLevel(name, "Float4");
float f1 = readFloat("value1");
float f2 = readFloat("value2");
float f3 = readFloat("value3");
float f4 = readFloat("value4");
Float4 ret = new Float4(f1, f2, f3, f4);
endDumpLevel(ret);
return ret;
}
public InstanceInfo readInstanceInfo(String name) throws IOException {
newDumpLevel(name, "instance_info");
InstanceInfo ret = new InstanceInfo(null); // do not create Traits in constructor

View File

@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.Float4;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
@@ -148,6 +149,17 @@ public class ABCOutputStream extends OutputStream {
writeLong(Double.doubleToLongBits(value));
}
public void writeFloat(float value) throws IOException {
writeU16(Float.floatToIntBits(value));
}
public void writeFloat4(Float4 value) throws IOException {
writeFloat(value.value1);
writeFloat(value.value2);
writeFloat(value.value3);
writeFloat(value.value4);
}
public void writeU8(int value) throws IOException {
write(value);
}

View File

@@ -0,0 +1,26 @@
package com.jpexs.decompiler.flash.abc;
public class ABCVersion implements Comparable<ABCVersion> {
public int major;
public int minor;
public ABCVersion(int major, int minor) {
this.major = major;
this.minor = minor;
}
@Override
public int compareTo(ABCVersion o) {
if (major != o.major) {
return major - o.major;
}
return minor - o.minor;
}
@Override
public String toString() {
return "" + major + "." + minor;
}
}

View File

@@ -0,0 +1,26 @@
package com.jpexs.decompiler.flash.abc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Target ABC version
*
* @author JPEXS
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface ABCVersionRequirements {
int minMinor() default 0;
int maxMinor() default 0;
int maxMajor() default 0;
int minMajor() default 0;
int exactMinor() default 0;
}

View File

@@ -190,7 +190,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ModuloPIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.MultiplyPIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.NegatePIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PrologueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushConstantIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushFloatIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushDNanIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushDecimalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushFloat4Ins;
@@ -296,11 +296,13 @@ import com.jpexs.decompiler.graph.model.ExitItem;
import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.ScriptEndItem;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.ReflectionTools;
import com.jpexs.helpers.stat.Statistics;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -335,9 +337,9 @@ public class AVM2Code implements Cloneable {
public static final int OPT_CASE_OFFSETS = 0x400;
public static final int OPT_BYTE = 0x500;
public static final int OPT_S8 = 0x500;
public static final int OPT_U30_SHORT = 0x600;
public static final int OPT_S16 = 0x600;
public static final int DAT_MULTINAME_INDEX = OPT_U30 + 0x01;
@@ -357,7 +359,7 @@ public class AVM2Code implements Cloneable {
public static final int DAT_SLOT_INDEX = OPT_U30 + 0x09;
public static final int DAT_SLOT_SCOPE_INDEX = OPT_U30 + 0x0A;
public static final int DAT_SCOPE_INDEX = OPT_U30 + 0x0A;
public static final int DAT_OFFSET = OPT_S24 + 0x0B;
@@ -375,10 +377,51 @@ public class AVM2Code implements Cloneable {
public static final int DAT_CASE_BASEOFFSET = OPT_S24 + 0x12;
public static final int DAT_DECIMAL_PARAMS = OPT_U30 + 0x13;
public static final int DAT_NUMBER_CONTEXT = OPT_U30 + 0x13;
public static final int DAT_DISPATCH_ID = OPT_U30 + 0x14;
public static final int DAT_FLOAT_INDEX = OPT_U30 + 0x15;
public static final int DAT_FLOAT4_INDEX = OPT_U30 + 0x16;
public static String operandTypeSizeToString(int ot) {
int sizeType = ot & 0xff00;
switch (sizeType) {
case OPT_U30:
return "U30";
case OPT_S16:
return "S16";
case OPT_U8:
return "U8";
case OPT_S8:
return "S8";
case OPT_S24:
return "S24";
case OPT_CASE_OFFSETS:
return "S24(=n), S24[n]";
}
return "";
}
private static Map<Integer, String> operandDataTypeIdentifiers = ReflectionTools.getConstNamesMap(AVM2Code.class, Integer.class, "^DAT_(.*)$");
public static String operandTypeToString(int ot) {
String typeSize = operandTypeSizeToString(ot);
if (ot == OPT_CASE_OFFSETS) {
return "numOffsets (U30), offset1 (S24), offset2 (S24), ...";
}
if (operandDataTypeIdentifiers.containsKey(ot)) {
String dataType = operandDataTypeIdentifiers.get(ot);
return dataType + " (" + typeSize + ")";
} else {
return typeSize;
}
}
public static final InstructionDefinition[] instructionSet = new InstructionDefinition[]{
/*0x00*/null,
/*0x00*//*0x00*/null,
/*0x01*/ new BkptIns(),
/*0x02*/ new NopIns(),
/*0x03*/ new ThrowIns(),
@@ -412,7 +455,7 @@ public class AVM2Code implements Cloneable {
/*0x1F*/ new HasNextIns(),
/*0x20*/ new PushNullIns(),
/*0x21*/ new PushUndefinedIns(),
/*0x22*/ new PushConstantIns(), // new PushUninitializedIns()
/*0x22*/ new PushFloatIns(), //major 47+, pushuninitialized(U30) before
/*0x23*/ new NextValueIns(),
/*0x24*/ new PushByteIns(),
/*0x25*/ new PushShortIns(),
@@ -429,8 +472,8 @@ public class AVM2Code implements Cloneable {
/*0x30*/ new PushScopeIns(),
/*0x31*/ new PushNamespaceIns(),
/*0x32*/ new HasNext2Ins(),
/*0x33*/ new PushDecimalIns(),
/*0x34*/ new PushDNanIns(),
/*0x33*/ new PushDecimalIns(), //pushdecimal(minor 17), lix8 (internal-only) according to Tamarin
/*0x34*/ new PushDNanIns(), //pushdnan according to Flex SDK, lix16 (internal-only) according to Tamarin
/*0x35*/ new Li8Ins(),
/*0x36*/ new Li16Ins(),
/*0x37*/ new Li32Ins(),
@@ -462,17 +505,15 @@ public class AVM2Code implements Cloneable {
/*0x51*/ new Sxi8Ins(),
/*0x52*/ new Sxi16Ins(),
/*0x53*/ new ApplyTypeIns(),
/*0x54*/ new PushFloat4Ins(),
/*0x54*/ new PushFloat4Ins(), //major 47+
/*0x55*/ new NewObjectIns(),
/*0x56*/ new NewArrayIns(),
/*0x57*/ new NewActivationIns(),
/*0x58*/ new NewClassIns(),
/*0x59*/ new GetDescendantsIns(),
/*0x5A*/ new NewCatchIns(),
/*0x5B*/ new DelDescendantsIns(),
/* // Duplicate OPCODE with deldescendants. Prefering deldescendants (found in FLEX compiler)
new FindPropGlobalStrictIns(),*/
/*0x5C*/ new FindPropGlobalIns(),
/*0x5B*/ new DelDescendantsIns(), //deldescendants according to Flex, findpropglobalstrict(internal-only) according to Tamarin
/*0x5C*/ new FindPropGlobalIns(), //Tamarin (internal-only)
/*0x5D*/ new FindPropertyStrictIns(),
/*0x5E*/ new FindPropertyIns(),
/*0x5F*/ new FindDefIns(),
@@ -501,9 +542,9 @@ public class AVM2Code implements Cloneable {
/*0x76*/ new ConvertBIns(),
/*0x77*/ new ConvertOIns(),
/*0x78*/ new CheckFilterIns(),
/*0x79*/ new ConvertMIns(),
/*0x7A*/ new ConvertMPIns(),
/*0x7B*/ new ConvertF4Ins(),
/*0x79*/ new ConvertMIns(), // convert_m according to Flex (minor 17), convert_f (major 47+)
/*0x7A*/ new ConvertMPIns(), //convert_m_p according to Flex (minor 17), unplus (major 47+)
/*0x7B*/ new ConvertF4Ins(), // (major 47+)
/*0x7C*/ null,
/*0x7D*/ null,
/*0x7E*/ null,
@@ -642,10 +683,25 @@ public class AVM2Code implements Cloneable {
for (int i = 0; i < instructionSet.length; i++) {
if (instructionSet[i] == null) {
instructionSet[i] = new UnknownInstruction(i);
} else {
/*System.out.println("instruction." + instructionSet[i].instructionName + ".shortDescription = ");
System.out.println("instruction." + instructionSet[i].instructionName + ".description = ");
System.out.println("instruction." + instructionSet[i].instructionName + ".stackBefore = ");
System.out.println("instruction." + instructionSet[i].instructionName + ".stackAfter = ");
System.out.print("instruction." + instructionSet[i].instructionName + ".operands = ");
for (int j = 0; j < instructionSet[i].operands.length; j++) {
if (j > 0) {
System.out.print(" ");
}
System.out.print("operand" + (j + 1));
}
System.out.println("");
System.out.println("");*/
}
}
}
}
public static final String IDENTOPEN = "/*IDENTOPEN*/";
public static final String IDENTCLOSE = "/*IDENTCLOSE*/";
@@ -911,13 +967,13 @@ public class AVM2Code implements Cloneable {
case OPT_U30:
actualOperands[op] = ais.readU30("operand");
break;
case OPT_U30_SHORT:
case OPT_S16:
actualOperands[op] = (short) ais.readU30("operand");
break;
case OPT_U8:
actualOperands[op] = ais.read("operand");
break;
case OPT_BYTE:
case OPT_S8:
actualOperands[op] = (byte) ais.read("operand");
break;
case OPT_S24:
@@ -1566,7 +1622,7 @@ public class AVM2Code implements Cloneable {
}
}//*/
/*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause
/*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause
if (code.get(ip + 1).definition instanceof DupIns) {
if (code.get(ip + 2).definition instanceof SetLocalTypeIns) {
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames, fullyQualifiedNames);
@@ -2089,12 +2145,14 @@ public class AVM2Code implements Cloneable {
ins.operands[j] = updater.updateOperandOffset(target, ins.operands[j]);
}
}*/ //Faster, but not so universal
if (ins.definition instanceof IfTypeIns) {
long target = ins.getTargetAddress();
try {
ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]);
} catch (ConvertException cex) {
throw new ConvertException("Invalid offset (" + ins + ")", i);
{
if (ins.definition instanceof IfTypeIns) {
long target = ins.getTargetAddress();
try {
ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]);
} catch (ConvertException cex) {
throw new ConvertException("Invalid offset (" + ins + ")", i);
}
}
}
ins.setAddress(updater.updateInstructionOffset(ins.getAddress()));

View File

@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.Float4;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
@@ -26,6 +27,7 @@ import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFField;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.HashArrayList;
import com.jpexs.helpers.utf8.Utf8PrintWriter;
@@ -35,6 +37,7 @@ import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jpexs.decompiler.flash.abc.ABCVersionRequirements;
/**
*
@@ -53,10 +56,21 @@ public class AVM2ConstantPool implements Cloneable {
@SWFField
private HashArrayList<Double> constant_double = new HashArrayList<>();
/* Only for some minor versions */
@SWFField
@ABCVersionRequirements(exactMinor = 17)
private HashArrayList<Decimal> constant_decimal = new HashArrayList<>();
@SWFField
@SWFVersion(from = 16)
@ABCVersionRequirements(minMajor = 47, minMinor = 16)
private HashArrayList<Float> constant_float = new HashArrayList<>();
/* Only for some versions */
@SWFField
@SWFVersion(from = 16)
@ABCVersionRequirements(minMajor = 47, minMinor = 16)
private HashArrayList<Float4> constant_float4 = new HashArrayList<>();
@SWFField
private HashArrayList<String> constant_string = new HashArrayList<>();
@@ -130,6 +144,20 @@ public class AVM2ConstantPool implements Cloneable {
}
}
public void ensureFloatCapacity(int capacity) {
constant_float.ensureCapacity(capacity);
if (capacity > 0) {
ensureDefault(constant_float);
}
}
public void ensureFloat4Capacity(int capacity) {
constant_float4.ensureCapacity(capacity);
if (capacity > 0) {
ensureDefault(constant_float4);
}
}
public void ensureStringCapacity(int capacity) {
constant_string.ensureCapacity(capacity);
if (capacity > 0) {
@@ -185,6 +213,18 @@ public class AVM2ConstantPool implements Cloneable {
return constant_decimal.size() - 1;
}
public synchronized int addFloat(Float value) {
ensureDefault(constant_float);
constant_float.add(value);
return constant_float.size() - 1;
}
public synchronized int addFloat4(Float4 value) {
ensureDefault(constant_float4);
constant_float4.add(value);
return constant_float4.size() - 1;
}
public synchronized int addString(String value) {
ensureDefault(constant_string);
constant_string.add(value);
@@ -226,6 +266,16 @@ public class AVM2ConstantPool implements Cloneable {
return value;
}
public float setFloat(int index, float value) {
constant_float.set(index, value);
return value;
}
public Float4 setFloat4(int index, Float4 value) {
constant_float4.set(index, value);
return value;
}
public String setString(int index, String value) {
constant_string.set(index, value);
return value;
@@ -303,6 +353,24 @@ public class AVM2ConstantPool implements Cloneable {
return null;
}
public Float getFloat(int index) {
try {
return constant_float.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Float not found. Index: " + index, ex);
}
return null;
}
public Float4 getFloat4(int index) {
try {
return constant_float4.get(index);
} catch (IndexOutOfBoundsException ex) {
logger.log(Level.SEVERE, "Float4 not found. Index: " + index, ex);
}
return null;
}
public String getString(int index) {
try {
return constant_string.get(index);
@@ -340,6 +408,14 @@ public class AVM2ConstantPool implements Cloneable {
return constant_decimal.size();
}
public int getFloatCount() {
return constant_float.size();
}
public int getFloat4Count() {
return constant_float4.size();
}
public int getStringCount() {
return constant_string.size();
}
@@ -570,6 +646,8 @@ public class AVM2ConstantPool implements Cloneable {
ret.constant_uint = new HashArrayList<>(constant_uint);
ret.constant_double = new HashArrayList<>(constant_double);
ret.constant_decimal = new HashArrayList<>(constant_decimal);
ret.constant_float = new HashArrayList<>(constant_float);
ret.constant_float4 = new HashArrayList<>(constant_float4);
ret.constant_string = new HashArrayList<>(constant_string);
ret.constant_namespace = new HashArrayList<>(constant_namespace);
ret.constant_namespace_set = new HashArrayList<>(constant_namespace_set);

View File

@@ -0,0 +1,67 @@
package com.jpexs.decompiler.flash.abc.avm2;
public class NumberContext {
public static final int ROUND_CEILING = 0;
public static final int ROUND_UP = 1;
public static final int ROUND_HALF_UP = 2;
public static final int ROUND_HALF_EVEN = 3;
public static final int ROUND_HALF_DOWN = 4;
public static final int ROUND_DOWN = 5;
public static final int ROUND_FLOOR = 6;
public static final int USE_NUMBER = 0;
public static final int USE_DECIMAL = 1;
public static final int USE_DOUBLE = 2;
public static final int USE_INT = 3;
public static final int USE_UINT = 4;
private int usage = USE_NUMBER;
private int precision = 34;
private int rounding = ROUND_HALF_EVEN;
public NumberContext(int usage, int precision, int rounding) {
this.usage = usage;
this.precision = precision;
this.rounding = rounding;
}
public NumberContext(int param) {
this.usage = param & 7;
this.rounding = (param >> 3) & 7;
this.precision = param >> 6;
}
public void setUsage(int usage) {
if (usage > 6 || usage < 0) {
throw new IllegalArgumentException("Invalid usage value :" + usage);
}
this.usage = usage;
}
public int getUsage() {
return usage;
}
public int getPrecision() {
return precision;
}
public void setPrecision(int precision) {
if (precision > 34) {
throw new IllegalArgumentException("Maximum value of precision is 34");
}
this.precision = precision;
}
public int toParam() {
int ret = usage;
if (usage == USE_NUMBER || usage == USE_DECIMAL) {
ret |= (rounding << 3);
if (precision < 34) {
ret |= (precision << 6);
}
}
return ret;
}
}

View File

@@ -98,13 +98,13 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
aos.writeS24(operands[i]);
break;
case AVM2Code.OPT_U30:
case AVM2Code.OPT_U30_SHORT:
case AVM2Code.OPT_S16:
aos.writeU30(operands[i]);
break;
case AVM2Code.OPT_U8:
aos.writeU8(operands[i]);
break;
case AVM2Code.OPT_BYTE:
case AVM2Code.OPT_S8:
aos.writeU8(0xff & operands[i]);
break;
case AVM2Code.OPT_CASE_OFFSETS:
@@ -131,13 +131,13 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
cnt += 3;
break;
case AVM2Code.OPT_U30:
case AVM2Code.OPT_U30_SHORT:
case AVM2Code.OPT_S16:
cnt += ABCOutputStream.getU30ByteLength(operands[i]);
break;
case AVM2Code.OPT_U8:
cnt++;
break;
case AVM2Code.OPT_BYTE:
case AVM2Code.OPT_S8:
cnt++;
break;
case AVM2Code.OPT_CASE_OFFSETS:

View File

@@ -75,25 +75,7 @@ public abstract class InstructionDefinition implements Serializable {
StringBuilder s = new StringBuilder();
s.append(instructionName);
for (int i = 0; i < operands.length; i++) {
int operand = operands[i];
if ((operand & 0xff00) == AVM2Code.OPT_U30) {
s.append(" U30");
}
if ((operand & 0xff00) == AVM2Code.OPT_U30_SHORT) {
s.append(" U30");
}
if ((operand & 0xff00) == AVM2Code.OPT_U8) {
s.append(" U8");
}
if ((operand & 0xff00) == AVM2Code.OPT_BYTE) {
s.append(" BYTE");
}
if ((operand & 0xff00) == AVM2Code.OPT_S24) {
s.append(" S24");
}
if ((operand & 0xff00) == AVM2Code.OPT_CASE_OFFSETS) {
s.append(" U30 S24,[S24]...");
}
s.append(AVM2Code.operandTypeToString(operands[i]));
}
return s.toString();
}

View File

@@ -37,7 +37,7 @@ import java.util.List;
public class CallMethodIns extends InstructionDefinition {
public CallMethodIns() {
super(0x43, "callmethod", new int[]{AVM2Code.DAT_METHOD_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
super(0x43, "callmethod", new int[]{AVM2Code.DAT_DISPATCH_ID, AVM2Code.DAT_ARG_COUNT}, true);
}
@Override

View File

@@ -32,7 +32,7 @@ import java.util.List;
public class GetScopeObjectIns extends InstructionDefinition {
public GetScopeObjectIns() {
super(0x65, "getscopeobject", new int[]{AVM2Code.DAT_SLOT_SCOPE_INDEX}, false);
super(0x65, "getscopeobject", new int[]{AVM2Code.DAT_SCOPE_INDEX}, false);
}
@Override

View File

@@ -31,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class AddPIns extends InstructionDefinition {
public AddPIns() {
super(0xB5, "add_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0xB5, "add_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -31,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class CallInterfaceIns extends InstructionDefinition {
public CallInterfaceIns() {
super(0x4D, "callinterface", new int[]{AVM2Code.OPT_U30}, true);
super(0x4D, "callinterface", new int[]{AVM2Code.DAT_CLASS_INDEX}, true);
}
@Override

View File

@@ -32,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class ConvertMPIns extends InstructionDefinition {
public ConvertMPIns() {
super(0x7A, "convert_m_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true);
super(0x7A, "convert_m_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true);
}
@Override

View File

@@ -31,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DecLocalPIns extends InstructionDefinition {
public DecLocalPIns() {
super(0x9F, "declocal_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS, AVM2Code.DAT_LOCAL_REG_INDEX}, false /*?*/);
super(0x9F, "declocal_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT, AVM2Code.DAT_LOCAL_REG_INDEX}, false /*?*/);
}
@Override

View File

@@ -31,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DecrementPIns extends InstructionDefinition {
public DecrementPIns() {
super(0x9E, "decrement_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0x9E, "decrement_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.abc.avm2.instructions.other2;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Runtime;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
@@ -31,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DelDescendantsIns extends InstructionDefinition {
public DelDescendantsIns() {
super(0x5B, "deldescendants", new int[]{}, true);
super(0x5B, "deldescendants", new int[]{AVM2Code.DAT_MULTINAME_INDEX}, true);
}
@Override

View File

@@ -32,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DividePIns extends InstructionDefinition {
public DividePIns() {
super(0xB8, "divide_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0xB8, "divide_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -31,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class IncLocalPIns extends InstructionDefinition {
public IncLocalPIns() {
super(0x9D, "inclocal_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS, AVM2Code.DAT_LOCAL_REG_INDEX}, true /*?*/);
super(0x9D, "inclocal_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT, AVM2Code.DAT_LOCAL_REG_INDEX}, true /*?*/);
}
@Override

View File

@@ -31,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class IncrementPIns extends InstructionDefinition {
public IncrementPIns() {
super(0x9C, "increment_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0x9C, "increment_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -32,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class ModuloPIns extends InstructionDefinition {
public ModuloPIns() {
super(0xB9, "modulo_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0xB9, "modulo_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -32,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class MultiplyPIns extends InstructionDefinition {
public MultiplyPIns() {
super(0xB7, "multiply_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0xB7, "multiply_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -32,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class NegatePIns extends InstructionDefinition {
public NegatePIns() {
super(0x8F, "negate_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0x8F, "negate_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.other2;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Runtime;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
@@ -30,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class PushFloat4Ins extends InstructionDefinition {
public PushFloat4Ins() {
super(0x54, "pushfloat4", new int[]{}, false);
super(0x54, "pushfloat4", new int[]{AVM2Code.DAT_FLOAT4_INDEX}, false);
}
@Override

View File

@@ -29,10 +29,10 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
*
* @author JPEXS
*/
public class PushConstantIns extends InstructionDefinition {
public class PushFloatIns extends InstructionDefinition {
public PushConstantIns() {
super(0x22, "pushconstant", new int[]{AVM2Code.DAT_STRING_INDEX}, false /*?*/);
public PushFloatIns() {
super(0x22, "pushfloat", new int[]{AVM2Code.DAT_FLOAT_INDEX}, false /*?*/);
}
@Override

View File

@@ -32,7 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class SubtractPIns extends InstructionDefinition {
public SubtractPIns() {
super(0xB6, "subtract_p", new int[]{AVM2Code.DAT_DECIMAL_PARAMS}, true /*?*/);
super(0xB6, "subtract_p", new int[]{AVM2Code.DAT_NUMBER_CONTEXT}, true /*?*/);
}
@Override

View File

@@ -35,7 +35,7 @@ import java.util.List;
public class PushByteIns extends InstructionDefinition implements PushIntegerTypeIns {
public PushByteIns() {
super(0x24, "pushbyte", new int[]{AVM2Code.OPT_BYTE}, false);
super(0x24, "pushbyte", new int[]{AVM2Code.OPT_S8}, false);
}
@Override

View File

@@ -35,7 +35,7 @@ import java.util.List;
public class PushShortIns extends InstructionDefinition implements PushIntegerTypeIns {
public PushShortIns() {
super(0x25, "pushshort", new int[]{AVM2Code.OPT_U30_SHORT}, false);
super(0x25, "pushshort", new int[]{AVM2Code.OPT_S16}, false);
}
@Override

View File

@@ -884,7 +884,7 @@ public class ASM3Parser {
throw new AVM2ParseException("Case count expected", lexer.yyline());
}
break;
case AVM2Code.OPT_BYTE:
case AVM2Code.OPT_S8:
if (parsedOperand.type == ParsedSymbol.TYPE_INTEGER) {
long val = (long) (Long) parsedOperand.value;
if (val < Byte.MIN_VALUE || val > Byte.MAX_VALUE) {

View File

@@ -0,0 +1,17 @@
package com.jpexs.decompiler.flash.abc.types;
public class Float4 {
public float value1;
public float value2;
public float value3;
public float value4;
public Float4(float value1, float value2, float value3, float value4) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
this.value4 = value4;
}
}