Decompiler improvement, and converter improvement
This commit is contained in:
parent
c9fe0153e4
commit
a06423a6bc
@ -18,9 +18,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
import static com.alterdekim.flash.decompiler.util.ByteUtil.bytesToInt;
|
import static com.alterdekim.flash.decompiler.util.ByteUtil.*;
|
||||||
import static com.alterdekim.flash.decompiler.util.ByteUtil.bytesToIntRev;
|
|
||||||
import static com.alterdekim.flash.decompiler.util.Compression.decompressDEFLATE;
|
import static com.alterdekim.flash.decompiler.util.Compression.decompressDEFLATE;
|
||||||
import static com.alterdekim.flash.decompiler.util.Compression.decompressLZMA;
|
import static com.alterdekim.flash.decompiler.util.Compression.decompressLZMA;
|
||||||
|
|
||||||
@ -106,6 +107,10 @@ public class FlashDecompiler {
|
|||||||
i++;
|
i++;
|
||||||
tag.getActions().add(new ActionDefineLocal());
|
tag.getActions().add(new ActionDefineLocal());
|
||||||
break;
|
break;
|
||||||
|
case DefineLocal2:
|
||||||
|
i++;
|
||||||
|
tag.getActions().add(new ActionDefineLocal2());
|
||||||
|
break;
|
||||||
case SetMember:
|
case SetMember:
|
||||||
i++;
|
i++;
|
||||||
tag.getActions().add(new ActionSetMember());
|
tag.getActions().add(new ActionSetMember());
|
||||||
@ -114,6 +119,16 @@ public class FlashDecompiler {
|
|||||||
i++;
|
i++;
|
||||||
tag.getActions().add(new ActionGetVariable());
|
tag.getActions().add(new ActionGetVariable());
|
||||||
break;
|
break;
|
||||||
|
case SetVariable:
|
||||||
|
i++;
|
||||||
|
tag.getActions().add(new ActionSetVariable());
|
||||||
|
break;
|
||||||
|
case GetMember:
|
||||||
|
i++;
|
||||||
|
tag.getActions().add(new ActionGetMember());
|
||||||
|
break;
|
||||||
|
case Unknown:
|
||||||
|
return tag;
|
||||||
default:
|
default:
|
||||||
log.error("Unknown action field type: {}", StringUtils.bytesToHex(new byte[] {data[i]}));
|
log.error("Unknown action field type: {}", StringUtils.bytesToHex(new byte[] {data[i]}));
|
||||||
i++;
|
i++;
|
||||||
@ -133,6 +148,7 @@ public class FlashDecompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int parseActionPush(byte[] data, int i, DoAction tag) {
|
private int parseActionPush(byte[] data, int i, DoAction tag) {
|
||||||
|
//int start_action_index = i; // for debug
|
||||||
i++;
|
i++;
|
||||||
int len_in_bytes = bytesToIntRev(Arrays.copyOfRange(data, i, i+2));
|
int len_in_bytes = bytesToIntRev(Arrays.copyOfRange(data, i, i+2));
|
||||||
int u = 0;
|
int u = 0;
|
||||||
@ -143,6 +159,7 @@ public class FlashDecompiler {
|
|||||||
while( u < len_in_bytes ) {
|
while( u < len_in_bytes ) {
|
||||||
ActionPushType type = ActionPushType.fromType(data[i]);
|
ActionPushType type = ActionPushType.fromType(data[i]);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
// implement other types (float especially)
|
||||||
case STRING:
|
case STRING:
|
||||||
i++;
|
i++;
|
||||||
var result = findNull(data, i, u);
|
var result = findNull(data, i, u);
|
||||||
@ -175,6 +192,18 @@ public class FlashDecompiler {
|
|||||||
i++;
|
i++;
|
||||||
u++;
|
u++;
|
||||||
continue;
|
continue;
|
||||||
|
case BOOLEAN:
|
||||||
|
i++;
|
||||||
|
push.getItems().add(new BooleanItem( data[i] == 0x01 ));
|
||||||
|
i++;
|
||||||
|
u += 2;
|
||||||
|
continue;
|
||||||
|
case DOUBLE:
|
||||||
|
i++;
|
||||||
|
push.getItems().add(new DoubleItem(bytesToDouble(Arrays.copyOfRange(data, i, i+8))));
|
||||||
|
i += 8;
|
||||||
|
u += 9;
|
||||||
|
continue;
|
||||||
default:
|
default:
|
||||||
i++;
|
i++;
|
||||||
u++;
|
u++;
|
||||||
@ -182,6 +211,12 @@ public class FlashDecompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tag.getActions().add(push);
|
tag.getActions().add(push);
|
||||||
|
/*byte[] bv = Arrays.copyOfRange(data, start_action_index, i);
|
||||||
|
List<String> s = IntStream.range(0, bv.length)
|
||||||
|
.map(v -> bv[v])
|
||||||
|
.mapToObj(v -> Integer.toHexString(v))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
log.info("Push data block: {}", s);*/
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import java.io.File;
|
|||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
FlashDecompiler decompiler = new FlashDecompiler();
|
FlashDecompiler decompiler = new FlashDecompiler();
|
||||||
ShockwaveFile file = decompiler.loadFromFile(new File("D:\\Documents\\rtmpSpring\\static\\swf\\cache\\rus\\resources.swf"));
|
ShockwaveFile file = decompiler.loadFromFile(new File("D:\\Documents\\rtmpSpring\\static\\swf\\cache\\rus\\base[17].swf"));
|
||||||
|
|
||||||
DoAction da = (DoAction) file.getTags()
|
DoAction da = (DoAction) file.getTags()
|
||||||
.stream()
|
.stream()
|
||||||
@ -20,12 +20,10 @@ public class Main {
|
|||||||
.findFirst()
|
.findFirst()
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
Flash2Java converter = new Flash2Java();
|
|
||||||
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
File out = new File("dec.json");
|
File out = new File("dec.json");
|
||||||
if( out.exists() ) out.delete();
|
if( out.exists() ) out.delete();
|
||||||
objectMapper.writeValue(out, converter.convert(da));
|
objectMapper.writeValue(out, new Flash2Java(da).convert());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package com.alterdekim.flash.decompiler.action;
|
package com.alterdekim.flash.decompiler.action;
|
||||||
|
|
||||||
import com.alterdekim.flash.decompiler.util.ActionField;
|
import com.alterdekim.flash.decompiler.util.ActionField;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
public class ActionAdd extends ByteCodeAction {
|
public class ActionAdd extends ByteCodeAction {
|
||||||
@Override
|
@Override
|
||||||
public ActionField getType() {
|
public ActionField getType() {
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.alterdekim.flash.decompiler.action;
|
||||||
|
|
||||||
|
import com.alterdekim.flash.decompiler.util.ActionField;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ActionDefineLocal2 extends ByteCodeAction {
|
||||||
|
@Override
|
||||||
|
public ActionField getType() {
|
||||||
|
return ActionField.DefineLocal2;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.alterdekim.flash.decompiler.action;
|
||||||
|
|
||||||
|
import com.alterdekim.flash.decompiler.util.ActionField;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ActionGetMember extends ByteCodeAction {
|
||||||
|
@Override
|
||||||
|
public ActionField getType() {
|
||||||
|
return ActionField.GetMember;
|
||||||
|
}
|
||||||
|
}
|
@ -12,4 +12,6 @@ public class ActionInitObject extends ByteCodeAction {
|
|||||||
public ActionField getType() {
|
public ActionField getType() {
|
||||||
return ActionField.InitObject;
|
return ActionField.InitObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.alterdekim.flash.decompiler.action;
|
||||||
|
|
||||||
|
import com.alterdekim.flash.decompiler.util.ActionField;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ActionSetVariable extends ByteCodeAction {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionField getType() {
|
||||||
|
return ActionField.SetVariable;
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,12 @@ public enum ActionPushType {
|
|||||||
DOUBLE(6),
|
DOUBLE(6),
|
||||||
INTEGER(7),
|
INTEGER(7),
|
||||||
POOL_INDEX(8),
|
POOL_INDEX(8),
|
||||||
POOL_INDEX_BIG(9);
|
POOL_INDEX_BIG(9),
|
||||||
|
|
||||||
|
// these types are internal (used for decompiler's purposes)
|
||||||
|
// they are not exist
|
||||||
|
|
||||||
|
INIT_OBJECT(-1);
|
||||||
|
|
||||||
public final int type;
|
public final int type;
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.alterdekim.flash.decompiler.item;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class BooleanItem extends ByteCodeItem {
|
||||||
|
|
||||||
|
private Boolean val;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionPushType getType() {
|
||||||
|
return ActionPushType.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.alterdekim.flash.decompiler.item;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DoubleItem extends ByteCodeItem {
|
||||||
|
|
||||||
|
private Double val;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionPushType getType() {
|
||||||
|
return ActionPushType.DOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return this.val;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.alterdekim.flash.decompiler.item.internal;
|
||||||
|
|
||||||
|
import com.alterdekim.flash.decompiler.item.ActionPushType;
|
||||||
|
import com.alterdekim.flash.decompiler.item.ByteCodeItem;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class InitObjectItem extends ByteCodeItem {
|
||||||
|
|
||||||
|
private HashMap<String, Object> val;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionPushType getType() {
|
||||||
|
return ActionPushType.INIT_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return this.val;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
package com.alterdekim.flash.decompiler.translator;
|
package com.alterdekim.flash.decompiler.translator;
|
||||||
|
|
||||||
import com.alterdekim.flash.decompiler.action.ActionPush;
|
import com.alterdekim.flash.decompiler.action.ActionPush;
|
||||||
import com.alterdekim.flash.decompiler.item.ActionPushType;
|
import com.alterdekim.flash.decompiler.item.*;
|
||||||
import com.alterdekim.flash.decompiler.action.ByteCodeAction;
|
import com.alterdekim.flash.decompiler.action.ByteCodeAction;
|
||||||
import com.alterdekim.flash.decompiler.item.ByteCodeItem;
|
import com.alterdekim.flash.decompiler.item.internal.InitObjectItem;
|
||||||
import com.alterdekim.flash.decompiler.item.PoolIndexItem;
|
|
||||||
import com.alterdekim.flash.decompiler.item.StringItem;
|
|
||||||
import com.alterdekim.flash.decompiler.tag.DoAction;
|
import com.alterdekim.flash.decompiler.tag.DoAction;
|
||||||
import com.alterdekim.flash.decompiler.util.ActionField;
|
import com.alterdekim.flash.decompiler.util.ActionField;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -15,80 +13,119 @@ import java.util.*;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class Flash2Java {
|
public class Flash2Java {
|
||||||
|
|
||||||
private List<String> pool;
|
private final List<String> pool;
|
||||||
|
private final List<ByteCodeAction> actions;
|
||||||
|
private final Stack<ByteCodeItem> stack; // ByteCodeAction
|
||||||
|
private final Map<String, FlashVar> vars;
|
||||||
|
|
||||||
public Map<String, FlashVar> convert(DoAction doAction) {
|
public Flash2Java(DoAction doAction) {
|
||||||
this.pool = doAction.getActionPool();
|
this.pool = doAction.getActionPool();
|
||||||
List<ByteCodeAction> actions = doAction.getActions();
|
this.stack = new Stack<>();
|
||||||
|
this.actions = doAction.getActions();
|
||||||
|
this.vars = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
// convert stack from List<ByteCodeAction> to List<ByteCodeItem> and rewrite all code accordingly.
|
public Map<String, FlashVar> convert() {
|
||||||
List<ByteCodeAction> stack = new ArrayList<>();
|
// abolish the activeness of variable inside of an HashMap. Use stack instead.
|
||||||
Map<String, FlashVar> vars = new HashMap<>();
|
|
||||||
for (ByteCodeAction action : actions) {
|
for (ByteCodeAction action : actions) {
|
||||||
try {
|
// try {
|
||||||
|
//log.info("Action type: " + action.getType().toString());
|
||||||
switch (action.getType()) {
|
switch (action.getType()) {
|
||||||
case DefineLocal:
|
case DefineLocal:
|
||||||
defineLocal(vars, stack);
|
defineLocal();
|
||||||
stack.clear();
|
|
||||||
break;
|
break;
|
||||||
case GetVariable:
|
case GetVariable:
|
||||||
getVariable(vars, stack);
|
getVariable();
|
||||||
stack.clear();
|
|
||||||
break;
|
break;
|
||||||
case SetMember:
|
case SetMember:
|
||||||
setMember(vars, stack);
|
setMember();
|
||||||
stack.clear();
|
|
||||||
break;
|
break;
|
||||||
case Add:
|
case Add:
|
||||||
reduceViaAdder(stack);
|
reduceViaAdder();
|
||||||
|
break;
|
||||||
|
case InitObject:
|
||||||
|
initObject();
|
||||||
|
break;
|
||||||
|
case Push:
|
||||||
|
this.stack.addAll(((ActionPush) action).getItems());
|
||||||
|
break;
|
||||||
|
case SetVariable:
|
||||||
|
setVariable();
|
||||||
|
break;
|
||||||
|
case GetMember:
|
||||||
|
getMember();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
stack.add(action);
|
// ignore
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
//} catch (Exception e) {
|
||||||
|
//log.error(e.getMessage());
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
return vars;
|
return vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reduceViaAdder(List<ByteCodeAction> stack) {
|
private void initObject() {
|
||||||
|
Integer numberOfEntries = (Integer) this.stack.pop().getValue();
|
||||||
|
HashMap<String, Object> obj = new HashMap<>();
|
||||||
|
for( int i = 0; i < numberOfEntries; i++ ) {
|
||||||
|
Object val = valConverter( this.stack.pop() );
|
||||||
|
String key = (String) valConverter( this.stack.pop() );
|
||||||
|
obj.put(key, val);
|
||||||
|
}
|
||||||
|
this.stack.push(new InitObjectItem(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reduceViaAdder() {
|
||||||
|
/*
|
||||||
// get last 2 elements from stack
|
// get last 2 elements from stack
|
||||||
List<Integer> si = new ArrayList<>();
|
List<Integer> si = new ArrayList<>();
|
||||||
List<ByteCodeItem> g = new ArrayList<>();
|
List<ByteCodeItem> g = new ArrayList<>();
|
||||||
for( int i = stack.size()-1; i >= 0; i-- ) {
|
for( int i = this.stack.size()-1; i >= 0; i-- ) {
|
||||||
ByteCodeAction e = stack.get(i);
|
ByteCodeAction e = this.stack.get(i);
|
||||||
if( e.getType() != ActionField.Push ) continue;
|
if( e.getType() != ActionField.Push ) continue;
|
||||||
ActionPush push = (ActionPush) e;
|
ActionPush push = (ActionPush) e;
|
||||||
if( push.getItems().size() >= 2 ) {
|
if( push.getItems().size() >= 2 ) {
|
||||||
StringItem from = (StringItem) push.getItems().get(push.getItems().size()-1);
|
StringItem from = (StringItem) push.getItems().get(push.getItems().size()-1);
|
||||||
StringItem to = (StringItem) push.getItems().get(push.getItems().size()-2);
|
StringItem to = (StringItem) push.getItems().get(push.getItems().size()-2);
|
||||||
push.getItems().remove()
|
/*push.getItems().remove()
|
||||||
((String) to.getValue()) + ((String) from.getValue())
|
((String) to.getValue()) + ((String) from.getValue())*//*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getMember() {
|
||||||
|
Object val = this.stack.pop().getValue();
|
||||||
|
String name = (String) valConverter( this.stack.pop() );
|
||||||
|
log.info("SetMember: {}", name);
|
||||||
|
String key = this.vars.keySet().stream().filter(k -> this.vars.get(k).isActive()).findFirst().get();
|
||||||
|
HashMap<String, Object> g = (HashMap<String, Object>) this.vars.get(key).getVal();
|
||||||
|
g.put(name, val);
|
||||||
|
this.vars.put(key, new FlashVar(true, g));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMember(Map<String, FlashVar> vars, List<ByteCodeAction> stack) {
|
private boolean hasActiveVariable() {
|
||||||
String varKey = vars.keySet().stream().filter(k -> vars.get(k).isActive()).findFirst().get();
|
return this.vars.keySet().stream().anyMatch(k -> this.vars.get(k).isActive());
|
||||||
FlashVar varVal = vars.get(varKey);
|
}
|
||||||
ActionPush push = (ActionPush) stack.get(0);
|
|
||||||
if( stack.size() == 1 ) {
|
private String getActiveVarKey() {
|
||||||
Map<Integer, String> m = varVal.getVal() != null ? ((Map<Integer, String>) varVal.getVal()) : new HashMap<>();
|
return this.vars.keySet().stream().filter(k -> this.vars.get(k).isActive()).findFirst().get();
|
||||||
m.put((Integer) push.getItems().get(0).getValue(), fromPool((Integer) push.getItems().get(1).getValue()));
|
}
|
||||||
varVal.setVal(m);
|
|
||||||
vars.put(varKey, varVal);
|
private void setMember() {
|
||||||
|
ByteCodeItem val = this.stack.pop();
|
||||||
|
|
||||||
|
if( this.stack.isEmpty() && this.hasActiveVariable() ) {
|
||||||
|
String var = getActiveVarKey();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<Integer, Map<String, Object>> m = varVal.getVal() != null ? ((Map<Integer, Map<String, Object>>) varVal.getVal()) : new HashMap<>();
|
Integer index = (Integer) this.stack.pop().getValue();
|
||||||
Map<String, Object> v = new HashMap<>();
|
String var = this.vars.keySet().stream().filter(k -> this.vars.get(k).isActive()).findFirst().get();
|
||||||
for( int i = 1; i < push.getItems().size()-1; i+=2 ) {
|
Map<String, Object> m = (Map<String, Object>) this.vars.get(var).getVal();
|
||||||
v.put(fromPool((Integer) push.getItems().get(i).getValue()), valConverter(push.getItems().get(i+1)));
|
m.put(String.valueOf(index), val.getValue());
|
||||||
}
|
this.vars.put(var, new FlashVar(false, m)); // this may cause a bug (false in FlashVar arg)
|
||||||
m.put((Integer) push.getItems().get(0).getValue(), v);
|
|
||||||
varVal.setVal(m);
|
|
||||||
vars.put(varKey, varVal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object valConverter(ByteCodeItem item) {
|
private Object valConverter(ByteCodeItem item) {
|
||||||
@ -100,27 +137,31 @@ public class Flash2Java {
|
|||||||
return item.getValue();
|
return item.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getVariable(Map<String, FlashVar> vars, List<ByteCodeAction> stack) throws Exception {
|
private void setVariable() {
|
||||||
if (stack.size() != 1 ) { throw new Exception("Bad getVariable format"); }
|
Object val = this.stack.pop().getValue();
|
||||||
ActionPush push = (ActionPush) stack.get(0);
|
String variableName = (String) valConverter( this.stack.pop() );
|
||||||
PoolIndexItem pi = (PoolIndexItem) push.getItems().get(0);
|
vars.put(variableName, new FlashVar(false, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getVariable() {
|
||||||
|
String variableName = (String) valConverter( this.stack.pop() );
|
||||||
vars.keySet().forEach(k -> {
|
vars.keySet().forEach(k -> {
|
||||||
FlashVar fv = vars.get(k);
|
FlashVar fv = vars.get(k);
|
||||||
fv.setActive(false);
|
fv.setActive(false);
|
||||||
vars.put(k, fv);
|
vars.put(k, fv);
|
||||||
});
|
});
|
||||||
String key = fromPool((int) pi.getValue());
|
FlashVar v = vars.get(variableName);
|
||||||
FlashVar v = vars.get(key);
|
|
||||||
v.setActive(true);
|
v.setActive(true);
|
||||||
vars.put(key, v);
|
vars.put(variableName, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void defineLocal(Map<String, FlashVar> vars, List<ByteCodeAction> stack) throws Exception {
|
private void defineLocal() {
|
||||||
if (stack.size() != 2 || stack.get(1).getType() != ActionField.InitObject) { throw new Exception("Bad defineLocal format"); }
|
ByteCodeItem val = this.stack.pop();
|
||||||
ActionPush push = (ActionPush) stack.get(0);
|
String name = (String) valConverter( this.stack.pop() );
|
||||||
PoolIndexItem pi = (PoolIndexItem) push.getItems().get(0);
|
// todo: implement assignment ability (from one value to another)
|
||||||
// todo: implement assignment ability
|
vars.put(name,
|
||||||
vars.put(fromPool((Integer) pi.getValue()), new FlashVar());
|
new FlashVar(false, val.getValue())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String fromPool(int index) {
|
private String fromPool(int index) {
|
||||||
|
@ -5,8 +5,11 @@ public enum ActionField {
|
|||||||
Push((byte) 0x96),
|
Push((byte) 0x96),
|
||||||
InitObject((byte) 0x43),
|
InitObject((byte) 0x43),
|
||||||
DefineLocal((byte) 0x3C),
|
DefineLocal((byte) 0x3C),
|
||||||
|
DefineLocal2((byte) 0x41),
|
||||||
SetMember((byte)0x4F),
|
SetMember((byte)0x4F),
|
||||||
|
GetMember((byte) 0x4E),
|
||||||
GetVariable((byte) 0x1C),
|
GetVariable((byte) 0x1C),
|
||||||
|
SetVariable((byte) 0x1D),
|
||||||
Add((byte) 0x47),
|
Add((byte) 0x47),
|
||||||
Unknown((byte) 0x00);
|
Unknown((byte) 0x00);
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.alterdekim.flash.decompiler.util;
|
package com.alterdekim.flash.decompiler.util;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
public class ByteUtil {
|
public class ByteUtil {
|
||||||
public static int bytesToInt(byte[] bytes) {
|
public static int bytesToInt(byte[] bytes) {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
@ -16,4 +19,8 @@ public class ByteUtil {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double bytesToDouble(byte[] bytes) {
|
||||||
|
return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getDouble();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user