Permalink
Browse files

Adding swf7zcompress

  • Loading branch information...
1 parent 61e8ff3 commit 8211bd6ef16d6927b2ad8cb6b843484b1ab09ff1 @CyberShadow committed Mar 25, 2010
Showing with 93 additions and 4 deletions.
  1. +10 −4 README.md
  2. +83 −0 swf7zcompress.d
View
@@ -10,16 +10,21 @@ These are:
* `abcexport` - extracts ABC from SWF files
* `abcreplace` - replaces ABC in SWF files
* `swfdecompress` - decompresses zlib-compressed SWF files
+ * `swf7zcompress` - (re-)compress the contents of a SWF using 7-Zip
`abcexport` and `abcreplace` are reimplementations of similar utilities from
my [swfutilsex][] Java package, however these work faster as they do not parse
the SWF files as deeply.
`swfdecompress` is ancilliary and is only useful for debugging and studying of
the SWF file format, and not required for ABC manipulation. It is functionally
-equivalent to [flasm][]'s `-x` option.
+equivalent to [flasm][]'s `-x` option.
+`swf7zcompress` is an utility to further reduce the size of SWF files. It uses
+[7-Zip][] to compress the data better than the standard zlib library would. It
+requires that the `7z` command-line program be installed and in `PATH`.
[swfutilsex]: http://github.com/CyberShadow/swfutilsex
[flasm]: http://flasm.sourceforge.net/
+ [7-Zip]: http://www.7-zip.org/
Motivation and goals
--------------------
@@ -49,9 +54,10 @@ Compiling should be straight-forward:
dmd rabcdasm abcfile asprogram disassembler murmurhash2a
dmd rabcasm abcfile asprogram assembler murmurhash2a
- dmd abcexport swffile
- dmd abcreplace swffile
- dmd swfdecompress swffile
+ dmd abcexport swffile zlibx
+ dmd abcreplace swffile zlibx
+ dmd swfdecompress swffile zlibx
+ dmd swf7zcompress swffile zlibx
[d1]: http://www.digitalmars.com/d/1.0/
[std2]: http://dsource.org/projects/std2
View
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 Vladimir Panteleev <vladimir@thecybershadow.net>
+ * This file is part of RABCDAsm.
+ *
+ * RABCDAsm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RABCDAsm 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RABCDAsm. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module swf7zcompress;
+
+import std.file;
+import std.process;
+import std.zlib;
+import swffile;
+import zlibx;
+
+ubyte[] gzip2zlib(ubyte[] data, uint adler)
+{
+ enum
+ {
+ FTEXT = 1,
+ FHCRC = 2,
+ FEXTRA = 4,
+ FNAME = 8,
+ FCOMMENT = 16
+ }
+
+ if (data.length < 10 || data[0] != 0x1F || data[1] != 0x8B || data[2] != 0x08)
+ throw new Exception("Bad or unsupported gzip format");
+ ubyte flags = data[3];
+ auto p = data.ptr;
+ p += 10; // header size
+ if (flags & (FHCRC | FEXTRA | FCOMMENT))
+ throw new Exception("Unsupported gzip flags");
+ if (flags & FNAME)
+ while (*p++) {}
+
+ ubyte[] chdr = [0x78, 0xDA]; // 11011010
+ return chdr ~ data[p-data.ptr..data.length-8] ~ cast(ubyte[])[adler];
+}
+
+void main(string[] args)
+{
+ if (args.length == 1)
+ throw new Exception("No file specified");
+ foreach (arg; args[1..$])
+ {
+ auto swf = cast(ubyte[])read(arg);
+ auto header = cast(SWFFile.Header*)swf.ptr;
+ ubyte[] data;
+ if (header.signature[0] == cast(ubyte)'C')
+ data = exactUncompress(swf[8..$], header.fileLength-8);
+ else
+ if (header.signature[0] == cast(ubyte)'F')
+ {
+ data = swf[8..$];
+ header.signature[0] = cast(ubyte)'C';
+ }
+ else
+ throw new Exception("Unknown format");
+ if (header.fileLength != data.length + 8)
+ throw new Exception("Incorrect file length in file header");
+ write(arg ~ ".tempdata", data);
+ if (system(`7z a -tgzip -mx=9 -mfb=258 "` ~ arg ~ `.tempdata.gz" "` ~ arg ~ `.tempdata"`) || !exists(arg ~ ".tempdata.gz"))
+ throw new Exception("7-Zip failed");
+ remove(arg ~ ".tempdata");
+ auto gzipdata = cast(ubyte[])read(arg ~ ".tempdata.gz");
+ remove(arg ~ ".tempdata.gz");
+ auto zlibdata = gzip2zlib(gzipdata, adler32(0, data));
+ swf = swf[0..8] ~ zlibdata;
+ write(arg, swf);
+ }
+}

0 comments on commit 8211bd6

Please sign in to comment.