mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-05 00:45:50 +00:00
Multi thread AS search
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.types.ConvertData;
|
||||
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.cache.ScriptDecompiledListener;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedText;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DecompilerPool {
|
||||
|
||||
private final ThreadPoolExecutor executor;
|
||||
|
||||
public DecompilerPool() {
|
||||
int threadCount = Configuration.getParallelThreadCount();
|
||||
executor = new ThreadPoolExecutor(threadCount, threadCount,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>());
|
||||
}
|
||||
|
||||
public Future<HighlightedText> submitTask(ASMSource src, ActionList actions, ScriptDecompiledListener<HighlightedText> listener) {
|
||||
Future<HighlightedText> f = executor.submit(new Callable<HighlightedText>() {
|
||||
@Override
|
||||
public HighlightedText call() throws Exception {
|
||||
Thread.sleep(10000);
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true);
|
||||
writer.startFunction("!script");
|
||||
src.getActionScriptSource(writer, actions);
|
||||
writer.endFunction();
|
||||
|
||||
HighlightedText result = new HighlightedText(writer);
|
||||
SWF swf = src.getSwf();
|
||||
if (swf != null) {
|
||||
swf.as2Cache.put(src, result);
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.onComplete(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public Future<HighlightedText> submitTask(ScriptPack pack, ScriptDecompiledListener<HighlightedText> listener) {
|
||||
Future<HighlightedText> f = executor.submit(new Callable<HighlightedText>() {
|
||||
@Override
|
||||
public HighlightedText call() throws Exception {
|
||||
int scriptIndex = pack.scriptIndex;
|
||||
ScriptInfo script = null;
|
||||
if (scriptIndex > -1) {
|
||||
script = pack.abc.script_info.get(scriptIndex);
|
||||
}
|
||||
boolean parallel = Configuration.parallelSpeedUp.get();
|
||||
Thread.sleep(10000);
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true);
|
||||
pack.toSource(writer, script == null ? null : script.traits.traits, new ConvertData(), ScriptExportMode.AS, parallel);
|
||||
|
||||
HighlightedText result = new HighlightedText(writer);
|
||||
SWF swf = pack.getSwf();
|
||||
if (swf != null) {
|
||||
swf.as3Cache.put(pack, result);
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener.onComplete(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public String getStat() {
|
||||
return "core: " + executor.getCorePoolSize()
|
||||
+ " size: " + executor.getPoolSize()
|
||||
+ " largest: " + executor.getLargestPoolSize()
|
||||
+ " max: " + executor.getMaximumPoolSize()
|
||||
+ " active: " + executor.getActiveCount()
|
||||
+ " count: " + executor.getTaskCount()
|
||||
+ " completed: " + executor.getCompletedTaskCount();
|
||||
}
|
||||
|
||||
public HighlightedText decompile(ASMSource src, ActionList actions) throws InterruptedException {
|
||||
Future<HighlightedText> future = submitTask(src, actions, null);
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException ex) {
|
||||
future.cancel(true);
|
||||
throw ex;
|
||||
} catch (ExecutionException ex) {
|
||||
Logger.getLogger(DecompilerPool.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HighlightedText decompile(ScriptPack pack) throws InterruptedException {
|
||||
Future<HighlightedText> future = submitTask(pack, null);
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException ex) {
|
||||
future.cancel(true);
|
||||
throw ex;
|
||||
} catch (ExecutionException ex) {
|
||||
Logger.getLogger(DecompilerPool.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void shutdown() throws InterruptedException {
|
||||
executor.shutdown();
|
||||
if (!executor.awaitTermination(100, TimeUnit.SECONDS)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,10 @@ public class RetryTask {
|
||||
} catch (InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
if (handler == null) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
switch (handler.handle(ex)) {
|
||||
case AbortRetryIgnoreHandler.ABORT:
|
||||
throw ex;
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.ConvertData;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
|
||||
@@ -70,6 +69,9 @@ import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionNewObject;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionSetMember;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2;
|
||||
import com.jpexs.decompiler.flash.cache.AS2Cache;
|
||||
import com.jpexs.decompiler.flash.cache.AS3Cache;
|
||||
import com.jpexs.decompiler.flash.cache.ScriptDecompiledListener;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode;
|
||||
@@ -156,6 +158,7 @@ import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Cache;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.ImmediateFuture;
|
||||
import com.jpexs.helpers.NulStream;
|
||||
import com.jpexs.helpers.ProgressListener;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
@@ -187,6 +190,7 @@ import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
@@ -338,13 +342,12 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
private final Cache<SoundTag, byte[]> soundCache = Cache.getInstance(false, false, "sound");
|
||||
|
||||
@Internal
|
||||
private final Cache<ASMSource, ActionList> as2PcodeCache = Cache.getInstance(true, true, "as2pcode");
|
||||
public final AS2Cache as2Cache = new AS2Cache();
|
||||
|
||||
@Internal
|
||||
private final Cache<ASMSource, HighlightedText> as2Cache = Cache.getInstance(true, false, "as2");
|
||||
public final AS3Cache as3Cache = new AS3Cache();
|
||||
|
||||
@Internal
|
||||
private final Cache<ScriptPack, HighlightedText> as3Cache = Cache.getInstance(true, false, "as3");
|
||||
private static final DecompilerPool decompilerPool = new DecompilerPool();
|
||||
|
||||
public static List<String> swfSignatures = Arrays.asList(
|
||||
"FWS", // Uncompressed Flash
|
||||
@@ -395,7 +398,6 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
swfList.swfs.clear();
|
||||
}
|
||||
|
||||
as2PcodeCache.clear();
|
||||
as2Cache.clear();
|
||||
as3Cache.clear();
|
||||
frameCache.clear();
|
||||
@@ -2543,7 +2545,6 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public void clearScriptCache() {
|
||||
as2PcodeCache.clear();
|
||||
as2Cache.clear();
|
||||
as3Cache.clear();
|
||||
IdentifiersDeobfuscation.clearCache();
|
||||
@@ -2582,31 +2583,71 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
public static void uncache(ASMSource src) {
|
||||
if (src != null) {
|
||||
SWF swf = src.getSwf();
|
||||
swf.as2Cache.remove(src);
|
||||
swf.as2PcodeCache.remove(src);
|
||||
if (swf != null) {
|
||||
swf.as2Cache.remove(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void uncache(ScriptPack pack) {
|
||||
if (pack != null) {
|
||||
pack.getSwf().as3Cache.remove(pack);
|
||||
SWF swf = pack.getSwf();
|
||||
if (swf != null) {
|
||||
swf.as3Cache.remove(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCached(ASMSource src) {
|
||||
return src.getSwf().as2Cache.contains(src);
|
||||
if (src != null) {
|
||||
SWF swf = src.getSwf();
|
||||
if (swf != null) {
|
||||
return swf.as2Cache.isCached(src);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isCached(ScriptPack pack) {
|
||||
return pack.getSwf().as3Cache.contains(pack);
|
||||
if (pack != null) {
|
||||
SWF swf = pack.getSwf();
|
||||
if (swf != null) {
|
||||
return swf.as3Cache.isCached(pack);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static HighlightedText getFromCache(ASMSource src) {
|
||||
if (src != null) {
|
||||
SWF swf = src.getSwf();
|
||||
if (swf != null) {
|
||||
return swf.as2Cache.get(src);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HighlightedText getFromCache(ScriptPack pack) {
|
||||
if (pack != null) {
|
||||
SWF swf = pack.getSwf();
|
||||
if (swf != null) {
|
||||
return swf.as3Cache.get(pack);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ActionList getCachedActionList(ASMSource src, final List<DisassemblyListener> listeners) throws InterruptedException {
|
||||
synchronized (src) {
|
||||
SWF swf = src.getSwf();
|
||||
int deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0;
|
||||
if (swf != null && swf.as2PcodeCache.contains(src)) {
|
||||
ActionList result = swf.as2PcodeCache.get(src);
|
||||
if (swf != null && swf.as2Cache.isPcodeCached(src)) {
|
||||
ActionList result = swf.as2Cache.getPcode(src);
|
||||
if (result.deobfuscationMode == deobfuscationMode) {
|
||||
return result;
|
||||
}
|
||||
@@ -2625,7 +2666,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
list.fileData = actionBytes.getArray();
|
||||
list.deobfuscationMode = deobfuscationMode;
|
||||
if (swf != null) {
|
||||
swf.as2PcodeCache.put(src, list);
|
||||
swf.as2Cache.put(src, list);
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -2638,49 +2679,68 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
public static HighlightedText getFromCache(ASMSource src) {
|
||||
SWF swf = src.getSwf();
|
||||
if (swf.as2Cache.contains(src)) {
|
||||
return swf.as2Cache.get(src);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HighlightedText getCached(ASMSource src, ActionList actions) throws InterruptedException {
|
||||
SWF swf = src.getSwf();
|
||||
if (swf.as2Cache.contains(src)) {
|
||||
return swf.as2Cache.get(src);
|
||||
HighlightedText res;
|
||||
if (swf != null) {
|
||||
res = swf.as2Cache.get(src);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true);
|
||||
writer.startFunction("!script");
|
||||
src.getActionScriptSource(writer, actions);
|
||||
writer.endFunction();
|
||||
|
||||
HighlightedText res = new HighlightedText(writer);
|
||||
swf.as2Cache.put(src, res);
|
||||
return res;
|
||||
return decompilerPool.decompile(src, actions);
|
||||
}
|
||||
|
||||
public static HighlightedText getCached(ScriptPack pack) throws InterruptedException {
|
||||
SWF swf = pack.getSwf();
|
||||
if (swf.as3Cache.contains(pack)) {
|
||||
return swf.as3Cache.get(pack);
|
||||
HighlightedText res;
|
||||
if (swf != null) {
|
||||
res = swf.as3Cache.get(pack);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
int scriptIndex = pack.scriptIndex;
|
||||
ScriptInfo script = null;
|
||||
if (scriptIndex > -1) {
|
||||
script = pack.abc.script_info.get(scriptIndex);
|
||||
}
|
||||
boolean parallel = Configuration.parallelSpeedUp.get();
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true);
|
||||
pack.toSource(writer, script == null ? null : script.traits.traits, new ConvertData(), ScriptExportMode.AS, parallel);
|
||||
HighlightedText res = new HighlightedText(writer);
|
||||
swf.as3Cache.put(pack, res);
|
||||
return decompilerPool.decompile(pack);
|
||||
}
|
||||
|
||||
return res;
|
||||
public static Future<HighlightedText> getCachedFuture(ASMSource src, ActionList actions, ScriptDecompiledListener<HighlightedText> listener) throws InterruptedException {
|
||||
SWF swf = src.getSwf();
|
||||
HighlightedText res;
|
||||
if (swf != null) {
|
||||
res = swf.as2Cache.get(src);
|
||||
if (res != null) {
|
||||
if (listener != null) {
|
||||
listener.onComplete(res);
|
||||
}
|
||||
|
||||
return new ImmediateFuture<>(res);
|
||||
}
|
||||
}
|
||||
|
||||
return decompilerPool.submitTask(src, actions, listener);
|
||||
}
|
||||
|
||||
public static Future<HighlightedText> getCachedFuture(ScriptPack pack, ScriptDecompiledListener<HighlightedText> listener) throws InterruptedException {
|
||||
SWF swf = pack.getSwf();
|
||||
HighlightedText res;
|
||||
if (swf != null) {
|
||||
res = swf.as3Cache.get(pack);
|
||||
if (res != null) {
|
||||
if (listener != null) {
|
||||
listener.onComplete(res);
|
||||
}
|
||||
|
||||
return new ImmediateFuture<>(res);
|
||||
}
|
||||
}
|
||||
|
||||
return decompilerPool.submitTask(pack, listener);
|
||||
}
|
||||
|
||||
public DecompilerPool getDecompilerPool() {
|
||||
return decompilerPool;
|
||||
}
|
||||
|
||||
public Cache<CharacterTag, RECT> getRectCache() {
|
||||
@@ -2898,7 +2958,8 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
timelined.setModified(true);
|
||||
timelined.resetTimeline();
|
||||
} else // timeline should be always the swf here
|
||||
if (removeDependencies) {
|
||||
{
|
||||
if (removeDependencies) {
|
||||
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
|
||||
timelined.setModified(true);
|
||||
} else {
|
||||
@@ -2907,6 +2968,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
timelined.setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
69
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/AS2Cache.java
vendored
Normal file
69
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/AS2Cache.java
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.cache;
|
||||
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedText;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.helpers.Cache;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS2Cache {
|
||||
|
||||
private final Cache<ASMSource, HighlightedText> cache = Cache.getInstance(true, false, "as2");
|
||||
|
||||
private final Cache<ASMSource, ActionList> pcodeCache = Cache.getInstance(true, true, "as2pcode");
|
||||
|
||||
public void clear() {
|
||||
pcodeCache.clear();
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public boolean isCached(ASMSource src) {
|
||||
return cache.contains(src);
|
||||
}
|
||||
|
||||
public boolean isPcodeCached(ASMSource src) {
|
||||
return pcodeCache.contains(src);
|
||||
}
|
||||
|
||||
public HighlightedText get(ASMSource src) {
|
||||
return cache.get(src);
|
||||
}
|
||||
|
||||
public ActionList getPcode(ASMSource src) {
|
||||
return pcodeCache.get(src);
|
||||
}
|
||||
|
||||
public void put(ASMSource src, HighlightedText text) {
|
||||
cache.put(src, text);
|
||||
}
|
||||
|
||||
public void put(ASMSource src, ActionList actionList) {
|
||||
pcodeCache.put(src, actionList);
|
||||
}
|
||||
|
||||
public void remove(ASMSource src) {
|
||||
if (src != null) {
|
||||
cache.remove(src);
|
||||
pcodeCache.remove(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/AS3Cache.java
vendored
Normal file
52
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/AS3Cache.java
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.cache;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedText;
|
||||
import com.jpexs.helpers.Cache;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS3Cache {
|
||||
|
||||
private final Cache<ScriptPack, HighlightedText> cache = Cache.getInstance(true, false, "as3");
|
||||
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public boolean isCached(ScriptPack pack) {
|
||||
return cache.contains(pack);
|
||||
}
|
||||
|
||||
public HighlightedText get(ScriptPack pack) {
|
||||
return cache.get(pack);
|
||||
}
|
||||
|
||||
public void put(ScriptPack pack, HighlightedText text) {
|
||||
cache.put(pack, text);
|
||||
}
|
||||
|
||||
public void remove(ScriptPack pack) {
|
||||
if (pack != null) {
|
||||
cache.remove(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/ScriptDecompiledListener.java
vendored
Normal file
27
libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/ScriptDecompiledListener.java
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.cache;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ScriptDecompiledListener<T> {
|
||||
|
||||
public void onComplete(T result);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ import javax.swing.JOptionPane;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Configuration {
|
||||
public final class Configuration {
|
||||
|
||||
private static final String CONFIG_NAME = "config.bin";
|
||||
|
||||
@@ -83,7 +83,7 @@ public class Configuration {
|
||||
|
||||
@ConfigurationDefaultInt(10)
|
||||
@ConfigurationCategory("decompilation")
|
||||
public static final ConfigurationItem<Integer> parallelSpeedUpThreadCount = null;
|
||||
private static final ConfigurationItem<Integer> parallelSpeedUpThreadCount = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("script")
|
||||
@@ -926,7 +926,7 @@ public class Configuration {
|
||||
}
|
||||
|
||||
public static Map<String, Field> getConfigurationFields() {
|
||||
Field[] fields = Configuration.class.getFields();
|
||||
Field[] fields = Configuration.class.getDeclaredFields();
|
||||
Map<String, Field> result = new HashMap<>();
|
||||
for (Field field : fields) {
|
||||
if (ConfigurationItem.class.isAssignableFrom(field.getType())) {
|
||||
|
||||
@@ -1,244 +1,243 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*
|
||||
* Based of works of somebody called eternity.
|
||||
*
|
||||
*/
|
||||
public class IggyFile implements StructureInterface {
|
||||
|
||||
final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName());
|
||||
|
||||
private File originalFile;
|
||||
private IggyHeader header;
|
||||
private List<IggySubFileEntry> subFileEntries = new ArrayList<>();
|
||||
private List<byte[]> subFileEntriesData = new ArrayList<>();
|
||||
|
||||
private IggySwf iggySwf;
|
||||
|
||||
public static final int FIRST_TAG_POSITION = 3;
|
||||
|
||||
public IggySwf getSwf() {
|
||||
return iggySwf;
|
||||
}
|
||||
|
||||
public IggyFile(String filePath) throws IOException {
|
||||
this(new File(filePath));
|
||||
}
|
||||
|
||||
public IggyFile(File file) throws IOException {
|
||||
this.originalFile = file;
|
||||
try (ReadDataStreamInterface stream = new RandomAccessFileDataStream(file)) {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public File getOriginalFile() {
|
||||
return originalFile;
|
||||
}
|
||||
|
||||
public IggyHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public IggySubFileEntry getSubFileEntry(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntries.get(entryIndex);
|
||||
}
|
||||
|
||||
public int getNumEntries() {
|
||||
return subFileEntries.size();
|
||||
}
|
||||
|
||||
public byte[] getEntryData(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntriesData.get(entryIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[IggyFile:").append("\r\n");
|
||||
sb.append(header).append("\r\n");
|
||||
sb.append("Entries:").append("\r\n");
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
sb.append(entry).append("\r\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void extractIggyFile(File iggyFile, File extractDir) throws IOException {
|
||||
final String FILENAME_FORMAT = "index%d_type%d.bin";
|
||||
IggyFile ir = new IggyFile(iggyFile);
|
||||
for (int i = 0; i < ir.getNumEntries(); i++) {
|
||||
IggySubFileEntry entry = ir.getSubFileEntry(i);
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(extractDir, String.format(FILENAME_FORMAT, i, entry.type)))) {
|
||||
fos.write(ir.getEntryData(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getSwfName() {
|
||||
return iggySwf.getName();
|
||||
}
|
||||
|
||||
public long getSwfXMin() {
|
||||
return iggySwf.getHdr().getXMin();
|
||||
}
|
||||
|
||||
public long getSwfYMin() {
|
||||
return iggySwf.getHdr().getYMin();
|
||||
}
|
||||
|
||||
public long getSwfXMax() {
|
||||
return iggySwf.getHdr().getXMax();
|
||||
}
|
||||
|
||||
public long getSwfYMax() {
|
||||
return iggySwf.getHdr().getYMax();
|
||||
}
|
||||
|
||||
public float getSwfFrameRate() {
|
||||
return iggySwf.getHdr().getFrameRate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes entries of type INDEX.There can be more than one INDEX,
|
||||
* continuous. This removes all ot them.
|
||||
*/
|
||||
public void removeIndexEntries() {
|
||||
long offsetsChange = 0;
|
||||
final int ENTRY_SIZE = 16;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
offsetsChange = offsetsChange - entry.size - ENTRY_SIZE;
|
||||
subFileEntriesData.remove(i);
|
||||
subFileEntries.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateFlashEntry() throws IOException {
|
||||
|
||||
byte replacementData[];
|
||||
byte replacementIndexData[];
|
||||
IggyIndexBuilder ib = new IggyIndexBuilder();
|
||||
try (DataStreamInterface stream = new TemporaryDataStream()) {
|
||||
stream.setIndexing(ib);
|
||||
iggySwf.writeToDataStream(stream);
|
||||
replacementData = stream.getAllBytes();
|
||||
replacementIndexData = ib.getIndexBytes();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(IggyFile.class.getName()).log(Level.SEVERE, "Error during updating SWF", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
long offsetsChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
long oldSize = entry.size;
|
||||
long newSize = replacementData.length;
|
||||
entry.size = newSize;
|
||||
entry.size2 = newSize;
|
||||
offsetsChange = offsetsChange + (newSize - oldSize); //entries after this one will have modified offsets
|
||||
subFileEntriesData.set(i, replacementData);
|
||||
}
|
||||
}
|
||||
|
||||
removeIndexEntries();
|
||||
IggySubFileEntry indexEntry = new IggySubFileEntry(IggySubFileEntry.TYPE_INDEX, replacementIndexData.length, replacementIndexData.length, 0 /*offset will be set automatically*/);
|
||||
subFileEntries.add(indexEntry);
|
||||
subFileEntriesData.add(replacementIndexData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseEntries() throws IOException {
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
iggySwf = new IggySwf(new TemporaryDataStream(getEntryData(i)));
|
||||
break;
|
||||
}
|
||||
/*if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
IggyIndexParser.parseIndex(true, new TemporaryDataStream(getEntryData(i)), new ArrayList<>(), new ArrayList<>());
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
|
||||
header = new IggyHeader(stream);
|
||||
if (!header.is64()) {
|
||||
throw new IOException("32 bit iggy files are not (yet) supported, sorry");
|
||||
}
|
||||
for (int i = 0; i < header.getNumSubfiles(); i++) {
|
||||
subFileEntries.add(new IggySubFileEntry(stream));
|
||||
}
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
stream.seek(entry.offset, SeekMode.SET);
|
||||
byte[] entryData = stream.readBytes((int) entry.size);
|
||||
subFileEntriesData.add(entryData);
|
||||
}
|
||||
parseEntries();
|
||||
}
|
||||
|
||||
public void saveChanges() throws IOException {
|
||||
updateFlashEntry();
|
||||
try (RandomAccessFileDataStream raf = new RandomAccessFileDataStream(originalFile)) {
|
||||
writeToDataStream(raf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
header.writeToDataStream(stream);
|
||||
|
||||
long startOffset = IggyHeader.STRUCT_SIZE + IggySubFileEntry.STRUCTURE_SIZE * subFileEntries.size();
|
||||
long currentOffset = startOffset;
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset = currentOffset;
|
||||
currentOffset += entry.size;
|
||||
entry.writeToDataStream(stream);
|
||||
}
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
byte[] entryData = subFileEntriesData.get(i);
|
||||
stream.writeBytes(entryData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.RandomAccessFileDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*
|
||||
* Based of works of somebody called eternity.
|
||||
*
|
||||
*/
|
||||
public class IggyFile implements StructureInterface {
|
||||
|
||||
final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName());
|
||||
|
||||
private File originalFile;
|
||||
|
||||
private IggyHeader header;
|
||||
|
||||
private List<IggySubFileEntry> subFileEntries = new ArrayList<>();
|
||||
|
||||
private List<byte[]> subFileEntriesData = new ArrayList<>();
|
||||
|
||||
private IggySwf iggySwf;
|
||||
|
||||
public static final int FIRST_TAG_POSITION = 3;
|
||||
|
||||
public IggySwf getSwf() {
|
||||
return iggySwf;
|
||||
}
|
||||
|
||||
public IggyFile(String filePath) throws IOException {
|
||||
this(new File(filePath));
|
||||
}
|
||||
|
||||
public IggyFile(File file) throws IOException {
|
||||
this.originalFile = file;
|
||||
try (ReadDataStreamInterface stream = new RandomAccessFileDataStream(file)) {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public File getOriginalFile() {
|
||||
return originalFile;
|
||||
}
|
||||
|
||||
public IggyHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public IggySubFileEntry getSubFileEntry(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntries.get(entryIndex);
|
||||
}
|
||||
|
||||
public int getNumEntries() {
|
||||
return subFileEntries.size();
|
||||
}
|
||||
|
||||
public byte[] getEntryData(int entryIndex) {
|
||||
if (entryIndex < 0 || entryIndex >= subFileEntries.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No entry with index " + entryIndex + " exists");
|
||||
}
|
||||
return subFileEntriesData.get(entryIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[IggyFile:").append("\r\n");
|
||||
sb.append(header).append("\r\n");
|
||||
sb.append("Entries:").append("\r\n");
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
sb.append(entry).append("\r\n");
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void extractIggyFile(File iggyFile, File extractDir) throws IOException {
|
||||
final String FILENAME_FORMAT = "index%d_type%d.bin";
|
||||
IggyFile ir = new IggyFile(iggyFile);
|
||||
for (int i = 0; i < ir.getNumEntries(); i++) {
|
||||
IggySubFileEntry entry = ir.getSubFileEntry(i);
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(extractDir, String.format(FILENAME_FORMAT, i, entry.type)))) {
|
||||
fos.write(ir.getEntryData(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getSwfName() {
|
||||
return iggySwf.getName();
|
||||
}
|
||||
|
||||
public long getSwfXMin() {
|
||||
return iggySwf.getHdr().getXMin();
|
||||
}
|
||||
|
||||
public long getSwfYMin() {
|
||||
return iggySwf.getHdr().getYMin();
|
||||
}
|
||||
|
||||
public long getSwfXMax() {
|
||||
return iggySwf.getHdr().getXMax();
|
||||
}
|
||||
|
||||
public long getSwfYMax() {
|
||||
return iggySwf.getHdr().getYMax();
|
||||
}
|
||||
|
||||
public float getSwfFrameRate() {
|
||||
return iggySwf.getHdr().getFrameRate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes entries of type INDEX.There can be more than one INDEX,
|
||||
* continuous. This removes all ot them.
|
||||
*/
|
||||
public void removeIndexEntries() {
|
||||
long offsetsChange = 0;
|
||||
final int ENTRY_SIZE = 16;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
offsetsChange = offsetsChange - entry.size - ENTRY_SIZE;
|
||||
subFileEntriesData.remove(i);
|
||||
subFileEntries.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateFlashEntry() throws IOException {
|
||||
|
||||
byte replacementData[];
|
||||
byte replacementIndexData[];
|
||||
IggyIndexBuilder ib = new IggyIndexBuilder();
|
||||
try (DataStreamInterface stream = new TemporaryDataStream()) {
|
||||
stream.setIndexing(ib);
|
||||
iggySwf.writeToDataStream(stream);
|
||||
replacementData = stream.getAllBytes();
|
||||
replacementIndexData = ib.getIndexBytes();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(IggyFile.class.getName()).log(Level.SEVERE, "Error during updating SWF", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
long offsetsChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
long oldSize = entry.size;
|
||||
long newSize = replacementData.length;
|
||||
entry.size = newSize;
|
||||
entry.size2 = newSize;
|
||||
offsetsChange = offsetsChange + (newSize - oldSize); //entries after this one will have modified offsets
|
||||
subFileEntriesData.set(i, replacementData);
|
||||
}
|
||||
}
|
||||
|
||||
removeIndexEntries();
|
||||
IggySubFileEntry indexEntry = new IggySubFileEntry(IggySubFileEntry.TYPE_INDEX, replacementIndexData.length, replacementIndexData.length, 0 /*offset will be set automatically*/);
|
||||
subFileEntries.add(indexEntry);
|
||||
subFileEntriesData.add(replacementIndexData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseEntries() throws IOException {
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
iggySwf = new IggySwf(new TemporaryDataStream(getEntryData(i)));
|
||||
break;
|
||||
}
|
||||
/*if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
IggyIndexParser.parseIndex(true, new TemporaryDataStream(getEntryData(i)), new ArrayList<>(), new ArrayList<>());
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
|
||||
header = new IggyHeader(stream);
|
||||
if (!header.is64()) {
|
||||
throw new IOException("32 bit iggy files are not (yet) supported, sorry");
|
||||
}
|
||||
for (int i = 0; i < header.getNumSubfiles(); i++) {
|
||||
subFileEntries.add(new IggySubFileEntry(stream));
|
||||
}
|
||||
for (IggySubFileEntry entry : subFileEntries) {
|
||||
stream.seek(entry.offset, SeekMode.SET);
|
||||
byte[] entryData = stream.readBytes((int) entry.size);
|
||||
subFileEntriesData.add(entryData);
|
||||
}
|
||||
parseEntries();
|
||||
}
|
||||
|
||||
public void saveChanges() throws IOException {
|
||||
updateFlashEntry();
|
||||
try (RandomAccessFileDataStream raf = new RandomAccessFileDataStream(originalFile)) {
|
||||
writeToDataStream(raf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
header.writeToDataStream(stream);
|
||||
|
||||
long startOffset = IggyHeader.STRUCT_SIZE + IggySubFileEntry.STRUCTURE_SIZE * subFileEntries.size();
|
||||
long currentOffset = startOffset;
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset = currentOffset;
|
||||
currentOffset += entry.size;
|
||||
entry.writeToDataStream(stream);
|
||||
}
|
||||
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
byte[] entryData = subFileEntriesData.get(i);
|
||||
stream.writeBytes(entryData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,64 +18,94 @@ public class IggyFlashHeader32 implements IggyFlashHeaderInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long main_offset; // 0 Relative offset to first section (matches sizeof header)
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long as3_section_offset; // 4 Relative offset to as3 file names table...
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_offset; // 8 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_offset2; // 0xC relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_offset3; // 0x10 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_offset4; // 0x14 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long xmin; //0x18 in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long ymin; //0x0C in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long xmax; // 0x20 in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long ymax; // 0x24 in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_28; // probably number of blocks/objects after header
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_2C;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_30;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_34;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_38;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_3C;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float frameRate;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_44;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_48;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_4C;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long names_offset; // 0x50 relative offset to the names/import section of the file
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_offset5; // 0x54 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long unk_58; // Maybe number of imports/names pointed by names_offset
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long last_section_offset; // 0x60 relative offset, points to the small last section of the file
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_offset6; // 0x64 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long as3_code_offset; // 0x68 relative offset to as3 code (8 bytes header + abc blob)
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long as3_names_offset; // 0x6C relative offset to as3 file names table (or classes names or whatever)
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_70;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_74;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_78; // Maybe number of classes / as3 names
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_7C;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jindra
|
||||
* @author JPEXS
|
||||
*
|
||||
* Based of works of somebody called eternity.
|
||||
*/
|
||||
@@ -17,62 +17,91 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_base; // 0 Relative offset to first section (matches sizeof header);
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_sequence_end; // 8 Relative offset to as3 file names table...
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_font_end; // 0x10 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_sequence_start1; // 0x18 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_sequence_start2; // 0x20 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_sequence_start3; // 0x28 names_offset; 0x50 relative pointer to the names/import section of the file
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long xmin; // 0x30 in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long ymin; // 0x34 in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long xmax; // 0x38 in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long ymax; // 0x3C in pixels
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_40; // probably numer of blocks/objects after header
|
||||
long unk_40; // probably number of blocks/objects after header
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_44;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_48;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_4C;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_50;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_54;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float frame_rate;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long unk_5C;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long imported_guid;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long my_guid; // same for some fonts (eng + chinese)
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_names; // 0x70 relative offset to the names/import section of the file - end of fonts
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_unk78; // 0x78 relative offset to something
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long unk80;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_last_section;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_flash_filename;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_decl_strings;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long off_type_of_fonts;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long flags;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long font_count;
|
||||
|
||||
@IggyFieldType(DataType.uint32_t)
|
||||
long zero2;
|
||||
|
||||
@@ -87,29 +116,51 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
}
|
||||
|
||||
private long base_address;
|
||||
|
||||
private long sequence_end_address;
|
||||
|
||||
private long font_end_address;
|
||||
|
||||
private long sequence_start_address1;
|
||||
|
||||
private long sequence_start_address2;
|
||||
|
||||
private long sequence_start_address3;
|
||||
|
||||
private long names_address;
|
||||
|
||||
private long unk78_address;
|
||||
|
||||
private long last_section_address;
|
||||
|
||||
private long flash_filename_address;
|
||||
|
||||
private long decl_strings_address;
|
||||
|
||||
private long type_fonts_address;
|
||||
|
||||
private long base_ofs_pos;
|
||||
|
||||
private long sequence_end_ofs_pos;
|
||||
|
||||
private long font_end_ofs_pos;
|
||||
|
||||
private long sequence_start1_ofs_pos;
|
||||
|
||||
private long sequence_start2_ofs_pos;
|
||||
|
||||
private long sequence_start3_ofs_pos;
|
||||
|
||||
private long names_ofs_pos;
|
||||
|
||||
private long unk78_ofs_pos;
|
||||
|
||||
private long last_section_ofs_pos;
|
||||
|
||||
private long flash_filename_ofs_pos;
|
||||
|
||||
private long decl_strings_ofs_pos;
|
||||
|
||||
private long type_fonts_ofs_pos;
|
||||
|
||||
public long getBase_ofs_pos() {
|
||||
@@ -389,5 +440,4 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
public float getFrameRate() {
|
||||
return frame_rate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,24 +16,34 @@ public class IggyFontBinInfo implements StructureInterface {
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long size_of_this_info = STRUCT_SIZE;
|
||||
|
||||
@IggyFieldType(value = DataType.uint16_t, count = 4)
|
||||
int font_specific[];
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float normX;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float zero;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float zero2;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float normY;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float minSize;
|
||||
|
||||
@IggyFieldType(DataType.float_t)
|
||||
float maxSize;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long order_in_iggy_file;
|
||||
|
||||
@IggyFieldType(DataType.int64_t)
|
||||
long address_back; //relative
|
||||
|
||||
@IggyFieldType(value = DataType.uint8_t, count = 40)
|
||||
byte pad[];
|
||||
|
||||
@@ -59,7 +69,7 @@ public class IggyFontBinInfo implements StructureInterface {
|
||||
maxSize = s.readFloat();
|
||||
order_in_iggy_file = s.readUI64();
|
||||
address_back = s.readSI64();
|
||||
//if(address_back + s.position() - 8 != text_offsets[i]) Printf("Wrong iggy font format (bininfo-offsetback) (%u)!\n",i);
|
||||
//if(address_back + s.position() - 8 != text_offsets[i]) Printf("Wrong iggy font format (bininfo-offsetback) (%u)!\n",i);
|
||||
pad = s.readBytes(40);
|
||||
}
|
||||
|
||||
@@ -79,5 +89,4 @@ public class IggyFontBinInfo implements StructureInterface {
|
||||
s.writeSI64(address_back);
|
||||
s.writeBytes(pad);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,339 +1,346 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwf implements StructureInterface {
|
||||
|
||||
final static int NO_OFFSET = 1;
|
||||
|
||||
@IggyFieldType(value = DataType.wchar_t, count = 48)
|
||||
String name;
|
||||
|
||||
private List<IggyFont> fonts = new ArrayList<>();
|
||||
// private List<Long> font_data_addresses = new ArrayList<>();
|
||||
private List<IggyFont> add_fonts = new ArrayList<>();
|
||||
// private List<Long> add_font_data_addresses = new ArrayList<>();
|
||||
|
||||
private IggyFlashHeader64 hdr;
|
||||
|
||||
public IggySwf(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
private List<IggyText> texts = new ArrayList<>();
|
||||
//private List<Long> text_data_addresses = new ArrayList<>();
|
||||
private List<IggyText> add_texts = new ArrayList<>();
|
||||
//private List<Long> add_text_data_addresses = new ArrayList<>();
|
||||
|
||||
//private byte font_add_data[];
|
||||
//private List<Long> font_additional_size = new ArrayList<>();
|
||||
private IggyFontBinInfo font_bin_info[];
|
||||
private List<String> sequenceNames = new ArrayList<>();
|
||||
//private List<Long> sequenceValues = new ArrayList<>();
|
||||
|
||||
private IggyFontTypeInfo type_info[];
|
||||
private String type_info_name[];
|
||||
private IggyDeclStrings decl_strings;
|
||||
private long ofs_additional;
|
||||
private long additional_address;
|
||||
|
||||
public IggyFlashHeader64 getHdr() {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
public List<IggyFont> getFonts() {
|
||||
return fonts;
|
||||
}
|
||||
|
||||
public List<IggyFont> getAddFonts() {
|
||||
return add_fonts;
|
||||
}
|
||||
|
||||
public List<IggyText> getTexts() {
|
||||
return texts;
|
||||
}
|
||||
|
||||
public List<IggyText> getAddTexts() {
|
||||
return add_texts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
this.hdr = new IggyFlashHeader64(s);
|
||||
//Save all font bytes to buffer for later easy modification
|
||||
//here is offset[0] - 184
|
||||
name = s.readWChar();
|
||||
//here is offset[1] - 230
|
||||
int pad8 = 8 - (int) (s.position() % 8);
|
||||
if (pad8 > 8) {
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
}
|
||||
//here is offset [2] - 232
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //pad 1
|
||||
|
||||
List<Long> itemsAddresses = new ArrayList<>();
|
||||
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
itemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
if (hdr.getImported_guid() != 0) {
|
||||
ofs_additional = s.readUI64();
|
||||
additional_address = ofs_additional == 1 ? 0 : ofs_additional + s.position() - 8;
|
||||
}
|
||||
for (Long addr : itemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//font_data_addresses.add(addr);
|
||||
fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//text_data_addresses.add(addr);
|
||||
texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown item kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
if (additional_address != 0) {
|
||||
s.seek(additional_address, SeekMode.SET);
|
||||
List<Long> additionalItemsAddresses = new ArrayList<>();
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
additionalItemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
for (Long addr : additionalItemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//add_font_data_addresses.add(addr);
|
||||
add_fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//add_text_data_addresses.add(addr);
|
||||
add_texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown imported item kind: " + kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
//here is offset [4] - 856 ?
|
||||
font_bin_info = new IggyFontBinInfo[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i] = new IggyFontBinInfo(s);
|
||||
}
|
||||
|
||||
sequenceNames = new ArrayList<>();
|
||||
|
||||
long seq_addresses[] = new long[]{hdr.getSequenceStartAddress1(), hdr.getSequenceStartAddress2(), hdr.getSequenceStartAddress3()};
|
||||
long seq_name_addresses[] = new long[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_addresses[i] == 0) {
|
||||
seq_name_addresses[i] = 0;
|
||||
//0
|
||||
} else {
|
||||
s.seek(seq_addresses[i], SeekMode.SET);
|
||||
long ofs_seq_name = s.readUI64();
|
||||
seq_name_addresses[i] = ofs_seq_name == 1 ? 0 : ofs_seq_name + s.position() - 8;
|
||||
s.readUI64(); //is this crucial?
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_name_addresses[i] > 0) {
|
||||
s.seek(seq_name_addresses[i], SeekMode.SET);
|
||||
sequenceNames.add(s.readWChar());
|
||||
} else {
|
||||
sequenceNames.add(null);
|
||||
}
|
||||
}
|
||||
s.pad8bytes();
|
||||
|
||||
//sequence = new IggySequence(s);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
type_info = new IggyFontTypeInfo[(int) hdr.font_count];
|
||||
type_info_name = new String[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i] = new IggyFontTypeInfo(s);
|
||||
}
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
s.seek(type_info[i].getLocal_name_ofs_pos() + type_info[i].ofs_local_name, SeekMode.SET);
|
||||
type_info_name[i] = s.readWChar();
|
||||
}
|
||||
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings = new IggyDeclStrings(s);
|
||||
/*WriteDataStreamInterface outs = new TemporaryDataStream();
|
||||
writeToDataStream(outs);
|
||||
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
hdr.writeToDataStream(s);
|
||||
s.writeWChar(name);
|
||||
s.pad8bytes();
|
||||
s.writeUI64(1);
|
||||
ib.write16bitArray(name.length() + 1);
|
||||
ib.writeTwoPaddingBytes();
|
||||
ib.write64bitPointerArray(64);
|
||||
long posBeforeOffsets = s.position();
|
||||
|
||||
final int FILL_LATER = 1;
|
||||
|
||||
List<Long> fontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
fontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> textPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
textPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(1);
|
||||
|
||||
long addPosFillLater = s.position();
|
||||
s.writeUI64(FILL_LATER);
|
||||
long posAfter = posBeforeOffsets + 64 * 8;
|
||||
long curPos = s.position();
|
||||
long numLeft = posAfter - curPos;
|
||||
long ofsLeft = numLeft / 8;
|
||||
for (int i = 0; i < ofsLeft - 1; i++) {
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(fontPosFillLater.get(i));
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(textPosFillLater.get(i));
|
||||
texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
|
||||
if (!add_fonts.isEmpty() || !add_texts.isEmpty()) {
|
||||
s.setOlderOffsetToThisPos(addPosFillLater);
|
||||
|
||||
List<Long> addFontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
addFontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> addTextPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
addTextPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(FILL_LATER);
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addFontPosFillLater.get(i));
|
||||
add_fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addTextPosFillLater.get(i));
|
||||
add_texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getFont_end_ofs_pos());
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_BIN_INFO_SIZE, hdr.font_count);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
long seq_ofs_pos[] = new long[]{hdr.getSequence_start1_ofs_pos(), hdr.getSequence_start2_ofs_pos(), hdr.getSequence_start3_ofs_pos()};
|
||||
long off_seq_expected[] = new long[]{hdr.off_sequence_start1, hdr.off_sequence_start2, hdr.off_sequence_start3};
|
||||
|
||||
long seq_name_fill_later[] = new long[3];
|
||||
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[0]);
|
||||
s.writeUI64(1);
|
||||
s.writeUI64(1);
|
||||
ib.writeLengthCustom(16, new int[]{0}, new int[]{2});
|
||||
|
||||
seq_name_fill_later[2] = s.position();
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[2]);
|
||||
s.writeUI64(FILL_LATER);
|
||||
s.writeUI64(0);
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (sequenceNames.get(i) != null) {
|
||||
s.setOlderOffsetToThisPos(seq_name_fill_later[i]);
|
||||
ib.write16bitArray(sequenceNames.get(i).length() + 1);
|
||||
s.writeWChar(sequenceNames.get(i));
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getSequence_end_ofs_pos());
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count);
|
||||
s.setOlderOffsetToThisPos(hdr.getType_fonts_ofs_pos());
|
||||
//s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
ib.write16bitArray(type_info_name[i].length() + 1);
|
||||
s.setOlderOffsetToThisPos(type_info[i].getLocal_name_ofs_pos());
|
||||
s.writeWChar(type_info_name[i]);
|
||||
}
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
s.setOlderOffsetToThisPos(hdr.getDecl_strings_ofs_pos());
|
||||
//s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings.writeToDataStream(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[\r\n");
|
||||
sb.append("name ").append(name).append("\r\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public IggyDeclStrings getDeclStrings() {
|
||||
return decl_strings;
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.SeekMode;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwf implements StructureInterface {
|
||||
|
||||
final static int NO_OFFSET = 1;
|
||||
|
||||
@IggyFieldType(value = DataType.wchar_t, count = 48)
|
||||
String name;
|
||||
|
||||
private List<IggyFont> fonts = new ArrayList<>();
|
||||
|
||||
// private List<Long> font_data_addresses = new ArrayList<>();
|
||||
private List<IggyFont> add_fonts = new ArrayList<>();
|
||||
// private List<Long> add_font_data_addresses = new ArrayList<>();
|
||||
|
||||
private IggyFlashHeader64 hdr;
|
||||
|
||||
public IggySwf(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
private List<IggyText> texts = new ArrayList<>();
|
||||
|
||||
//private List<Long> text_data_addresses = new ArrayList<>();
|
||||
private List<IggyText> add_texts = new ArrayList<>();
|
||||
//private List<Long> add_text_data_addresses = new ArrayList<>();
|
||||
|
||||
//private byte font_add_data[];
|
||||
//private List<Long> font_additional_size = new ArrayList<>();
|
||||
private IggyFontBinInfo font_bin_info[];
|
||||
|
||||
private List<String> sequenceNames = new ArrayList<>();
|
||||
//private List<Long> sequenceValues = new ArrayList<>();
|
||||
|
||||
private IggyFontTypeInfo type_info[];
|
||||
|
||||
private String type_info_name[];
|
||||
|
||||
private IggyDeclStrings decl_strings;
|
||||
|
||||
private long ofs_additional;
|
||||
|
||||
private long additional_address;
|
||||
|
||||
public IggyFlashHeader64 getHdr() {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
public List<IggyFont> getFonts() {
|
||||
return fonts;
|
||||
}
|
||||
|
||||
public List<IggyFont> getAddFonts() {
|
||||
return add_fonts;
|
||||
}
|
||||
|
||||
public List<IggyText> getTexts() {
|
||||
return texts;
|
||||
}
|
||||
|
||||
public List<IggyText> getAddTexts() {
|
||||
return add_texts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
this.hdr = new IggyFlashHeader64(s);
|
||||
//Save all font bytes to buffer for later easy modification
|
||||
//here is offset[0] - 184
|
||||
name = s.readWChar();
|
||||
//here is offset[1] - 230
|
||||
int pad8 = 8 - (int) (s.position() % 8);
|
||||
if (pad8 > 8) {
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
}
|
||||
//here is offset [2] - 232
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //pad 1
|
||||
|
||||
List<Long> itemsAddresses = new ArrayList<>();
|
||||
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
itemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
if (hdr.getImported_guid() != 0) {
|
||||
ofs_additional = s.readUI64();
|
||||
additional_address = ofs_additional == 1 ? 0 : ofs_additional + s.position() - 8;
|
||||
}
|
||||
for (Long addr : itemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//font_data_addresses.add(addr);
|
||||
fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//text_data_addresses.add(addr);
|
||||
texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown item kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
if (additional_address != 0) {
|
||||
s.seek(additional_address, SeekMode.SET);
|
||||
List<Long> additionalItemsAddresses = new ArrayList<>();
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
additionalItemsAddresses.add(offset + s.position() - 8);
|
||||
}
|
||||
for (Long addr : additionalItemsAddresses) {
|
||||
s.seek(addr, SeekMode.SET);
|
||||
int kind = s.readUI8();
|
||||
s.seek(-1, SeekMode.CUR);
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
//add_font_data_addresses.add(addr);
|
||||
add_fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
//add_text_data_addresses.add(addr);
|
||||
add_texts.add(text);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown imported item kind: " + kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
//here is offset [4] - 856 ?
|
||||
font_bin_info = new IggyFontBinInfo[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i] = new IggyFontBinInfo(s);
|
||||
}
|
||||
|
||||
sequenceNames = new ArrayList<>();
|
||||
|
||||
long seq_addresses[] = new long[]{hdr.getSequenceStartAddress1(), hdr.getSequenceStartAddress2(), hdr.getSequenceStartAddress3()};
|
||||
long seq_name_addresses[] = new long[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_addresses[i] == 0) {
|
||||
seq_name_addresses[i] = 0;
|
||||
//0
|
||||
} else {
|
||||
s.seek(seq_addresses[i], SeekMode.SET);
|
||||
long ofs_seq_name = s.readUI64();
|
||||
seq_name_addresses[i] = ofs_seq_name == 1 ? 0 : ofs_seq_name + s.position() - 8;
|
||||
s.readUI64(); //is this crucial?
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_name_addresses[i] > 0) {
|
||||
s.seek(seq_name_addresses[i], SeekMode.SET);
|
||||
sequenceNames.add(s.readWChar());
|
||||
} else {
|
||||
sequenceNames.add(null);
|
||||
}
|
||||
}
|
||||
s.pad8bytes();
|
||||
|
||||
//sequence = new IggySequence(s);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
type_info = new IggyFontTypeInfo[(int) hdr.font_count];
|
||||
type_info_name = new String[(int) hdr.font_count];
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i] = new IggyFontTypeInfo(s);
|
||||
}
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
s.seek(type_info[i].getLocal_name_ofs_pos() + type_info[i].ofs_local_name, SeekMode.SET);
|
||||
type_info_name[i] = s.readWChar();
|
||||
}
|
||||
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings = new IggyDeclStrings(s);
|
||||
/*WriteDataStreamInterface outs = new TemporaryDataStream();
|
||||
writeToDataStream(outs);
|
||||
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());*/
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
hdr.writeToDataStream(s);
|
||||
s.writeWChar(name);
|
||||
s.pad8bytes();
|
||||
s.writeUI64(1);
|
||||
ib.write16bitArray(name.length() + 1);
|
||||
ib.writeTwoPaddingBytes();
|
||||
ib.write64bitPointerArray(64);
|
||||
long posBeforeOffsets = s.position();
|
||||
|
||||
final int FILL_LATER = 1;
|
||||
|
||||
List<Long> fontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
fontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> textPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
textPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(1);
|
||||
|
||||
long addPosFillLater = s.position();
|
||||
s.writeUI64(FILL_LATER);
|
||||
long posAfter = posBeforeOffsets + 64 * 8;
|
||||
long curPos = s.position();
|
||||
long numLeft = posAfter - curPos;
|
||||
long ofsLeft = numLeft / 8;
|
||||
for (int i = 0; i < ofsLeft - 1; i++) {
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(fontPosFillLater.get(i));
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(textPosFillLater.get(i));
|
||||
texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
|
||||
if (!add_fonts.isEmpty() || !add_texts.isEmpty()) {
|
||||
s.setOlderOffsetToThisPos(addPosFillLater);
|
||||
|
||||
List<Long> addFontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
addFontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> addTextPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
addTextPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(FILL_LATER);
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addFontPosFillLater.get(i));
|
||||
add_fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addTextPosFillLater.get(i));
|
||||
add_texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getFont_end_ofs_pos());
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_BIN_INFO_SIZE, hdr.font_count);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
long seq_ofs_pos[] = new long[]{hdr.getSequence_start1_ofs_pos(), hdr.getSequence_start2_ofs_pos(), hdr.getSequence_start3_ofs_pos()};
|
||||
long off_seq_expected[] = new long[]{hdr.off_sequence_start1, hdr.off_sequence_start2, hdr.off_sequence_start3};
|
||||
|
||||
long seq_name_fill_later[] = new long[3];
|
||||
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[0]);
|
||||
s.writeUI64(1);
|
||||
s.writeUI64(1);
|
||||
ib.writeLengthCustom(16, new int[]{0}, new int[]{2});
|
||||
|
||||
seq_name_fill_later[2] = s.position();
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[2]);
|
||||
s.writeUI64(FILL_LATER);
|
||||
s.writeUI64(0);
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (sequenceNames.get(i) != null) {
|
||||
s.setOlderOffsetToThisPos(seq_name_fill_later[i]);
|
||||
ib.write16bitArray(sequenceNames.get(i).length() + 1);
|
||||
s.writeWChar(sequenceNames.get(i));
|
||||
}
|
||||
}
|
||||
s.setOlderOffsetToThisPos(hdr.getSequence_end_ofs_pos());
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count);
|
||||
s.setOlderOffsetToThisPos(hdr.getType_fonts_ofs_pos());
|
||||
//s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
ib.write16bitArray(type_info_name[i].length() + 1);
|
||||
s.setOlderOffsetToThisPos(type_info[i].getLocal_name_ofs_pos());
|
||||
s.writeWChar(type_info_name[i]);
|
||||
}
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
s.setOlderOffsetToThisPos(hdr.getDecl_strings_ofs_pos());
|
||||
//s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings.writeToDataStream(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[\r\n");
|
||||
sb.append("name ").append(name).append("\r\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public IggyDeclStrings getDeclStrings() {
|
||||
return decl_strings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,109 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import com.jpexs.helpers.ReReadableInputStream;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwfBundle implements SWFBundle {
|
||||
|
||||
private IggyFile iggyFile;
|
||||
|
||||
public IggySwfBundle(InputStream is) throws IOException {
|
||||
this(is, null);
|
||||
}
|
||||
|
||||
public IggySwfBundle(File filename) throws IOException {
|
||||
this(null, filename);
|
||||
}
|
||||
|
||||
protected IggySwfBundle(InputStream is, File filename) throws IOException {
|
||||
initBundle(is, filename);
|
||||
}
|
||||
|
||||
protected void initBundle(InputStream is, File filename) throws IOException {
|
||||
if (filename == null) {
|
||||
filename = File.createTempFile("bundle", ".iggy");
|
||||
Helper.saveStream(is, filename);
|
||||
}
|
||||
iggyFile = new IggyFile(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> ret = new TreeSet<>();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ret.add(iggyFile.getSwfName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int keyToSwfIndex(String key) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (key.equals(iggyFile.getSwfName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Key " + key + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableInputStream getSWF(String key) throws IOException {
|
||||
SWF swf = IggyToSwfConvertor.getSwf(iggyFile);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
swf.saveTo(baos);
|
||||
MemoryInputStream mis = new MemoryInputStream(baos.toByteArray());
|
||||
return mis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SeekableInputStream> getAll() throws IOException {
|
||||
Map<String, SeekableInputStream> ret = new HashMap<>();
|
||||
for (String key : getKeys()) {
|
||||
ret.put(key, getSWF(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "iggy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putSWF(String key, InputStream is) throws IOException {
|
||||
try {
|
||||
SWF swf = new SWF(is, false, false);
|
||||
SwfToIggyConvertor.updateIggy(iggyFile.getSwf(), swf);
|
||||
iggyFile.saveChanges();
|
||||
return true;
|
||||
} catch (InterruptedException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwfBundle implements SWFBundle {
|
||||
|
||||
private IggyFile iggyFile;
|
||||
|
||||
public IggySwfBundle(InputStream is) throws IOException {
|
||||
this(is, null);
|
||||
}
|
||||
|
||||
public IggySwfBundle(File filename) throws IOException {
|
||||
this(null, filename);
|
||||
}
|
||||
|
||||
protected IggySwfBundle(InputStream is, File filename) throws IOException {
|
||||
initBundle(is, filename);
|
||||
}
|
||||
|
||||
protected void initBundle(InputStream is, File filename) throws IOException {
|
||||
if (filename == null) {
|
||||
filename = File.createTempFile("bundle", ".iggy");
|
||||
Helper.saveStream(is, filename);
|
||||
}
|
||||
iggyFile = new IggyFile(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> ret = new TreeSet<>();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ret.add(iggyFile.getSwfName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int keyToSwfIndex(String key) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (key.equals(iggyFile.getSwfName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Key " + key + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableInputStream getSWF(String key) throws IOException {
|
||||
SWF swf = IggyToSwfConvertor.getSwf(iggyFile);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
swf.saveTo(baos);
|
||||
MemoryInputStream mis = new MemoryInputStream(baos.toByteArray());
|
||||
return mis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SeekableInputStream> getAll() throws IOException {
|
||||
Map<String, SeekableInputStream> ret = new HashMap<>();
|
||||
for (String key : getKeys()) {
|
||||
ret.put(key, getSWF(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "iggy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putSWF(String key, InputStream is) throws IOException {
|
||||
try {
|
||||
SWF swf = new SWF(is, false, false);
|
||||
SwfToIggyConvertor.updateIggy(iggyFile.getSwf(), swf);
|
||||
iggyFile.saveChanges();
|
||||
return true;
|
||||
} catch (InterruptedException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ decompilationError.timeout.description = No s'ha descompilat degut al l\u00edmit
|
||||
decompilationError.obfuscated = El codi pot estar ofuscat
|
||||
decompilationError.errorType = Tipus d'error
|
||||
decompilationError.error.description = No s'ha descompilat degut a l'error
|
||||
decompilationError.actionCount = Recompte d'accions:
|
||||
decompilationError.instructionCount = Recompe d'instruccions:
|
||||
|
||||
decompilation.skipped = S'ha om\u00e8s la descompilaci\u00f3
|
||||
decompilation.unsupported = No suportat pel descompilador
|
||||
|
||||
@@ -1040,8 +1040,8 @@ public class Graph {
|
||||
private void getPrecontinues(String path, BaseLocalData localData, GraphPart parent, GraphPart part, Set<GraphPart> allParts, List<Loop> loops, List<GraphPart> stopPart) throws InterruptedException {
|
||||
try {
|
||||
markLevels(path, localData, part, allParts, loops);
|
||||
} catch (ThreadDeath | InterruptedException iex) {
|
||||
throw iex;
|
||||
} catch (ThreadDeath | InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
//It is unusual code so markLevels failed, nevermind, it can still work
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user