rayyaw's SWF patcher
Project description
rayyaw's SWF Patcher
CI/CD
PyPI
Requirements
Build Dependencies
To compile this project yourself, you must install ANTLR. You can view more information at https://www.antlr.org/. For most linux distributions, this will be available as antlr4
through your package manager.
Runtime Dependencies
You must install JPEXS Free Flash Decompiler to use this patcher. For more information, check https://github.com/jindrapetrik/jpexs-decompiler. This will need to be installed manually.
Flash Patcher will automatically detect your FFDec install location.
You must have Python 3.10 or greater on your system to run this script, including the antlr4-python3-runtime
pip package. This will be installed and verified automatically when installing through pip.
Testing
To run unit tests, simply run make test
from the build
folder. You must have pytest
and coverage
installed to run unit tests.
Installing and running
To apply a patch, run the flash-patcher
command.
The patcher will take the input SWF, apply the patches specified in the stage file (which must be located in the patch folder), and create the output SWF.
The recommended way to install Flash Patcher is through pip. You can do this with pip install flash-patcher
.
If you want to build the Flash Patcher .whl file locally, run cd build && make
. The .whl will be generated in the dist/ folder. The hatch
pip package is required to run the build. You can also run make install
to install the package locally. Note that this will run pip with --break-system-packages
and --force-reinstall
options, so use this at your own risk.
The command line arguments are as follows:
Required arguments
--inputswf
: The input SWF to use. You should create a base hack to avoid issues with Flash deobfuscation.--folder
: The top-level folder where all your patch, asset, and stage files are located.--stagefile
: The stage file's path within the top level folder.--outputswf
: The path to save the output swf (relative to the current path)
Example: $PATCHER --inputswf $SWF_FILE_PATH/SMF_Base_Hack.swf --folder . --stagefile fullgame.stage --outputswf SMF-Fullgame-Build-$1.swf
Optional arguments
--invalidateCache
: Force the patcher to decompile the SWF. If this flag is not set, Flash Patcher may use a cached version of the SWF decompilation to speed up the process.--all
: Recompile the full SWF. This is required when injecting asset packs but slows down recompilation.--xml
: Inject in xml mode. This decompiles the .swf to .xml and allows you to modify the xml file.
File Structure
You should create the following file structure for your patches:
- Create a top-level patch folder. You will put all your files in this folder.
- Create one or more patch stage files. These specify which patches to apply.
- Create one or more patch files. These contain the code to inject into the SWF.
Patch Stage Files
A patch stage file (usually ending in .stage), may look something like this:
# Comment
patch1.patch
subfolder/patch2.patch
subfolder/pack.assets
script.py
You can use # to comment out certain lines. Each line contains a patch file to run, and each injected file must be in the same top-level patch folder as the stage file. When the patcher runs, it will apply each patch file in order.
Patch Files
A patch file (which must end in .patch), may look something like this:
# Comment
add DefineSprite_1058 boss2/DoAction.as 789
begin-patch
_root.gotoAndStop(15);
// cmd: skip 15
end-patch
remove frame_1/DoAction.as 789-1111
Every patch file consists of a set of commands, separated by newlines. You can use # to write comments. The first parameter to any command is the file to modify (in this case, "DefineSprite_1058 boss2/DoAction.as" or "frame_1/DoAction.as"). To find the name of this, export all scripts using FFDec and make a note of the file name you want to modify.
add
command
You are allowed to put multiple add
statements before a code block you wish to inject.
The first parameter to the add or remove command is always the name of the file to inject into.
The add and remove parameters can come in the following forms:
add file.as 567
. This will inject at line 567 infile.as
.add file.as end
. This will inject at the end offile.as
.add file.as function Mainfunc
. This will inject after the definition ofMainfunc
infile.as
.add file.as function Mainfunc 15
. This will inject after the definition ofMainfunc
infile.as
, with an offset of 15 lines from the start ofMainfunc
.
remove
command
Note that remove
commands are inclusive of the final line.
Here is an example remove
command. Note that you can still use the function
and end
targets as shown above.
remove file.as 567-568
. This will remove lines 567 to 568 offile.as
.
replace
command
Note that just like add
, you can put multiple replace
statements before a code block.
Here is an example replace
command. Note that you can still use the function
and end
targets as shown above, as well as any // cmd:
commands.
replace file.as 3
begin-content
A
end-content
begin-patch
B
end-patch
This will look for the 3rd instance of A
in file.as
, and replace it with B
.
Putting a function + offset of N instead of a raw number will find and replace the Nth instance of the content after the function header, and putting end
will replace the last instance of the content.
replace-all
command
As with the other commands, you can have multiple replace-all
headers before the blocks. The syntax is mostly the same as the replace command, with the content
and patch
blocks operating in the same way. However, the header is changed:
replace-all file.as
We only need to specify the filename, as nothing else is used.
Caveats
There are several limitations that come with the replace-all
command:
- You may not use both
replace
andreplace-all
headers for the same block, as this is invalid syntax. replace-all
blocks do not support secondary commands.
Content Insertion
For the add command, all lines up to (but not including) the end-patch
command will be inserted into the SWF, on the specified line. For the remove command, all lines between the two numbers specified will be removed (and this is inclusive).
After one or more add commands, add a newline, a begin-patch\n
and then enter your code block. At the end of the block, add a newline and end-patch
to tell the patcher the patch is finished.
Secondary commands
Within a code block, you can also use the following syntax to skip ahead within the file:
// cmd: skip N
Type // cmd: skip
(with spaces as shown), then the number of lines you wish to skip without modifying.
To inject while in XML mode, use normal .patch
files, but the add location will be the hardcoded string swf.xml
.
Asset Packs
An asset pack file (which must end in .assets), contains instructions on assets to inject into the Flash file. Currently supported types include:
- Images
- Sounds
- Shapes
- Text
The file will look something like this:
# Comment
add-asset localfolder/derp.png images/8.png
This asset pack file takes the local file at localfolder/derp.png
and copies it to images/8.png
within the SWF. If there was already a file named images/8.png
, it will be overwritten with the new file.
Python Files
Arbitrary Python scripts can be referenced in the stage file. They should be placed in the patch folder, and will be executed inside the decompiled directory, with the following API:
- Only Python 3 is supported.
- The name of the Python file must not contain spaces.
- You must print a list of files that are modified. This list must be comma-separated and formatted in UTF-8.
An example of such a list: DoAction1.as, DoAction2.as
. Trailing whitespace or newlines are fine, as those will be stripped off.
Injection Order
Patchfiles and asset packs will be applied in the order that they are specified in the stage file. Within each patchfile, the patches will be processed one block at a time, with each add
or remove
being processed from the top of the file to the bottom. Note that if you are injecting multiple times into the same file, this means that you should inject bottom to top to avoid the line numbers changing as the file is being patched.
Licensing
This code is made available under CC-BY SA 4.0. For more information, check https://creativecommons.org/licenses/by-sa/4.0 .
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for flash_patcher-5.2.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | da612230645e9a545247d9e0ae93226359ecfe3fda72aa2545139e2cfd24a7c6 |
|
MD5 | 96b90549bc86502384ca0d669523b342 |
|
BLAKE2b-256 | 78ac48c0e6a2feb2c0a12211c78ab548be60b95473208e22e3bdd63069b95607 |