diff --git a/pom.xml b/pom.xml
index 1ef6c95..d7ea83a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,4 +54,16 @@
2.17.2
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 14
+ 14
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/flash/decompiler/Main.java b/src/main/java/com/alterdekim/flash/decompiler/Main.java
index 6afd01b..dd57da6 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/Main.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/Main.java
@@ -1,5 +1,6 @@
package com.alterdekim.flash.decompiler;
+import com.alterdekim.flash.decompiler.compiler.FlashCompiler;
import com.alterdekim.flash.decompiler.tag.DoAction;
import com.alterdekim.flash.decompiler.tag.TagType;
import com.alterdekim.flash.decompiler.translator.Flash2Java;
@@ -8,12 +9,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
@Slf4j
public class Main {
public static void main(String[] args) throws Exception {
FlashDecompiler decompiler = new FlashDecompiler();
- ShockwaveFile file = decompiler.loadFromFile(new File("D:\\Documents\\rtmpSpring\\static\\swf\\cache\\rus\\catalogs[18].swf")); //
+ ShockwaveFile file = decompiler.loadFromFile(new File("catalogs.swf")); // D:\Documents\FlashProjects\Untitled-2.swf
DoAction da = (DoAction) file.getTags()
.stream()
@@ -25,6 +29,7 @@ public class Main {
File out = new File("dec.json");
if( out.exists() ) out.delete();
//objectMapper.writeValue(out, new Flash2Java(da).convert());
- new Java2Flash().convert(new Flash2Java(da).convert());
+ var j2f = new Java2Flash().convert(new Flash2Java(da).convert());
+ Files.write(Path.of("./export1.swf"), new FlashCompiler(j2f).compile(), StandardOpenOption.CREATE);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/flash/decompiler/action/ActionConstantPool.java b/src/main/java/com/alterdekim/flash/decompiler/action/ActionConstantPool.java
new file mode 100644
index 0000000..67bd565
--- /dev/null
+++ b/src/main/java/com/alterdekim/flash/decompiler/action/ActionConstantPool.java
@@ -0,0 +1,20 @@
+package com.alterdekim.flash.decompiler.action;
+
+import com.alterdekim.flash.decompiler.util.ActionField;
+import lombok.*;
+
+import java.util.List;
+
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class ActionConstantPool extends ByteCodeAction {
+
+ private List pool;
+
+ @Override
+ public ActionField getType() {
+ return ActionField.ConstantPool;
+ }
+}
diff --git a/src/main/java/com/alterdekim/flash/decompiler/action/ActionPush.java b/src/main/java/com/alterdekim/flash/decompiler/action/ActionPush.java
index 37a7b7f..c9e0b3a 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/action/ActionPush.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/action/ActionPush.java
@@ -2,16 +2,14 @@ package com.alterdekim.flash.decompiler.action;
import com.alterdekim.flash.decompiler.util.ActionField;
import com.alterdekim.flash.decompiler.item.ByteCodeItem;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
+import lombok.*;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
+@AllArgsConstructor
@ToString
public class ActionPush extends ByteCodeAction {
diff --git a/src/main/java/com/alterdekim/flash/decompiler/compiler/CompileObject.java b/src/main/java/com/alterdekim/flash/decompiler/compiler/CompileObject.java
new file mode 100644
index 0000000..4e0821a
--- /dev/null
+++ b/src/main/java/com/alterdekim/flash/decompiler/compiler/CompileObject.java
@@ -0,0 +1,8 @@
+package com.alterdekim.flash.decompiler.compiler;
+
+import java.util.BitSet;
+import java.util.List;
+
+public interface CompileObject {
+ List compile();
+}
diff --git a/src/main/java/com/alterdekim/flash/decompiler/compiler/FlashCompiler.java b/src/main/java/com/alterdekim/flash/decompiler/compiler/FlashCompiler.java
new file mode 100644
index 0000000..c0e613e
--- /dev/null
+++ b/src/main/java/com/alterdekim/flash/decompiler/compiler/FlashCompiler.java
@@ -0,0 +1,40 @@
+package com.alterdekim.flash.decompiler.compiler;
+
+import com.alterdekim.flash.decompiler.tag.*;
+import com.alterdekim.flash.decompiler.translator.Java2Flash;
+import com.alterdekim.flash.decompiler.util.ByteUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Queue;
+import java.util.stream.Collectors;
+
+@RequiredArgsConstructor
+@Slf4j
+public class FlashCompiler {
+ private final Java2Flash pcode;
+
+ public byte[] compile() {
+ List data = new ArrayList<>();
+ data.addAll(List.of((byte) 0x46, (byte) 0x57, (byte) 0x53));
+ data.add((byte) 0x08); // swf version (8)
+ List d1 = new ArrayList<>();
+ d1.addAll(List.of((byte) 0x30, (byte) 0x0A, (byte) 0x00, (byte) 0xA0)); // rect
+ d1.addAll(List.of((byte) 0x00, (byte) 0x19)); // frameRate
+ d1.addAll(ByteUtil.intToBytes(1)); // frames Count
+ //List tags = List.of(new SetBackgroundColor(new byte[] {0,0,0}), new DoAction(pcode.getPool(), pcode.getActions()), new ShowFrame(), new End());
+ //d1.addAll(tags.stream().map(CompileObject::compile).flatMap(Collection::stream).collect(Collectors.toList()));
+ d1.addAll(new SetBackgroundColor(new byte[] {0,0,0}).compile());
+ d1.addAll(new DoAction(pcode.getPool(), pcode.getActions()).compile());
+ d1.addAll(new ShowFrame().compile());
+ d1.addAll(new End().compile());
+ // fileSize u32
+ log.info("fileSize u32: {}", d1.size());
+ data.addAll(ByteUtil.intToBytes32(d1.size()));
+ data.addAll(d1);
+ return ByteUtil.toPrimitive(data);
+ }
+}
diff --git a/src/main/java/com/alterdekim/flash/decompiler/item/BooleanItem.java b/src/main/java/com/alterdekim/flash/decompiler/item/BooleanItem.java
index da4d69f..72f1cdb 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/item/BooleanItem.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/item/BooleanItem.java
@@ -1,8 +1,10 @@
package com.alterdekim.flash.decompiler.item;
import lombok.AllArgsConstructor;
+import lombok.ToString;
@AllArgsConstructor
+@ToString
public class BooleanItem extends ByteCodeItem {
private Boolean val;
diff --git a/src/main/java/com/alterdekim/flash/decompiler/tag/DoAction.java b/src/main/java/com/alterdekim/flash/decompiler/tag/DoAction.java
index 9a1541a..5eb0d4e 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/tag/DoAction.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/tag/DoAction.java
@@ -1,18 +1,26 @@
package com.alterdekim.flash.decompiler.tag;
+import com.alterdekim.flash.decompiler.action.ActionConstantPool;
+import com.alterdekim.flash.decompiler.action.ActionPush;
import com.alterdekim.flash.decompiler.action.ByteCodeAction;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
+import com.alterdekim.flash.decompiler.compiler.CompileObject;
+import com.alterdekim.flash.decompiler.util.ActionField;
+import com.alterdekim.flash.decompiler.util.ByteUtil;
+import lombok.*;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collection;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
@NoArgsConstructor
@ToString
@Getter
@Setter
-public class DoAction extends ShockwaveTag {
+@AllArgsConstructor
+public class DoAction extends ShockwaveTag implements CompileObject {
private List actionPool;
private List actions;
@@ -21,4 +29,61 @@ public class DoAction extends ShockwaveTag {
public TagType getType() {
return TagType.DoAction;
}
+
+ @Override
+ public List compile() {
+ List bytes = new ArrayList<>();
+ this.actions.forEach(action -> {
+ bytes.add(action.getType().id);
+ switch(action.getType()) {
+ case Push:
+ ActionPush push = (ActionPush) action;
+ List data = new ArrayList<>();
+ push.getItems().forEach(item -> {
+ data.add((byte) item.getType().type);
+ switch (item.getType()) {
+ case STRING:
+ data.addAll(fromString((String) item.getValue()));
+ break;
+ case INTEGER:
+ data.addAll(ByteUtil.intToBytes32((Integer) item.getValue()));
+ break;
+ case POOL_INDEX:
+ Integer index = (Integer) item.getValue();
+ data.addAll(index < 256 ? ByteUtil.intToBytes8(index) : ByteUtil.intToBytes(index));
+ break;
+ case DOUBLE:
+ data.addAll(ByteUtil.doubleToBytes((Double) item.getValue()));
+ break;
+ case BOOLEAN:
+ data.add((byte) ((Boolean) item.getValue() ? 0x01 : 0x00));
+ break;
+ }
+ });
+ bytes.addAll(ByteUtil.intToBytes(data.size()));
+ bytes.addAll(data);
+ break;
+ case ConstantPool:
+ ActionConstantPool pool = (ActionConstantPool) action;
+ bytes.addAll(ByteUtil.intToBytes(pool.getPool().size())); // maybe there should also be u8 size of data
+ pool.getPool().forEach(s -> {
+ bytes.addAll(fromString(s));
+ });
+ break;
+ }
+ });
+ bytes.add((byte) 0x0);
+ int val = getType().getId() << 6;
+ val |= 63; // 265955
+ return Stream.of( ByteUtil.intToBytes(val), ByteUtil.intToBytes32(bytes.size()+6), bytes ).flatMap(Collection::stream).collect(Collectors.toList());
+ }
+
+ private List fromString(String s) {
+ List l = new ArrayList<>();
+ for( char c : s.toCharArray() ) {
+ l.add((byte) c);
+ }
+ l.add((byte) 0x0);
+ return l;
+ }
}
diff --git a/src/main/java/com/alterdekim/flash/decompiler/tag/End.java b/src/main/java/com/alterdekim/flash/decompiler/tag/End.java
new file mode 100644
index 0000000..08cfdb3
--- /dev/null
+++ b/src/main/java/com/alterdekim/flash/decompiler/tag/End.java
@@ -0,0 +1,22 @@
+package com.alterdekim.flash.decompiler.tag;
+
+import com.alterdekim.flash.decompiler.compiler.CompileObject;
+import com.alterdekim.flash.decompiler.util.ByteUtil;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+import java.util.List;
+
+@ToString
+@NoArgsConstructor
+public class End extends ShockwaveTag implements CompileObject {
+ @Override
+ public TagType getType() {
+ return TagType.End;
+ }
+
+ @Override
+ public List compile() {
+ return ByteUtil.fromPrimitive(new byte[] {0, 0});
+ }
+}
diff --git a/src/main/java/com/alterdekim/flash/decompiler/tag/SetBackgroundColor.java b/src/main/java/com/alterdekim/flash/decompiler/tag/SetBackgroundColor.java
new file mode 100644
index 0000000..71a968f
--- /dev/null
+++ b/src/main/java/com/alterdekim/flash/decompiler/tag/SetBackgroundColor.java
@@ -0,0 +1,35 @@
+package com.alterdekim.flash.decompiler.tag;
+
+import com.alterdekim.flash.decompiler.compiler.CompileObject;
+import com.alterdekim.flash.decompiler.util.ByteUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@ToString
+@Getter
+@AllArgsConstructor
+public class SetBackgroundColor extends ShockwaveTag implements CompileObject {
+
+ private byte[] backgroundColor;
+
+ @Override
+ public TagType getType() {
+ return TagType.SetBackgroundColor;
+ }
+
+ @Override
+ public List compile() {
+ int val = getType().getId() << 6;
+ val |= 3;
+ return Stream.of(ByteUtil.intToBytes(val), ByteUtil.fromPrimitive(backgroundColor)).flatMap(Collection::stream).collect(Collectors.toList());
+ }
+}
+
diff --git a/src/main/java/com/alterdekim/flash/decompiler/tag/ShowFrame.java b/src/main/java/com/alterdekim/flash/decompiler/tag/ShowFrame.java
new file mode 100644
index 0000000..4379096
--- /dev/null
+++ b/src/main/java/com/alterdekim/flash/decompiler/tag/ShowFrame.java
@@ -0,0 +1,25 @@
+package com.alterdekim.flash.decompiler.tag;
+
+import com.alterdekim.flash.decompiler.compiler.CompileObject;
+import com.alterdekim.flash.decompiler.util.ByteUtil;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+import java.util.BitSet;
+import java.util.List;
+import java.util.stream.Stream;
+
+@ToString
+@NoArgsConstructor
+public class ShowFrame extends ShockwaveTag implements CompileObject {
+ @Override
+ public TagType getType() {
+ return TagType.ShowFrame;
+ }
+
+ @Override
+ public List compile() {
+ int val = this.getType().getId() << 6;
+ return ByteUtil.intToBytes(val);
+ }
+}
diff --git a/src/main/java/com/alterdekim/flash/decompiler/tag/TagType.java b/src/main/java/com/alterdekim/flash/decompiler/tag/TagType.java
index 9a7f93e..592c60d 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/tag/TagType.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/tag/TagType.java
@@ -1,5 +1,8 @@
package com.alterdekim.flash.decompiler.tag;
+import lombok.Getter;
+
+@Getter
public enum TagType {
SetBackgroundColor(9),
DoAction(12),
diff --git a/src/main/java/com/alterdekim/flash/decompiler/translator/Flash2Java.java b/src/main/java/com/alterdekim/flash/decompiler/translator/Flash2Java.java
index a53ba61..dd2cb0c 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/translator/Flash2Java.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/translator/Flash2Java.java
@@ -131,7 +131,7 @@ public class Flash2Java {
m.put(index, this.vars.get(valToString(val)));
return;
}
- m.put(index, val.getValue());
+ m.put(index, valConverter(val));
return;
}
Map m = recursiveGet((ArrayDeque) varOrMember.getValue());
@@ -139,7 +139,7 @@ public class Flash2Java {
m.put(index, this.vars.get(valToString(val)));
return;
}
- m.put(index, val.getValue());
+ m.put(index, valConverter(val));
}
private Map recursiveGet(Deque l) {
@@ -169,7 +169,7 @@ public class Flash2Java {
}
private void setVariable() {
- Object val = this.stack.pop().getValue();
+ Object val = valConverter( this.stack.pop() );
String variableName = valToString( this.stack.pop() );
this.vars.put(variableName, val);
}
@@ -186,7 +186,7 @@ public class Flash2Java {
this.vars.put(name, this.vars.get(valToString(val)));
return;
}
- this.vars.put(name, val.getValue());
+ this.vars.put(name, valConverter(val));
}
private String fromPool(int index) {
diff --git a/src/main/java/com/alterdekim/flash/decompiler/translator/Java2Flash.java b/src/main/java/com/alterdekim/flash/decompiler/translator/Java2Flash.java
index 36c4296..cf41eb2 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/translator/Java2Flash.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/translator/Java2Flash.java
@@ -1,36 +1,115 @@
package com.alterdekim.flash.decompiler.translator;
-import com.alterdekim.flash.decompiler.action.ByteCodeAction;
+import com.alterdekim.flash.decompiler.action.*;
+import com.alterdekim.flash.decompiler.item.*;
+import com.alterdekim.flash.decompiler.item.internal.InitObjectItem;
+import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.compress.harmony.unpack200.bytecode.ByteCode;
import java.util.*;
@Slf4j
+@Getter
public class Java2Flash {
- private Set pool;
- public List convert(Map map) {
- this.pool = new HashSet<>(65535);
- extractAllStrings(map);
- log.info("poolSet: {}", this.pool);
- return new ArrayList<>();
+ private List pool;
+ private List actions;
+
+ public Java2Flash convert(Map map) {
+ this.actions = new ArrayList<>();
+ this.pool = new ArrayList<>();
+ this.pool.addAll(extractAllStrings(new HashSet<>(65535), map)); // maybe make a check if hashset size is bigger than initialCapacity
+ this.actions.add(new ActionConstantPool(this.pool));
+ map.keySet().forEach(k -> createVariable(map, k));
+ map.keySet().stream().filter(k -> map.get(k).getClass().getSimpleName().equals("HashMap")).forEach(k -> setMembers(map, k));
+ return this;
}
- private void extractAllStrings(Map map) {
+ private void setMembers(Map map, String key) {
+ HashMap m = (HashMap) map.get(key);
+ m.keySet().forEach(k -> {
+ this.actions.add(new ActionPush(Collections.singletonList(fromString(key))));
+ this.actions.add(new ActionGetVariable());
+ this.actions.add(new ActionPush(switch (m.get(k).getClass().getSimpleName()) {
+ case "String" -> List.of(fromString(k), fromString((String) m.get(k)));
+ case "Integer" -> List.of(fromString(k), new IntegerItem((Integer) m.get(k)));
+ case "Double" -> List.of(fromString(k), new DoubleItem((Double) m.get(k)));
+ case "Boolean" -> List.of(fromString(k), new BooleanItem((Boolean) m.get(k)));
+ default -> List.of(fromString(k));
+ }));
+ if( m.get(k).getClass().getSimpleName().equals("HashMap") ) {
+ HashMap s = (HashMap) m.get(k);
+ parseHashMapMember(s);
+ this.actions.add(new ActionPush(Collections.singletonList(new IntegerItem(s.keySet().size()))));
+ this.actions.add(new ActionInitObject());
+ }
+ this.actions.add(new ActionSetMember());
+ });
+ }
+
+ private void parseHashMapMember(Map m) {
+ m.keySet().forEach(key -> {
+ switch (m.get(key).getClass().getSimpleName()) {
+ case "String":
+ this.actions.add(new ActionPush(List.of(fromString(key), fromString((String) m.get(key)))));
+ break;
+ case "Integer":
+ this.actions.add(new ActionPush(List.of(fromString(key), new IntegerItem((Integer) m.get(key)))));
+ break;
+ case "Double":
+ this.actions.add(new ActionPush(List.of(fromString(key), new DoubleItem((Double) m.get(key)))));
+ break;
+ case "Boolean":
+ this.actions.add(new ActionPush(List.of(fromString(key), new BooleanItem((Boolean) m.get(key)))));
+ break;
+ case "HashMap":
+ HashMap s = (HashMap) m.get(key);
+ parseHashMapMember(s);
+ this.actions.add(new ActionPush(Collections.singletonList(new IntegerItem(s.keySet().size()))));
+ this.actions.add(new ActionInitObject());
+ break;
+ }
+ });
+ }
+
+ private void createVariable(Map map, String key) {
+ List items = new ArrayList<>();
+ items.add(fromString(key));
+ log.info("Type: {}", map.get(key).getClass().getSimpleName());
+ items.add(switch (map.get(key).getClass().getSimpleName()) {
+ case "String" -> fromString((String) map.get(key));
+ case "Integer" -> new IntegerItem((Integer) map.get(key));
+ case "Double" -> new DoubleItem((Double) map.get(key));
+ case "Boolean" -> new BooleanItem((Boolean) map.get(key));
+ default -> new IntegerItem(0);
+ });
+ this.actions.add(new ActionPush(items));
+ if( map.get(key).getClass().getSimpleName().equals("HashMap") ) {
+ this.actions.add(new ActionInitObject());
+ }
+ this.actions.add(new ActionDefineLocal());
+ }
+
+ private ByteCodeItem fromString(String s) {
+ int i = this.pool.indexOf(s);
+ return i != -1 ? new PoolIndexItem(i) : new StringItem(s);
+ }
+
+ private Set extractAllStrings(Set pool, Map map) {
map.keySet().forEach(k -> {
- if(k.matches("[^0-9].+")) {
+ try {
+ Integer.parseInt(k);
+ } catch (Exception e) {
pool.add(k);
}
});
map.values().forEach(o -> {
- switch( o.getClass().getSimpleName() ) {
- case "HashMap":
- extractAllStrings((HashMap) o);
- break;
- case "String":
- pool.add((String) o);
- break;
+ switch (o.getClass().getSimpleName()) {
+ case "HashMap" -> extractAllStrings(pool, (HashMap) o);
+ case "String" -> pool.add((String) o);
}
});
+ return pool;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/alterdekim/flash/decompiler/util/ByteUtil.java b/src/main/java/com/alterdekim/flash/decompiler/util/ByteUtil.java
index 7d96696..b3c4e52 100644
--- a/src/main/java/com/alterdekim/flash/decompiler/util/ByteUtil.java
+++ b/src/main/java/com/alterdekim/flash/decompiler/util/ByteUtil.java
@@ -5,6 +5,9 @@ import lombok.extern.slf4j.Slf4j;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
@Slf4j
public class ByteUtil {
@@ -24,6 +27,36 @@ public class ByteUtil {
return value;
}
+ private static byte[] int2bytes(int val, int len) {
+ byte[] r = new byte[len];
+ for( int i = 0; i < len; i++ ) {
+ r[i] = (byte) ( (val >> 8*i) & 0xFF );
+ }
+ return r;
+ }
+
+ public static List intToBytes(int i) {
+ return fromPrimitive(int2bytes(i, 2));
+ }
+
+ public static List intToBytes8(int i) {
+ return fromPrimitive(int2bytes(i, 1));
+ }
+
+ public static List intToBytes32(int i) {
+ return fromPrimitive(int2bytes(i, 4));
+ }
+
+ public static List fromPrimitive(byte[] b) {
+ return IntStream.range(0, b.length).boxed().map(i -> b[i]).collect(Collectors.toList());
+ }
+
+ public static byte[] toPrimitive(List b) {
+ byte[] a = new byte[b.size()];
+ IntStream.range(0, b.size()).boxed().forEach(i -> a[i] = b.get(i));
+ return a;
+ }
+
public static double bytesToDouble(byte[] bytes) {
byte[] b1 = new byte[8];
for( int i = bytes.length-1, u = 0; i >= 0; i--, u++ ) {
@@ -34,4 +67,12 @@ public class ByteUtil {
System.arraycopy(Arrays.copyOfRange(b1, 0, 4), 0, d, 4, 4);
return ByteBuffer.wrap(d).order(ByteOrder.BIG_ENDIAN).getDouble();
}
+
+ public static List doubleToBytes(double d) {
+ byte[] b = ByteBuffer.allocate(8).putDouble(d).array();
+ byte[] b1 = new byte[8];
+ System.arraycopy(b, 0, b1, 4, 4);
+ System.arraycopy(b, 4, b1, 0, 4);
+ return fromPrimitive(b1);
+ }
}