swf-toolkit 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +125 -2
- package/README.tr.md +126 -0
- package/dist/abc/abc-file.d.ts +168 -0
- package/dist/abc/abc-file.js +656 -0
- package/dist/abc/analysis.d.ts +36 -0
- package/dist/abc/analysis.js +213 -0
- package/dist/abc/code.d.ts +59 -0
- package/dist/abc/code.js +379 -0
- package/dist/abc/constants.d.ts +80 -0
- package/dist/abc/constants.js +93 -0
- package/dist/abc/interner.d.ts +46 -0
- package/dist/abc/interner.js +168 -0
- package/dist/abc/model.d.ts +40 -0
- package/dist/abc/model.js +146 -0
- package/dist/abc/opcodes.d.ts +39 -0
- package/dist/abc/opcodes.js +196 -0
- package/dist/abc/pcode/assembler.d.ts +42 -0
- package/dist/abc/pcode/assembler.js +635 -0
- package/dist/abc/pcode/disassembler.d.ts +17 -0
- package/dist/abc/pcode/disassembler.js +147 -0
- package/dist/abc/pcode/format.d.ts +23 -0
- package/dist/abc/pcode/format.js +131 -0
- package/dist/abc/pcode/lexer.d.ts +34 -0
- package/dist/abc/pcode/lexer.js +183 -0
- package/dist/assets/assets.d.ts +26 -0
- package/dist/assets/assets.js +151 -0
- package/dist/assets/images.d.ts +31 -0
- package/dist/assets/images.js +238 -0
- package/dist/assets/png.d.ts +12 -0
- package/dist/assets/png.js +196 -0
- package/dist/assets/sounds.d.ts +37 -0
- package/dist/assets/sounds.js +236 -0
- package/dist/avm1/avm1.d.ts +55 -0
- package/dist/avm1/avm1.js +642 -0
- package/dist/avm1/project.d.ts +16 -0
- package/dist/avm1/project.js +81 -0
- package/dist/cjs/abc/abc-file.d.ts +168 -0
- package/dist/cjs/abc/abc-file.js +663 -0
- package/dist/cjs/abc/analysis.d.ts +36 -0
- package/dist/cjs/abc/analysis.js +221 -0
- package/dist/cjs/abc/code.d.ts +59 -0
- package/dist/cjs/abc/code.js +387 -0
- package/dist/cjs/abc/constants.d.ts +80 -0
- package/dist/cjs/abc/constants.js +97 -0
- package/dist/cjs/abc/interner.d.ts +46 -0
- package/dist/cjs/abc/interner.js +172 -0
- package/dist/cjs/abc/model.d.ts +40 -0
- package/dist/cjs/abc/model.js +155 -0
- package/dist/cjs/abc/opcodes.d.ts +39 -0
- package/dist/cjs/abc/opcodes.js +201 -0
- package/dist/cjs/abc/pcode/assembler.d.ts +42 -0
- package/dist/cjs/abc/pcode/assembler.js +640 -0
- package/dist/cjs/abc/pcode/disassembler.d.ts +17 -0
- package/dist/cjs/abc/pcode/disassembler.js +152 -0
- package/dist/cjs/abc/pcode/format.d.ts +23 -0
- package/dist/cjs/abc/pcode/format.js +141 -0
- package/dist/cjs/abc/pcode/lexer.d.ts +34 -0
- package/dist/cjs/abc/pcode/lexer.js +188 -0
- package/dist/cjs/assets/assets.d.ts +26 -0
- package/dist/cjs/assets/assets.js +159 -0
- package/dist/cjs/assets/images.d.ts +31 -0
- package/dist/cjs/assets/images.js +246 -0
- package/dist/cjs/assets/png.d.ts +12 -0
- package/dist/cjs/assets/png.js +202 -0
- package/dist/cjs/assets/sounds.d.ts +37 -0
- package/dist/cjs/assets/sounds.js +246 -0
- package/dist/cjs/avm1/avm1.d.ts +55 -0
- package/dist/cjs/avm1/avm1.js +649 -0
- package/dist/cjs/avm1/project.d.ts +16 -0
- package/dist/cjs/avm1/project.js +88 -0
- package/dist/cjs/compiler/ast.d.ts +285 -0
- package/dist/cjs/compiler/ast.js +3 -0
- package/dist/cjs/compiler/class-compiler.d.ts +34 -0
- package/dist/cjs/compiler/class-compiler.js +440 -0
- package/dist/cjs/compiler/codegen.d.ts +144 -0
- package/dist/cjs/compiler/codegen.js +1589 -0
- package/dist/cjs/compiler/lexer.d.ts +27 -0
- package/dist/cjs/compiler/lexer.js +254 -0
- package/dist/cjs/compiler/parser.d.ts +58 -0
- package/dist/cjs/compiler/parser.js +989 -0
- package/dist/cjs/compiler/program.d.ts +29 -0
- package/dist/cjs/compiler/program.js +36 -0
- package/dist/cjs/compiler/scope.d.ts +22 -0
- package/dist/cjs/compiler/scope.js +242 -0
- package/dist/cjs/compression/lzma.d.ts +37 -0
- package/dist/cjs/compression/lzma.js +575 -0
- package/dist/cjs/compression/swf-container.d.ts +19 -0
- package/dist/cjs/compression/swf-container.js +92 -0
- package/dist/cjs/decompiler/ast.d.ts +228 -0
- package/dist/cjs/decompiler/ast.js +455 -0
- package/dist/cjs/decompiler/cfg.d.ts +40 -0
- package/dist/cjs/decompiler/cfg.js +236 -0
- package/dist/cjs/decompiler/class-printer.d.ts +9 -0
- package/dist/cjs/decompiler/class-printer.js +173 -0
- package/dist/cjs/decompiler/method.d.ts +41 -0
- package/dist/cjs/decompiler/method.js +436 -0
- package/dist/cjs/decompiler/simulate.d.ts +55 -0
- package/dist/cjs/decompiler/simulate.js +591 -0
- package/dist/cjs/decompiler/structure.d.ts +48 -0
- package/dist/cjs/decompiler/structure.js +764 -0
- package/dist/cjs/errors.d.ts +11 -0
- package/dist/cjs/errors.js +25 -0
- package/dist/cjs/index.d.ts +41 -0
- package/dist/cjs/index.js +82 -0
- package/dist/cjs/io/reader.d.ts +48 -0
- package/dist/cjs/io/reader.js +180 -0
- package/dist/cjs/io/writer.d.ts +37 -0
- package/dist/cjs/io/writer.js +175 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/project/pcode-project.d.ts +32 -0
- package/dist/cjs/project/pcode-project.js +210 -0
- package/dist/cjs/project/source-export.d.ts +12 -0
- package/dist/cjs/project/source-export.js +51 -0
- package/dist/cjs/project/source-import.d.ts +13 -0
- package/dist/cjs/project/source-import.js +73 -0
- package/dist/cjs/swf/swf.d.ts +63 -0
- package/dist/cjs/swf/swf.js +147 -0
- package/dist/cjs/swf/tag-codes.d.ts +77 -0
- package/dist/cjs/swf/tag-codes.js +109 -0
- package/dist/cjs/swf/tags.d.ts +118 -0
- package/dist/cjs/swf/tags.js +330 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +296 -0
- package/dist/compiler/ast.d.ts +285 -0
- package/dist/compiler/ast.js +2 -0
- package/dist/compiler/class-compiler.d.ts +34 -0
- package/dist/compiler/class-compiler.js +437 -0
- package/dist/compiler/codegen.d.ts +144 -0
- package/dist/compiler/codegen.js +1585 -0
- package/dist/compiler/lexer.d.ts +27 -0
- package/dist/compiler/lexer.js +249 -0
- package/dist/compiler/parser.d.ts +58 -0
- package/dist/compiler/parser.js +984 -0
- package/dist/compiler/program.d.ts +29 -0
- package/dist/compiler/program.js +32 -0
- package/dist/compiler/scope.d.ts +22 -0
- package/dist/compiler/scope.js +238 -0
- package/dist/compression/lzma.d.ts +37 -0
- package/dist/compression/lzma.js +569 -0
- package/dist/compression/swf-container.d.ts +19 -0
- package/dist/compression/swf-container.js +87 -0
- package/dist/decompiler/ast.d.ts +228 -0
- package/dist/decompiler/ast.js +441 -0
- package/dist/decompiler/cfg.d.ts +40 -0
- package/dist/decompiler/cfg.js +231 -0
- package/dist/decompiler/class-printer.d.ts +9 -0
- package/dist/decompiler/class-printer.js +170 -0
- package/dist/decompiler/method.d.ts +41 -0
- package/dist/decompiler/method.js +427 -0
- package/dist/decompiler/simulate.d.ts +55 -0
- package/dist/decompiler/simulate.js +586 -0
- package/dist/decompiler/structure.d.ts +48 -0
- package/dist/decompiler/structure.js +760 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +20 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +49 -0
- package/dist/io/reader.d.ts +48 -0
- package/dist/io/reader.js +176 -0
- package/dist/io/writer.d.ts +37 -0
- package/dist/io/writer.js +169 -0
- package/dist/project/pcode-project.d.ts +32 -0
- package/dist/project/pcode-project.js +203 -0
- package/dist/project/source-export.d.ts +12 -0
- package/dist/project/source-export.js +47 -0
- package/dist/project/source-import.d.ts +13 -0
- package/dist/project/source-import.js +70 -0
- package/dist/swf/swf.d.ts +63 -0
- package/dist/swf/swf.js +143 -0
- package/dist/swf/tag-codes.d.ts +77 -0
- package/dist/swf/tag-codes.js +105 -0
- package/dist/swf/tags.d.ts +118 -0
- package/dist/swf/tags.js +316 -0
- package/package.json +71 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Recep Asan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,126 @@
|
|
|
1
|
-
#
|
|
1
|
+
# swf-toolkit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**English** | [Türkçe](README.tr.md)
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/swf-toolkit)
|
|
6
|
+
[](https://github.com/recepasan/swf-toolkit/actions/workflows/ci.yml)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
A pure TypeScript library and CLI for reading, editing and writing Adobe Flash SWF files. No Java or other external tools required.
|
|
10
|
+
|
|
11
|
+
- **SWF:** Reads and writes FWS, CWS (zlib) and ZWS (LZMA). LZMA encoder and decoder included. Unmodified files are written back byte-for-byte.
|
|
12
|
+
- **AS3 decompiler:** Produces readable ActionScript 3 source. Recovers if/else, loops, for-in/for-each, switch, try/catch and `&&`/`||`/ternary expressions.
|
|
13
|
+
- **AS3 compiler:** Compiles edited or newly written `.as` files to AVM2 bytecode. Add methods and fields to existing classes, define new classes and interfaces, or build a SWF from scratch.
|
|
14
|
+
- **AVM2 P-code:** Disassembler and assembler for bytecode-level editing. Constant pools, stack and scope limits are handled automatically.
|
|
15
|
+
- **AS1/AS2 (AVM1):** Disassembler and assembler for DoAction/DoInitAction blocks.
|
|
16
|
+
- **Assets:** Export and replace images (PNG/JPEG/GIF), sounds (MP3/WAV), binary data and text fields.
|
|
17
|
+
|
|
18
|
+
Requires Node.js 18+. Ships both ESM (`import`) and CommonJS (`require()`) builds. No runtime dependencies.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install swf-toolkit # as a library
|
|
24
|
+
npm install -g swf-toolkit # as a CLI (swf-toolkit command)
|
|
25
|
+
npx swf-toolkit info game.swf # run without installing
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## CLI
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Inspect
|
|
32
|
+
swf-toolkit info game.swf
|
|
33
|
+
swf-toolkit classes game.swf
|
|
34
|
+
swf-toolkit decompile game.swf com.foo.Bar
|
|
35
|
+
swf-toolkit disasm game.swf com.foo.Bar init
|
|
36
|
+
|
|
37
|
+
# Source-level AS3 editing
|
|
38
|
+
swf-toolkit export-as3 game.swf ./src # one .as file per class
|
|
39
|
+
# … edit files under ./src, add new .as files …
|
|
40
|
+
swf-toolkit import-as3 game.swf ./src out.swf # only changed members are compiled
|
|
41
|
+
swf-toolkit compile game.swf out.swf New.as Other.as
|
|
42
|
+
|
|
43
|
+
# Build a SWF from scratch
|
|
44
|
+
swf-toolkit build app.swf Main.as lib/Helper.as --main Main --width 800 --height 600
|
|
45
|
+
|
|
46
|
+
# Bytecode (P-code) editing
|
|
47
|
+
swf-toolkit export-pcode game.swf ./pcode
|
|
48
|
+
swf-toolkit import-pcode game.swf ./pcode out.swf
|
|
49
|
+
|
|
50
|
+
# AS1/AS2
|
|
51
|
+
swf-toolkit export-as2 old.swf ./as2
|
|
52
|
+
swf-toolkit import-as2 old.swf ./as2 out.swf
|
|
53
|
+
|
|
54
|
+
# Assets
|
|
55
|
+
swf-toolkit export-assets game.swf ./assets # images, sounds, binary, texts
|
|
56
|
+
swf-toolkit replace game.swf out.swf 12 new.png 40 music.mp3
|
|
57
|
+
|
|
58
|
+
# Compression
|
|
59
|
+
swf-toolkit decompress game.swf plain.swf
|
|
60
|
+
swf-toolkit compress plain.swf small.swf lzma
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`import-as3` compares each class with the decompiled form of its current bytecode. Methods whose text has not changed keep their original bytecode, so code the decompiler cannot reproduce perfectly stays intact as long as you leave it alone. Methods that could not be decompiled are written with a `// Decompilation failed` comment and their P-code. They are never replaced with an empty body unless you write a new body yourself.
|
|
64
|
+
|
|
65
|
+
## Library
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { Swf, decompileClass, compileClassSource, compileSources, createSwf } from 'swf-toolkit';
|
|
69
|
+
|
|
70
|
+
const swf = await Swf.load('game.swf');
|
|
71
|
+
const abc = swf.abcTags[0].abc;
|
|
72
|
+
|
|
73
|
+
// Edit a class as AS3
|
|
74
|
+
const ci = abc.findClass('com.foo.Bar');
|
|
75
|
+
const src = decompileClass(abc, ci);
|
|
76
|
+
const edited = src.replace('return 10;', 'return 99;');
|
|
77
|
+
compileClassSource(abc, edited); // only changed members are compiled
|
|
78
|
+
await swf.save('game-patched.swf');
|
|
79
|
+
|
|
80
|
+
// Build a SWF from scratch
|
|
81
|
+
const { abc: fresh } = compileSources([{ name: 'Main.as', text: mainSource }]);
|
|
82
|
+
await createSwf(fresh, { documentClass: 'Main' }).save('app.swf');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Other APIs:
|
|
86
|
+
|
|
87
|
+
- P-code: `disassembleMethod`, `assembleMethod`, `exportPcode`, `importPcode`.
|
|
88
|
+
- Bytecode tools: `decodeCode`, `encodeCode`, `computeLimits`, `verifyCode`.
|
|
89
|
+
- Parser: `parseAs3`.
|
|
90
|
+
- Assets: `exportAssets`, `replaceAsset`.
|
|
91
|
+
- AVM1: `decodeActions`, `formatActions`, `parseActions`, `encodeActions`.
|
|
92
|
+
|
|
93
|
+
## How the compiler resolves names
|
|
94
|
+
|
|
95
|
+
Local variables and parameters are bound to registers. Variables captured by closures are stored in activation-object slots. Every other name is emitted as a `Multiname` with the class's open namespace set and resolved by the VM through the scope chain, which is what the Flex compiler does for names it cannot bind early. Type annotations (`var x:Foo`, parameters, return types) are resolved to QNames using imports, the same package, top-level classes and the SWF's own constant pool, so `playerglobal.swc` is not needed.
|
|
96
|
+
|
|
97
|
+
For classes without a constructor, an implicit constructor is generated for non-constant field initialisers. As in Flex, these values are assigned before the `super()` call.
|
|
98
|
+
|
|
99
|
+
Supported language features: classes, interfaces, inheritance, `super`, getters/setters, static members, constants, default and `...rest` parameters, closures, every loop form (including labelled break/continue), switch, try/catch/finally, `with`, regular expressions, Vector, object and array literals, `as`/`is`/`instanceof`/`in`/`typeof`/`delete`, compound assignments (including `&&=` and `||=`), E4X access (`.@attr`, `..child`, `.(filter)`) and XML literals (compiled to `new XML(...)` at runtime).
|
|
100
|
+
|
|
101
|
+
## Tests
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm test
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Tests use Node's built-in `node:test` module. They cover:
|
|
108
|
+
|
|
109
|
+
- LZMA, SWF container and ABC round-trips, the P-code round-trip and the verifier.
|
|
110
|
+
- The parser, the compiler and decompile → compile → decompile stability.
|
|
111
|
+
- PNG, sound and AVM1 round-trips.
|
|
112
|
+
|
|
113
|
+
If [Ruffle](https://ruffle.rs) is installed (`/Applications/Ruffle.app` or `RUFFLE=/path/to/ruffle`), the compiled test program runs in a real Flash VM and 59 runtime checks are verified. Without Ruffle this test is skipped.
|
|
114
|
+
|
|
115
|
+
## Limitations
|
|
116
|
+
|
|
117
|
+
- **No type checking.** Type errors only surface at runtime. Interface conformance and override signatures are not checked either.
|
|
118
|
+
- **finally:** `finally` blocks are duplicated on the normal exit, `return`, `break` and `continue` paths.
|
|
119
|
+
- **Namespace declarations:** Package-level namespace declarations (`public namespace x = "..."`) are not compiled. Existing namespaces can be used with `use namespace` and `ns::name`.
|
|
120
|
+
- **XML literals:** `{expression}` interpolation is not supported.
|
|
121
|
+
- **Decompiler:** Works well on Flex/ASC output. Methods that fail on obfuscated code are shown as P-code in comments.
|
|
122
|
+
- **Assets:** Fonts and shape/sprite vector graphics are not converted and are kept as raw tags. JPEG3/4 alpha channels are exported as a separate mask PNG. Nellymoser and Speex sounds are exported as raw data.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
MIT
|
package/README.tr.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# swf-toolkit
|
|
2
|
+
|
|
3
|
+
[English](README.md) | **Türkçe**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/swf-toolkit)
|
|
6
|
+
[](https://github.com/recepasan/swf-toolkit/actions/workflows/ci.yml)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
Adobe Flash SWF dosyalarını okumak, düzenlemek ve yeniden yazmak için saf TypeScript kütüphanesi ve CLI. Java ya da başka bir harici araç gerektirmez.
|
|
10
|
+
|
|
11
|
+
- **SWF:** FWS, CWS (zlib) ve ZWS (LZMA) formatlarını okur ve yazar. LZMA kodlayıcı ve çözücü pakete dahil. Değiştirilmeyen dosyalar byte byte aynı yazılır.
|
|
12
|
+
- **AS3 decompiler:** Okunabilir ActionScript 3 kaynağı üretir. if/else, döngüler, for-in/for-each, switch, try/catch ve `&&`/`||`/ternary yapılarını geri kurar.
|
|
13
|
+
- **AS3 derleyici:** Düzenlenmiş ya da yeni yazılmış `.as` dosyalarını AVM2 bytecode'a derler. Var olan sınıflara yeni metod ve alan eklenebilir, yeni sınıf ve interface tanımlanabilir, sıfırdan SWF üretilebilir.
|
|
14
|
+
- **AVM2 P-code:** Bytecode seviyesinde düzenleme için disassembler ve assembler. Sabit havuzlarını, stack ve scope hesaplarını otomatik yapar.
|
|
15
|
+
- **AS1/AS2 (AVM1):** DoAction/DoInitAction blokları için disassembler ve assembler.
|
|
16
|
+
- **Kaynaklar:** Görsel (PNG/JPEG/GIF), ses (MP3/WAV), binary veri ve metin alanlarını dışa aktarır ve değiştirir.
|
|
17
|
+
|
|
18
|
+
Node.js 18+ gerekir. Paket hem ESM (`import`) hem CommonJS (`require()`) olarak gelir. Çalışma zamanında bağımlılığı yoktur.
|
|
19
|
+
|
|
20
|
+
## Kurulum
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install swf-toolkit # kütüphane olarak
|
|
24
|
+
npm install -g swf-toolkit # CLI olarak (swf-toolkit komutu)
|
|
25
|
+
npx swf-toolkit info oyun.swf # kurmadan çalıştırmak için
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## CLI
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# İnceleme
|
|
32
|
+
swf-toolkit info oyun.swf
|
|
33
|
+
swf-toolkit classes oyun.swf
|
|
34
|
+
swf-toolkit decompile oyun.swf com.foo.Bar
|
|
35
|
+
swf-toolkit disasm oyun.swf com.foo.Bar init
|
|
36
|
+
|
|
37
|
+
# AS3 kaynak seviyesinde düzenleme
|
|
38
|
+
swf-toolkit export-as3 oyun.swf ./src # her sınıf için .as dosyası
|
|
39
|
+
# … ./src altındaki dosyaları düzenle, yeni .as dosyaları ekle …
|
|
40
|
+
swf-toolkit import-as3 oyun.swf ./src out.swf # sadece değişen üyeler derlenir
|
|
41
|
+
swf-toolkit compile oyun.swf out.swf Yeni.as Diger.as
|
|
42
|
+
|
|
43
|
+
# Sıfırdan SWF
|
|
44
|
+
swf-toolkit build app.swf Main.as lib/Helper.as --main Main --width 800 --height 600
|
|
45
|
+
|
|
46
|
+
# Bytecode (P-code) seviyesinde düzenleme
|
|
47
|
+
swf-toolkit export-pcode oyun.swf ./pcode
|
|
48
|
+
swf-toolkit import-pcode oyun.swf ./pcode out.swf
|
|
49
|
+
|
|
50
|
+
# AS1/AS2
|
|
51
|
+
swf-toolkit export-as2 eski.swf ./as2
|
|
52
|
+
swf-toolkit import-as2 eski.swf ./as2 out.swf
|
|
53
|
+
|
|
54
|
+
# Kaynaklar
|
|
55
|
+
swf-toolkit export-assets oyun.swf ./assets # images, sounds, binary, texts
|
|
56
|
+
swf-toolkit replace oyun.swf out.swf 12 yeni.png 40 muzik.mp3
|
|
57
|
+
|
|
58
|
+
# Sıkıştırma
|
|
59
|
+
swf-toolkit decompress oyun.swf acik.swf
|
|
60
|
+
swf-toolkit compress acik.swf kucuk.swf lzma
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`import-as3` her sınıfı mevcut bytecode'un decompile edilmiş haliyle karşılaştırır. Metni değişmeyen metodlar orijinal bytecode'larıyla kalır. Böylece decompiler'ın kusursuz geri kuramadığı kod, dokunulmadığı sürece bozulmaz. Decompile edilemeyen metodlar `// Decompilation failed` yorumu ve P-code ile yazılır. Bu metodlar elle yeni bir gövde yazılmadıkça hiçbir zaman boş gövdeyle değiştirilmez.
|
|
64
|
+
|
|
65
|
+
## Kütüphane
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { Swf, decompileClass, compileClassSource, compileSources, createSwf } from 'swf-toolkit';
|
|
69
|
+
|
|
70
|
+
const swf = await Swf.load('oyun.swf');
|
|
71
|
+
const abc = swf.abcTags[0].abc;
|
|
72
|
+
|
|
73
|
+
// Bir sınıfı AS3 olarak düzenle
|
|
74
|
+
const ci = abc.findClass('com.foo.Bar');
|
|
75
|
+
const src = decompileClass(abc, ci);
|
|
76
|
+
const edited = src.replace('return 10;', 'return 99;');
|
|
77
|
+
compileClassSource(abc, edited); // sadece değişen üyeler derlenir
|
|
78
|
+
await swf.save('oyun-patched.swf');
|
|
79
|
+
|
|
80
|
+
// Sıfırdan SWF
|
|
81
|
+
const { abc: fresh } = compileSources([{ name: 'Main.as', text: mainSource }]);
|
|
82
|
+
await createSwf(fresh, { documentClass: 'Main' }).save('app.swf');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Diğer API'ler:
|
|
86
|
+
|
|
87
|
+
- P-code: `disassembleMethod`, `assembleMethod`, `exportPcode`, `importPcode`.
|
|
88
|
+
- Bytecode araçları: `decodeCode`, `encodeCode`, `computeLimits`, `verifyCode`.
|
|
89
|
+
- Parser: `parseAs3`.
|
|
90
|
+
- Kaynaklar: `exportAssets`, `replaceAsset`.
|
|
91
|
+
- AVM1: `decodeActions`, `formatActions`, `parseActions`, `encodeActions`.
|
|
92
|
+
|
|
93
|
+
## Derleyicinin isim çözümleme modeli
|
|
94
|
+
|
|
95
|
+
Yerel değişkenler ve parametreler register'lara bağlanır. Closure'ların yakaladığı değişkenler activation nesnesindeki slotlara konur. Diğer bütün isimler, sınıfın açık namespace kümesiyle bir `Multiname` olarak üretilir ve VM tarafından scope zinciri üzerinden çözülür. Flex derleyicisi de önceden bağlayamadığı isimler için aynısını yapar. Tip açıklamaları (`var x:Foo`, parametreler, dönüş tipleri) import'lar, aynı paket, top-level sınıflar ve SWF'in kendi sabit havuzu kullanılarak QName'e çözülür. Bu sayede `playerglobal.swc` gerekmez.
|
|
96
|
+
|
|
97
|
+
Kurucusu olmayan sınıflarda, sabit olmayan alan başlangıç değerleri için örtük bir kurucu üretilir. Bu değerler, Flex'te olduğu gibi `super()` çağrısından önce atanır.
|
|
98
|
+
|
|
99
|
+
Desteklenen dil özellikleri: sınıflar, interface'ler, kalıtım, `super`, getter/setter, static üyeler, const, varsayılan ve `...rest` parametreleri, closure'lar, bütün döngü türleri (etiketli break/continue dahil), switch, try/catch/finally, `with`, regex, Vector, nesne ve dizi literal'leri, `as`/`is`/`instanceof`/`in`/`typeof`/`delete`, bileşik atamalar (`&&=` ve `||=` dahil), E4X erişimleri (`.@attr`, `..child`, `.(filtre)`) ve XML literal'leri (çalışma zamanında `new XML(...)` olarak).
|
|
100
|
+
|
|
101
|
+
## Testler
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm test
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Testler Node'un yerleşik `node:test` modülüyle yazıldı. Kapsadıkları:
|
|
108
|
+
|
|
109
|
+
- LZMA, SWF container ve ABC round-trip'leri, P-code round-trip'i ve doğrulayıcı.
|
|
110
|
+
- Parser, derleyici ve decompile → derle → decompile kararlılığı.
|
|
111
|
+
- PNG, ses ve AVM1 round-trip'leri.
|
|
112
|
+
|
|
113
|
+
[Ruffle](https://ruffle.rs) kuruluysa (`/Applications/Ruffle.app` ya da `RUFFLE=/yol/ruffle`) derlenen test programı gerçek bir Flash VM'de çalıştırılır ve 59 çalışma zamanı kontrolü doğrulanır. Ruffle yoksa bu test atlanır.
|
|
114
|
+
|
|
115
|
+
## Sınırlamalar
|
|
116
|
+
|
|
117
|
+
- **Derleyici tip denetimi yapmaz.** Tip hataları ancak çalışma zamanında ortaya çıkar. Arayüz uyumu ve override imzaları da denetlenmez.
|
|
118
|
+
- **finally:** `finally` blokları normal çıkış, `return`, `break` ve `continue` yollarına kopyalanır.
|
|
119
|
+
- **Namespace bildirimi:** Paket seviyesinde namespace bildirimleri (`public namespace x = "..."`) derlenmez. Var olan namespace'ler `use namespace` ve `ns::isim` ile kullanılabilir.
|
|
120
|
+
- **XML literal'leri:** `{ifade}` gömme desteklenmez.
|
|
121
|
+
- **Decompiler:** Flex/ASC çıktısında iyi sonuç verir. Obfuscate edilmiş kodda başarısız olan metodlar P-code olarak yorum satırında gösterilir.
|
|
122
|
+
- **Kaynaklar:** Fontlar ve shape/sprite vektör çizimleri dönüştürülmez, ham tag olarak korunur. JPEG3/4 alfa kanalı ayrı bir maske PNG'si olarak dışa aktarılır. Nellymoser ve Speex sesleri ham veri olarak çıkarılır.
|
|
123
|
+
|
|
124
|
+
## Lisans
|
|
125
|
+
|
|
126
|
+
MIT
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
export interface NamespaceInfo {
|
|
2
|
+
kind: number;
|
|
3
|
+
/** String pool index (0 = no name). */
|
|
4
|
+
name: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A multiname pool entry. Only the fields relevant for `kind` are meaningful:
|
|
8
|
+
* - QName(A): ns, name
|
|
9
|
+
* - RTQName(A): name
|
|
10
|
+
* - RTQNameL(A): –
|
|
11
|
+
* - Multiname(A): name, nsSet
|
|
12
|
+
* - MultinameL(A): nsSet
|
|
13
|
+
* - TypeName: base, params
|
|
14
|
+
*/
|
|
15
|
+
export interface MultinameInfo {
|
|
16
|
+
kind: number;
|
|
17
|
+
ns: number;
|
|
18
|
+
name: number;
|
|
19
|
+
nsSet: number;
|
|
20
|
+
base: number;
|
|
21
|
+
params: number[];
|
|
22
|
+
}
|
|
23
|
+
export interface OptionalParam {
|
|
24
|
+
kind: number;
|
|
25
|
+
value: number;
|
|
26
|
+
}
|
|
27
|
+
export interface MethodInfo {
|
|
28
|
+
paramTypes: number[];
|
|
29
|
+
returnType: number;
|
|
30
|
+
name: number;
|
|
31
|
+
flags: number;
|
|
32
|
+
optional: OptionalParam[];
|
|
33
|
+
paramNames: number[];
|
|
34
|
+
}
|
|
35
|
+
export interface MetadataInfo {
|
|
36
|
+
name: number;
|
|
37
|
+
keys: number[];
|
|
38
|
+
values: number[];
|
|
39
|
+
}
|
|
40
|
+
export interface Trait {
|
|
41
|
+
name: number;
|
|
42
|
+
kind: number;
|
|
43
|
+
/** Upper 4 bits of the kind byte (Final / Override / Metadata). */
|
|
44
|
+
attrs: number;
|
|
45
|
+
/** slot_id for Slot/Const/Class/Function, disp_id for Method/Getter/Setter. */
|
|
46
|
+
id: number;
|
|
47
|
+
/** Slot/Const: type multiname. */
|
|
48
|
+
typeName: number;
|
|
49
|
+
/** Slot/Const: default value index (0 = none). */
|
|
50
|
+
valueIndex: number;
|
|
51
|
+
/** Slot/Const: default value kind (only if valueIndex != 0). */
|
|
52
|
+
valueKind: number;
|
|
53
|
+
/** Class: class index. */
|
|
54
|
+
classIndex: number;
|
|
55
|
+
/** Method/Getter/Setter/Function: method index. */
|
|
56
|
+
method: number;
|
|
57
|
+
metadata: number[];
|
|
58
|
+
}
|
|
59
|
+
export interface InstanceInfo {
|
|
60
|
+
name: number;
|
|
61
|
+
superName: number;
|
|
62
|
+
flags: number;
|
|
63
|
+
protectedNs: number;
|
|
64
|
+
interfaces: number[];
|
|
65
|
+
iinit: number;
|
|
66
|
+
traits: Trait[];
|
|
67
|
+
}
|
|
68
|
+
export interface ClassInfo {
|
|
69
|
+
cinit: number;
|
|
70
|
+
traits: Trait[];
|
|
71
|
+
}
|
|
72
|
+
export interface ScriptInfo {
|
|
73
|
+
init: number;
|
|
74
|
+
traits: Trait[];
|
|
75
|
+
}
|
|
76
|
+
export interface ExceptionInfo {
|
|
77
|
+
from: number;
|
|
78
|
+
to: number;
|
|
79
|
+
target: number;
|
|
80
|
+
excType: number;
|
|
81
|
+
varName: number;
|
|
82
|
+
}
|
|
83
|
+
export interface MethodBody {
|
|
84
|
+
method: number;
|
|
85
|
+
maxStack: number;
|
|
86
|
+
localCount: number;
|
|
87
|
+
initScopeDepth: number;
|
|
88
|
+
maxScopeDepth: number;
|
|
89
|
+
code: Uint8Array;
|
|
90
|
+
exceptions: ExceptionInfo[];
|
|
91
|
+
traits: Trait[];
|
|
92
|
+
}
|
|
93
|
+
export declare function emptyMultiname(kind?: number): MultinameInfo;
|
|
94
|
+
export declare function newTrait(partial: Partial<Trait> & {
|
|
95
|
+
name: number;
|
|
96
|
+
kind: number;
|
|
97
|
+
}): Trait;
|
|
98
|
+
/** A parsed ActionScript Byte Code (ABC) file. */
|
|
99
|
+
export declare class AbcFile {
|
|
100
|
+
minorVersion: number;
|
|
101
|
+
majorVersion: number;
|
|
102
|
+
ints: number[];
|
|
103
|
+
uints: number[];
|
|
104
|
+
doubles: number[];
|
|
105
|
+
strings: string[];
|
|
106
|
+
namespaces: NamespaceInfo[];
|
|
107
|
+
nsSets: number[][];
|
|
108
|
+
multinames: MultinameInfo[];
|
|
109
|
+
methods: MethodInfo[];
|
|
110
|
+
metadata: MetadataInfo[];
|
|
111
|
+
instances: InstanceInfo[];
|
|
112
|
+
classes: ClassInfo[];
|
|
113
|
+
scripts: ScriptInfo[];
|
|
114
|
+
bodies: MethodBody[];
|
|
115
|
+
/** Raw bytes of strings that are not valid UTF-8, keyed by pool index. */
|
|
116
|
+
private rawStrings;
|
|
117
|
+
/** Pools whose count was written as 1 (instead of 0) while empty; preserved for exact round-trips. */
|
|
118
|
+
private onePools;
|
|
119
|
+
private readonly intCache;
|
|
120
|
+
private readonly uintCache;
|
|
121
|
+
private readonly doubleCache;
|
|
122
|
+
private readonly stringCache;
|
|
123
|
+
private readonly nsCache;
|
|
124
|
+
private readonly nsSetCache;
|
|
125
|
+
private readonly mnCache;
|
|
126
|
+
private bodyIndex;
|
|
127
|
+
private bodyIndexSize;
|
|
128
|
+
static parse(bytes: Uint8Array): AbcFile;
|
|
129
|
+
toBytes(): Uint8Array;
|
|
130
|
+
/** String pool index for `s` (adds it if missing). */
|
|
131
|
+
string(s: string): number;
|
|
132
|
+
int(v: number): number;
|
|
133
|
+
uint(v: number): number;
|
|
134
|
+
double(v: number): number;
|
|
135
|
+
/** Namespace pool index. `PrivateNs` entries are always created fresh unless `reuse` is set. */
|
|
136
|
+
namespace(kind: number, name: string | number, reuse?: boolean): number;
|
|
137
|
+
packageNamespace(name: string): number;
|
|
138
|
+
nsSet(namespaces: number[]): number;
|
|
139
|
+
multiname(info: Partial<MultinameInfo> & {
|
|
140
|
+
kind: number;
|
|
141
|
+
}): number;
|
|
142
|
+
/** QName multiname index. `ns` may be a namespace index or a package name. */
|
|
143
|
+
qname(ns: number | string, name: string): number;
|
|
144
|
+
/** QName for a fully qualified name like "flash.display.Sprite" (or "flash.display:Sprite"). */
|
|
145
|
+
qnameFor(qualified: string): number;
|
|
146
|
+
/** Method body for a method index, if the method has one. */
|
|
147
|
+
methodBody(methodIndex: number): MethodBody | undefined;
|
|
148
|
+
/** Namespace URI string (empty for the public/unnamed namespace). */
|
|
149
|
+
namespaceName(nsIndex: number): string;
|
|
150
|
+
/** Local name of a multiname ("*" if any). */
|
|
151
|
+
multinameName(mnIndex: number): string;
|
|
152
|
+
/**
|
|
153
|
+
* Fully qualified dotted name of a multiname, e.g. "flash.display.Sprite".
|
|
154
|
+
* For non-QName multinames this is just the local name.
|
|
155
|
+
*/
|
|
156
|
+
qualifiedName(mnIndex: number): string;
|
|
157
|
+
/** Fully qualified name of class `classIndex`. */
|
|
158
|
+
className(classIndex: number): string;
|
|
159
|
+
/** Class index by fully qualified name ("com.example.Foo" or "com.example:Foo"); -1 if not found. */
|
|
160
|
+
findClass(qualified: string): number;
|
|
161
|
+
/** Names of all classes defined in this ABC. */
|
|
162
|
+
classNames(): string[];
|
|
163
|
+
}
|
|
164
|
+
/** Split "a.b.C" / "a.b:C" into package and local name. */
|
|
165
|
+
export declare function splitQualifiedName(qualified: string): {
|
|
166
|
+
pkg: string;
|
|
167
|
+
name: string;
|
|
168
|
+
};
|