Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2dbee2e2a | ||
|
|
66bccc6a6f | ||
|
|
22194e5baf | ||
|
|
b95f0ece09 | ||
|
|
b691796c4e | ||
|
|
54349c3a55 | ||
|
|
f0302dcfca |
@@ -0,0 +1,36 @@
|
||||
RABCDAsm Changelog
|
||||
==================
|
||||
|
||||
RABCDAsm v1.3 (2010.11.11)
|
||||
--------------------------
|
||||
|
||||
* Fixed double precision problem
|
||||
* This also fixes problems with illegal default values for function
|
||||
parameters (default values for integer parameters are stored as doubles,
|
||||
which might become out-of-range due to inadequate double precision)
|
||||
* Added Changelog
|
||||
* Documentation markdown fixes
|
||||
|
||||
RABCDAsm v1.2 (2010.11.06)
|
||||
--------------------------
|
||||
|
||||
* Fixed ref generation for orphan objects which were only referenced
|
||||
by other orphans
|
||||
* Better error handling in `abcexport`; warn when no DoABC tags found
|
||||
* Documentation updates
|
||||
|
||||
RABCDAsm v1.1 (2010.06.30)
|
||||
--------------------------
|
||||
|
||||
* Private namespaces are now referenced by auto-generated names
|
||||
* Use `:` to delimit namespace and name in QNames for consistency
|
||||
* Warning: this breaks compatibility with v1.0 disassemblies
|
||||
* Fixed relative include paths
|
||||
* Add optional byte offsets to labels, which allows lossless representation
|
||||
of jumps inside instructions and outside the function bounds
|
||||
* Documentation updates
|
||||
|
||||
RABCDAsm v1.0 (2010.05.05)
|
||||
--------------------------
|
||||
|
||||
* Initial release.
|
||||
@@ -1,7 +1,7 @@
|
||||
Robust ABC (ActionScript Bytecode) [Dis-]Assembler
|
||||
==================================================
|
||||
|
||||
[RABCDAsm][] is a collection of utilities including an ActionScript
|
||||
[RABCDAsm][] is a collection of utilities including an ActionScript 3
|
||||
assembler/disassembler, and a few tools to manipulate SWF files.
|
||||
These are:
|
||||
|
||||
@@ -31,7 +31,7 @@ Motivation and goals
|
||||
--------------------
|
||||
|
||||
This package was created due to lack of similar software out there.
|
||||
Particularly, I needed an utility which would allow me to edit ActionScript
|
||||
Particularly, I needed an utility which would allow me to edit ActionScript 3
|
||||
bytecode with the following properties:
|
||||
|
||||
1. Speed. Less waiting means more productivity. `rabcasm` can assemble large
|
||||
@@ -102,6 +102,9 @@ To assemble the `.asasm` files back, and update the SWF file:
|
||||
rabcasm file0/file0.main.asasm
|
||||
abcreplace file0.swf 0 file0/file0.main.abc
|
||||
|
||||
The second `abcreplace` argument represents the index of the ABC block in the
|
||||
SWF file, and corresponds to the number in the filename created by `abcexport`.
|
||||
|
||||
Syntax
|
||||
======
|
||||
|
||||
@@ -294,9 +297,9 @@ be instantiated in two ways:
|
||||
although variables are defined using a string syntax, they are not
|
||||
inserted as a string using this syntax. Thus, the code:
|
||||
|
||||
#set str "Hello, world!"
|
||||
...
|
||||
pushstring $str
|
||||
#set str "Hello, world!"
|
||||
...
|
||||
pushstring $str
|
||||
|
||||
will expand to `pushstring Hello, world!`, which will result in an error.
|
||||
To correct the problem, add escaped quotes around the variable contents
|
||||
@@ -311,20 +314,20 @@ be instantiated in two ways:
|
||||
Here's an example of how to use the above features to create a macro which
|
||||
logs a string literal and the contents of a register:
|
||||
|
||||
#set log "
|
||||
findpropstrict QName(PackageNamespace(\"\"), \"log\")
|
||||
pushstring $\"1\"
|
||||
getlocal $2
|
||||
callpropvoid QName(PackageNamespace(\"\"), \"log\"), 2
|
||||
"
|
||||
|
||||
; ...
|
||||
|
||||
pushbyte 2
|
||||
pushbyte 2
|
||||
add_i
|
||||
setlocal1
|
||||
#call $"log"("two plus two equals", "1")
|
||||
#set log "
|
||||
findpropstrict QName(PackageNamespace(\"\"), \"log\")
|
||||
pushstring $\"1\"
|
||||
getlocal $2
|
||||
callpropvoid QName(PackageNamespace(\"\"), \"log\"), 2
|
||||
"
|
||||
|
||||
; ...
|
||||
|
||||
pushbyte 2
|
||||
pushbyte 2
|
||||
add_i
|
||||
setlocal1
|
||||
#call $"log"("two plus two equals", "1")
|
||||
|
||||
Highlighting
|
||||
------------
|
||||
@@ -344,19 +347,19 @@ instead of indexes, allowing easy manipulation without having to worry about
|
||||
record order or constant pools. Conversion between various states is done as
|
||||
follows:
|
||||
|
||||
file.abc
|
||||
| ^
|
||||
ABCReader | | ABCWriter
|
||||
v |
|
||||
ABCFile
|
||||
| ^
|
||||
ABCtoAS | | AStoABC
|
||||
v |
|
||||
ASProgram
|
||||
| ^
|
||||
Disassembler | | Assembler
|
||||
v |
|
||||
file.asasm
|
||||
file.abc
|
||||
| ^
|
||||
------ ABCReader | | ABCWriter ----
|
||||
/ v | \
|
||||
/ ABCFile \
|
||||
/ | ^ \
|
||||
rabcdasm---------- ABCtoAS | | AStoABC --------rabcasm
|
||||
\ v | /
|
||||
\ ASProgram /
|
||||
\ | ^ /
|
||||
--- Disassembler | | Assembler ----
|
||||
v |
|
||||
file.asasm
|
||||
|
||||
`AStoABC` will rebuild the constant pools, in a manner similar to Adobe's
|
||||
compilers (reverse-sorted by reference count). The exact order will almost
|
||||
@@ -394,19 +397,19 @@ RABCDAsm users.
|
||||
placed in the `OnBeforeResponse` function) will automatically save all SWF
|
||||
files while preserving the directory structure.
|
||||
|
||||
if (oSession.oResponse.headers.ExistsAndContains("Content-Type",
|
||||
"application/x-shockwave-flash")) {
|
||||
// Set desired path here
|
||||
var path:String = "C:\\Temp\\FiddlerCapture\\" +
|
||||
oSession.host + oSession.PathAndQuery;
|
||||
if (path.Contains('?'))
|
||||
path = path.Substring(0, path.IndexOf('?'));
|
||||
var dir:String = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
oSession.utilDecodeResponse();
|
||||
oSession.SaveResponseBody(path);
|
||||
}
|
||||
if (oSession.oResponse.headers.ExistsAndContains("Content-Type",
|
||||
"application/x-shockwave-flash")) {
|
||||
// Set desired path here
|
||||
var path:String = "C:\\Temp\\FiddlerCapture\\" +
|
||||
oSession.host + oSession.PathAndQuery;
|
||||
if (path.Contains('?'))
|
||||
path = path.Substring(0, path.IndexOf('?'));
|
||||
var dir:String = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
oSession.utilDecodeResponse();
|
||||
oSession.SaveResponseBody(path);
|
||||
}
|
||||
|
||||
Once you have edited a SWF file, you can use Fiddler's [AutoResponder][] to
|
||||
replace the original file with your modified version.
|
||||
@@ -420,8 +423,6 @@ Limitations
|
||||
* Metadata is currently ignored. I haven't noticed any metadata blocks in any
|
||||
SWF files I've disassembled.
|
||||
|
||||
* Floating point numbers may not be disassembled with adequate precision.
|
||||
|
||||
* `rabcasm` may create a broken file due to not ordering classes by ancestry.
|
||||
|
||||
The problem originates from the fact that a class's ancestors (extended
|
||||
@@ -432,7 +433,7 @@ Limitations
|
||||
of order. This results in a file that, when opened, will fail to load with
|
||||
an error message similar to:
|
||||
|
||||
`VerifyError: Error #1014: Class AncestorClassName could not be found.`
|
||||
VerifyError: Error #1014: Class AncestorClassName could not be found.
|
||||
|
||||
The simple work-around is to re-order the classes as they are declared in
|
||||
the `.main.asasm` file, and place ancestors before descendants.
|
||||
|
||||
+22
-16
@@ -21,6 +21,7 @@ module abcexport;
|
||||
import std.file;
|
||||
import std.path;
|
||||
import std.string;
|
||||
import std.stdio;
|
||||
import swffile;
|
||||
|
||||
void main(string[] args)
|
||||
@@ -28,22 +29,27 @@ void main(string[] args)
|
||||
if (args.length == 1)
|
||||
throw new Exception("No file specified");
|
||||
foreach (arg; args[1..$])
|
||||
{
|
||||
scope swf = SWFFile.read(cast(ubyte[])read(arg));
|
||||
uint count;
|
||||
foreach (ref tag; swf.tags)
|
||||
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2))
|
||||
{
|
||||
ubyte[] abc;
|
||||
if (tag.type == TagType.DoABC)
|
||||
abc = tag.data;
|
||||
else
|
||||
try
|
||||
{
|
||||
scope swf = SWFFile.read(cast(ubyte[])read(arg));
|
||||
uint count = 0;
|
||||
foreach (ref tag; swf.tags)
|
||||
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2))
|
||||
{
|
||||
auto p = tag.data.ptr+4; // skip flags
|
||||
while (*p++) {} // skip name
|
||||
abc = tag.data[p-tag.data.ptr..$];
|
||||
ubyte[] abc;
|
||||
if (tag.type == TagType.DoABC)
|
||||
abc = tag.data;
|
||||
else
|
||||
{
|
||||
auto p = tag.data.ptr+4; // skip flags
|
||||
while (*p++) {} // skip name
|
||||
abc = tag.data[p-tag.data.ptr..$];
|
||||
}
|
||||
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
|
||||
}
|
||||
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
|
||||
}
|
||||
}
|
||||
if (count == 0)
|
||||
throw new Exception("No DoABC tags found");
|
||||
}
|
||||
catch (Object o)
|
||||
writefln("Error while processing %s: %s", arg, o);
|
||||
}
|
||||
|
||||
+7
-3
@@ -109,6 +109,10 @@ final class RefBuilder : ASTraitsVisitor
|
||||
{
|
||||
foreach (i, ref v; as.scripts)
|
||||
addMethod(v.sinit, "script" ~ .toString(i) ~ "_sinit");
|
||||
foreach (vclass; as.orphanClasses)
|
||||
addClass(vclass, "orphan");
|
||||
foreach (method; as.orphanMethods)
|
||||
addMethod(method, "orphan");
|
||||
super.run();
|
||||
}
|
||||
|
||||
@@ -257,9 +261,9 @@ final class RefBuilder : ASTraitsVisitor
|
||||
return uniqueName;
|
||||
}
|
||||
|
||||
void addClass(ASProgram.Class vclass)
|
||||
void addClass(ASProgram.Class vclass, string field = null)
|
||||
{
|
||||
addObject(vclass, classByName, string.init);
|
||||
addObject(vclass, classByName, field);
|
||||
addMethod(vclass.cinit, "cinit");
|
||||
addMethod(vclass.instance.iinit, "iinit");
|
||||
}
|
||||
@@ -412,7 +416,7 @@ final class Disassembler
|
||||
if (v == ABCFile.NULL_DOUBLE)
|
||||
sb ~= "null";
|
||||
else
|
||||
sb ~= .toString(v);
|
||||
sb ~= format("%.18g", v);
|
||||
}
|
||||
|
||||
void dumpString(StringBuilder sb, string str)
|
||||
|
||||
Reference in New Issue
Block a user