How to edit ActionScript 3 from iggy files
Nov 1, 2016 22:07:37 GMT
Val E Ryon, The Mad Titan, and 7 more like this
Post by eternity on Nov 1, 2016 22:07:37 GMT
Requeriments of the tutorial:
- iggy_as3_test from my tools thread.
- JPEXS Free Flash Decompiler from its homepage.
- Programming knowledge. Not necessarily ActionScript3 (I don't know it myself, this is the first flash-related thing I do in my life), but if you know a language close to it like Java or C#, you won't have problems understanding the code.
For method 2 and 3:
- Assembler knowledge is definitely welcome, because the edit will be done in the asm code of ActionScript 3, and not in AS3 itself. In concrete, the knowledge of some stack-based machine assembler (like Java or .net vm) is ideal, because the AS3 vm is a stack-based machine.
-----
In this tutorial, we will remove the randomness from the "Random" button in the character selection screen. We will make it so it just select a random costume/skin of the current selected character, instead of random character+costume. Something simple enough.
I will provide three different methods, all of them do the same. You probably want to use method 1, as it is the only one it doesn't require as3 asm.
Method 1
This method requires the additional following downloads:
- Download Adobe Flex Sdk 4.6 from its official page. (it is freeware, don't worry).
- You will need a 32 bits version of the Java VM. Even if you already have Java installed, you probably have the 64 bits version, but adobe flex sdk needs the 32 bits version.
Download from here. (Select the windows offline version, the non-64 one).
Install Java first. Then, extract adobe flex sdk 4.6 somewhere in your system. I recommend to stick to a short path without spaces, like C:\flex_sdk_4.6
Now, next step is optional but totally recommended: add C:\flex_sdk_4.6\bin to the PATH variable of your system, so that you can call the compiler (mxmlc) from any folder.
So, once you have all that done, get the file data/ui/iggy/CHARASELE.iggy from the game, and drag it to iggy_as3_test. A swf file will be generated. This is a dummy swf file that only contains AS3 bytecode.
Open the file with JPEXS Free Flash Decompiler. In the tree at the left, select the scripts folder, righ click, export selection. Click ok, and select a folder in your system. It would be a good idea if you select an empty folder here, one created for this.
So now, it is time to modify and recompile the code. I will assume that you put the flex sdk in the path variable, and that you are now in a command line, in the directory where the scripts were extracted (but not inside the scripts folder).
Before continuing, I want to mention a thing here. There is a gui tool for the flex sdk called FlashDevelop, but we cannot use it. FlashDevelop forces a flag into the compiler ("incremental" option) that cannot be disabled, and which generates a swf with multiple bytecode sections, which iggy_as3_test doesn't like. So we don't have more options than to use the compiler from command line. You could still use FlashDevelop to edit the code, but you must do the compilation in the command line.
Before editing the code of the random key, we need to edit another thing, it is a workaround to a compiler issue.
Open the file scripts/CHARASELE_fla/MainTimeline.as with a text editor of your choice. Somewhere in the class, declare a dummy variable containing the name of the rest of files (classes) of CHARASELE_fla directory. As illustrated int his screenshot:
"Why are wo doing this?" you may wonder. The answer: the compiler can only handle a single ".as" file argument. The compiler will automatically include all files that file uses, and the files that those files, use, etc recursively and add it to the swf. But those files I put there are unused by the rest of the code. And even if unused, they are needed by the game (or something odd happens). So a way to solve this problem is to trick the compiler into including them, by declaring those dummy variables in the screenshot.
Now open the file scripts/action_script/CharaSele.as. Navigate to the pushKeyRandom, which contains the implementation of the random button. You'll noticetwo calls to Math.random in this method, one to select a random character, and another one to select a random costume/skin of that character. We will remove the first one.
So this code:
After the random+floor, _loc3_ will contain the displacement to apply to the current character to select the next one. If we make _loc3_ 0, the selected character will stay in place.
So, we want to remove that whole "if" so that _loc3 stays at 0.
So do it, leave only the "var _loc3_:int = 0"
Save the file, and time to compile.
The file we will compile will be scripts/CHARASELE_fla/MainTimeline.as. The compiler will be able to automatically find the rest of the classes.
Run the compiler like this:
You will get some warnings, but they can be ignored safely. A file called MainTimeline.swf will be generated at scripts/CHARASELE_fla/. Rename to CHARASELE.swf. Some smart guy may notice here that this swf is too much smaller than the one my program extracted. Don't panic! The compiler generates compressed swf, while my tool always generates uncompressed ones, that's the reason.
So now, just put the CHARASELE.swf in the same directory than CHARASELE.iggy, drag the .swf file into iggy_as3_test, and the file CHARASELE.iggy will be modified. You can now test it in game.
Method 2
So, get the file data/ui/iggy/CHARASELE.iggy from the game, and drag it to iggy_as3_test. A swf file will be generated. This is a dummy swf file that only contains AS3 bytecode.
Open the file with JPEXS Free Flash Decompiler.
The part of the source code that we are gonna modify is in scripts/action_script/CharaSele
Navigate to the "pushKeyRandom" method in the code. There are two calls to Math.random in this method, one to select a random character, and another one to select a random costume/skin of that character. We will remove the first one.
Well, this is the method that is called when the random key is pressed in the character selection screen. There are two calls to Math.random in this method, one to select a random character, and another one to select a random costume/skin of that character. We will remove the first one.
So look at these lines:
After the random+floor, _loc3_ will contain the displacement to apply to the current character to select the next one. If we make _loc3_ 0, the selected character will stay in place.
So, we want to remove that whole "if" so that the _loc3 stays at 0.
You may be tempted to use the "Edit ActionScript" button below, but don't do it. That feature is totally experimental and seems to corrupt the code.
We will edit the assembler code at the right.
The selected code in this screenshot contains the whole if in the AS3 assembler:
A small explanation of the asm code:
The "getlocal_2" instruction pushes the _loc2_ variable into the stack.
The "pushbyte 1" instruction pushes the constant 1 into the stack.
The instruction "ifngt ofs0080" pops the two previous paraemters from the stack, performs a comparison, and jumps to offs0080 if the first parameter (_loc2_) is not greater than the second parameter (1). That's the if condition itself. The rest of the selected code would be the body of the "if".
So, press the "Edit P-code" button and remove the selected text.
Click Save. Also click the "Save" button in the main toolbar, or the swf file won't be modified.
Now drag the CHARASELE.swf file into the iggy_as3_test program. (the file CHARASELE.iggy must also be there).
Now you can test the CHARASELE.iggy file in the game.
Method 3
Tool used in this alternate method:
github.com/CyberShadow/RABCDAsm
Steps:
- Use my iggy_as3_test from command line "iggy_as3_test CHARASELE.iggy CHARASELE.abc". This will make my tool to output an .abc (actionscript3 byte code) file instead of a swf file.
- Use "rabcdsasm CHARASELE.abc" to disassemble the file. You will get a folder called CHARASELE.abc
- The code for the CharaSele class will be in "CHARSELE/action_script/CharaSele.class.asasm"
- That file can be edited just like with the jpexs previous method. Label names may differ, but it is essentially the same.
- To reassemble the file, use "rabcasm CHARASELE/CHARASELE.main.asasm"
- A file CHARASELE.main.abc is generated in CHARASELE directory. Rename it to CHARASELE.abc, and insert it in iggy_as3_test.
----
Using the trace debug function to output messages to a file
Requirement: xv2patcher 0.3 or later (in my tools thread).
I will assume that you are using "method 1". You can use the AS3 "trace" function to output things and help with debugging. Notice how the CHARASELE.as file has some "hello" messages from the developers using that function
By default, the mxmlc compiler removes all traces when generating code. To keep them, you must compile like this:
Notice the "-omit-trace-statements=false". Now the remaining thing is to configure xv2patcher to output iggy traces.
Edit the file XV2PATCHER/xv2patcher.ini. Set the variable "iggy_debug" in the Patches section (which is defaulted to false) to true.
That's it, now you can run the game. Output messages will be output to the file XV2PATCHER/xv2_log.txt. All iggy related messages will start with "IGGY".
Make sure that XV2PATCHER directory is writable (in a default Steam installation, it will be) or the xv2_log.txt won't be able to be created.
- iggy_as3_test from my tools thread.
- JPEXS Free Flash Decompiler from its homepage.
- Programming knowledge. Not necessarily ActionScript3 (I don't know it myself, this is the first flash-related thing I do in my life), but if you know a language close to it like Java or C#, you won't have problems understanding the code.
For method 2 and 3:
- Assembler knowledge is definitely welcome, because the edit will be done in the asm code of ActionScript 3, and not in AS3 itself. In concrete, the knowledge of some stack-based machine assembler (like Java or .net vm) is ideal, because the AS3 vm is a stack-based machine.
-----
In this tutorial, we will remove the randomness from the "Random" button in the character selection screen. We will make it so it just select a random costume/skin of the current selected character, instead of random character+costume. Something simple enough.
I will provide three different methods, all of them do the same. You probably want to use method 1, as it is the only one it doesn't require as3 asm.
Method 1
This method requires the additional following downloads:
- Download Adobe Flex Sdk 4.6 from its official page. (it is freeware, don't worry).
- You will need a 32 bits version of the Java VM. Even if you already have Java installed, you probably have the 64 bits version, but adobe flex sdk needs the 32 bits version.
Download from here. (Select the windows offline version, the non-64 one).
Install Java first. Then, extract adobe flex sdk 4.6 somewhere in your system. I recommend to stick to a short path without spaces, like C:\flex_sdk_4.6
Now, next step is optional but totally recommended: add C:\flex_sdk_4.6\bin to the PATH variable of your system, so that you can call the compiler (mxmlc) from any folder.
So, once you have all that done, get the file data/ui/iggy/CHARASELE.iggy from the game, and drag it to iggy_as3_test. A swf file will be generated. This is a dummy swf file that only contains AS3 bytecode.
Open the file with JPEXS Free Flash Decompiler. In the tree at the left, select the scripts folder, righ click, export selection. Click ok, and select a folder in your system. It would be a good idea if you select an empty folder here, one created for this.
So now, it is time to modify and recompile the code. I will assume that you put the flex sdk in the path variable, and that you are now in a command line, in the directory where the scripts were extracted (but not inside the scripts folder).
Before continuing, I want to mention a thing here. There is a gui tool for the flex sdk called FlashDevelop, but we cannot use it. FlashDevelop forces a flag into the compiler ("incremental" option) that cannot be disabled, and which generates a swf with multiple bytecode sections, which iggy_as3_test doesn't like. So we don't have more options than to use the compiler from command line. You could still use FlashDevelop to edit the code, but you must do the compilation in the command line.
Before editing the code of the random key, we need to edit another thing, it is a workaround to a compiler issue.
Open the file scripts/CHARASELE_fla/MainTimeline.as with a text editor of your choice. Somewhere in the class, declare a dummy variable containing the name of the rest of files (classes) of CHARASELE_fla directory. As illustrated int his screenshot:
"Why are wo doing this?" you may wonder. The answer: the compiler can only handle a single ".as" file argument. The compiler will automatically include all files that file uses, and the files that those files, use, etc recursively and add it to the swf. But those files I put there are unused by the rest of the code. And even if unused, they are needed by the game (or something odd happens). So a way to solve this problem is to trick the compiler into including them, by declaring those dummy variables in the screenshot.
Now open the file scripts/action_script/CharaSele.as. Navigate to the pushKeyRandom, which contains the implementation of the random button. You'll noticetwo calls to Math.random in this method, one to select a random character, and another one to select a random costume/skin of that character. We will remove the first one.
So this code:
var _loc3_:int = 0;
if(_loc2_ > 1)
{
_loc3_ = Math.floor(Math.random() * _loc2_);
}
After the random+floor, _loc3_ will contain the displacement to apply to the current character to select the next one. If we make _loc3_ 0, the selected character will stay in place.
So, we want to remove that whole "if" so that _loc3 stays at 0.
So do it, leave only the "var _loc3_:int = 0"
Save the file, and time to compile.
The file we will compile will be scripts/CHARASELE_fla/MainTimeline.as. The compiler will be able to automatically find the rest of the classes.
Run the compiler like this:
mxmlc -compiler.source-path=.\scripts .\scripts\CHARASELE_fla\MainTimeline.as
You will get some warnings, but they can be ignored safely. A file called MainTimeline.swf will be generated at scripts/CHARASELE_fla/. Rename to CHARASELE.swf. Some smart guy may notice here that this swf is too much smaller than the one my program extracted. Don't panic! The compiler generates compressed swf, while my tool always generates uncompressed ones, that's the reason.
So now, just put the CHARASELE.swf in the same directory than CHARASELE.iggy, drag the .swf file into iggy_as3_test, and the file CHARASELE.iggy will be modified. You can now test it in game.
Method 2
So, get the file data/ui/iggy/CHARASELE.iggy from the game, and drag it to iggy_as3_test. A swf file will be generated. This is a dummy swf file that only contains AS3 bytecode.
Open the file with JPEXS Free Flash Decompiler.
The part of the source code that we are gonna modify is in scripts/action_script/CharaSele
Navigate to the "pushKeyRandom" method in the code. There are two calls to Math.random in this method, one to select a random character, and another one to select a random costume/skin of that character. We will remove the first one.
Well, this is the method that is called when the random key is pressed in the character selection screen. There are two calls to Math.random in this method, one to select a random character, and another one to select a random costume/skin of that character. We will remove the first one.
So look at these lines:
var _loc3_:int = 0;
if(_loc2_ > 1)
{
_loc3_ = Math.floor(Math.random() * _loc2_);
}
After the random+floor, _loc3_ will contain the displacement to apply to the current character to select the next one. If we make _loc3_ 0, the selected character will stay in place.
So, we want to remove that whole "if" so that the _loc3 stays at 0.
You may be tempted to use the "Edit ActionScript" button below, but don't do it. That feature is totally experimental and seems to corrupt the code.
We will edit the assembler code at the right.
The selected code in this screenshot contains the whole if in the AS3 assembler:
A small explanation of the asm code:
The "getlocal_2" instruction pushes the _loc2_ variable into the stack.
The "pushbyte 1" instruction pushes the constant 1 into the stack.
The instruction "ifngt ofs0080" pops the two previous paraemters from the stack, performs a comparison, and jumps to offs0080 if the first parameter (_loc2_) is not greater than the second parameter (1). That's the if condition itself. The rest of the selected code would be the body of the "if".
So, press the "Edit P-code" button and remove the selected text.
Click Save. Also click the "Save" button in the main toolbar, or the swf file won't be modified.
Now drag the CHARASELE.swf file into the iggy_as3_test program. (the file CHARASELE.iggy must also be there).
Now you can test the CHARASELE.iggy file in the game.
Method 3
Tool used in this alternate method:
github.com/CyberShadow/RABCDAsm
Steps:
- Use my iggy_as3_test from command line "iggy_as3_test CHARASELE.iggy CHARASELE.abc". This will make my tool to output an .abc (actionscript3 byte code) file instead of a swf file.
- Use "rabcdsasm CHARASELE.abc" to disassemble the file. You will get a folder called CHARASELE.abc
- The code for the CharaSele class will be in "CHARSELE/action_script/CharaSele.class.asasm"
- That file can be edited just like with the jpexs previous method. Label names may differ, but it is essentially the same.
- To reassemble the file, use "rabcasm CHARASELE/CHARASELE.main.asasm"
- A file CHARASELE.main.abc is generated in CHARASELE directory. Rename it to CHARASELE.abc, and insert it in iggy_as3_test.
----
Using the trace debug function to output messages to a file
Requirement: xv2patcher 0.3 or later (in my tools thread).
I will assume that you are using "method 1". You can use the AS3 "trace" function to output things and help with debugging. Notice how the CHARASELE.as file has some "hello" messages from the developers using that function
By default, the mxmlc compiler removes all traces when generating code. To keep them, you must compile like this:
mxmlc -compiler.source-path=.\scripts -omit-trace-statements=false .\scripts\CHARASELE_fla\MainTimeline.as
Notice the "-omit-trace-statements=false". Now the remaining thing is to configure xv2patcher to output iggy traces.
Edit the file XV2PATCHER/xv2patcher.ini. Set the variable "iggy_debug" in the Patches section (which is defaulted to false) to true.
That's it, now you can run the game. Output messages will be output to the file XV2PATCHER/xv2_log.txt. All iggy related messages will start with "IGGY".
Make sure that XV2PATCHER directory is writable (in a default Steam installation, it will be) or the xv2_log.txt won't be able to be created.