Skip to content

Instantly share code, notes, and snippets.

@AvalonWot
Forked from Herschel/Haxe Format ABC example
Created November 25, 2022 02:58
Show Gist options
  • Save AvalonWot/3b0d3be3bb12acb3c7b887901bf47eb6 to your computer and use it in GitHub Desktop.
Save AvalonWot/3b0d3be3bb12acb3c7b887901bf47eb6 to your computer and use it in GitHub Desktop.
Example of using the Haxe format lib to parse and modify Flash ABC bytecode
package;
import haxe.io.Bytes;
import haxe.io.BytesInput;
import haxe.io.BytesOutput;
import haxe.Resource;
import format.abc.Data;
using Main;
class Main {
static function main() {
new Main();
}
public function new() {
var swfInput = new BytesInput( Resource.getBytes( "in.swf" ) );
var swfReader = new format.swf.Reader( swfInput );
var swf = swfReader.read();
for( i in 0...swf.tags.length ) {
var tag = swf.tags[i];
switch( tag ) {
case TSymbolClass( classes ):
trace( 'Class linkage: $classes' );
case TActionScript3( abcBytes, other ):
swf.tags[i] = TActionScript3( transformAbc( abcBytes ) );
case _:
}
}
var swfOutput = new BytesOutput();
var swfWriter = new format.swf.Writer( swfOutput );
swfWriter.write( swf );
// swfOutput.getBytes() now returns the modified SWF, which you can write to disk.
}
function transformAbc( abcBytes : Bytes )
{
var abcInput = new BytesInput( abcBytes );
var abcReader = new format.abc.Reader( abcInput );
var abcData = abcReader.read();
for( cls in abcData.classes ) {
switch( abcData.getName( cls.name ) ) {
case NName( name, ns ):
var nameString = abcData.getString( name );
var newNameString = '${nameString}_Modified';
abcData.setString( name, newNameString);
trace( 'Class: $nameString changed to $newNameString' );
case _:
throw "Unexpected class name";
}
}
for( f in abcData.functions ) {
var code = format.abc.OpReader.decode( new BytesInput( f.code ) );
trace( code );
}
var abcOutput = new BytesOutput();
var abcWriter = new format.abc.Writer( abcOutput );
abcWriter.write( abcData );
return abcOutput.getBytes();
}
// Static extensions for easier dereferencing of indices
public static function getName( abcData : format.abc.Data.ABCData, idx : Index<Name> ) : Name {
switch( idx ) {
case Idx(i): return abcData.names[i-1];
}
}
public static function getString( abcData : format.abc.Data.ABCData, idx : Index<String> ) : String {
switch( idx ) {
case Idx(i): return abcData.strings[i-1];
}
}
public static function setString( abcData : format.abc.Data.ABCData, idx : Index<String>, value : String ) {
switch( idx ) {
case Idx(i): abcData.strings[i-1] = value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment