Reverse Engineering Super Smash Flash
I made a Sonic Battle Hacking Discord Server, filled with a bunch of people who like modding Sonic Battle for the GBA. Somebody in this Discord Server asked me to check out Super Smash Flash 2 Beta v1.1.0.1 because their old modding tools didnât work for it.
The SSF2 developers have had a strong stance against modding, which I personally thing is poor considering theyâre making a non-profit game. That of course didnât stop me from digging into the game.
I used the JPEXS Flash decompiler to inspect the code. SSF2 is written in ActionScript, which is very similar to other OOP languages. The first thing I noticed was that nothing was obfuscated, which made it easy to find some things, except some of the core resource loading was obfuscated (manually?).
The resource files are in a âhiddenâ ssf format. The files in the resources
folder are named DAT1.ssf, DAT2.ssf, DAT3.ssf, etc. These files are âencryptedâ
SWF files. All we need is to figure out how do decode these into the SWF format
and have JPEXS do the rest.
Inspecting these ssfs shows us a couple things:
- Theyâre ZLIB compressed
- Thereâs a mystery header before the SWF header
- Modifying this header breaks loading the resource
This tells us something in the code has to be decompressing them.
I disassembled the game using JPEXS and grepped the code for ZLIB.
Instantly had one hit in com/mcleodgaming/ssf2/util/Resource.as.
wellthatwaseasy.jpg
The code containing the string is:
var c: ByteArray = null;
var l: int = 0;
var n: int = 0;
var x: int = 0;
var b: ByteArray = m_urlLoader.data as ByteArray;
c = new ByteArray();
try {
b.uncompress(CompressionAlgorithm.ZLIB);
l = b.readInt();
n = b.readInt();
for (x = 0; x < n; x++) {
b.readInt();
}
c.writeBytes(b,b.position,l);
b = c;
c = null;
}
Letâs disect this code a bit.
- At the beginning,
bis our resource file that is loaded into aByteArray - A new
ByteArray,c, is constructed to obfuscate things bis decompressed using ZLIB- The beginning two ints in
bare stored inlandn - We then read
nints out ofb - The bytes in
bfrom[b.position, l)are copied toc bis set to the bytes we just copied tob, truncating the original array tol
Whatâs really going on here? b starts off with the length of the SWF data (l)
and the length of the mystery header (n). This mystery header doesnât actually
contain any information, itâs skipped right over!
Hereâs what a decompressed .ssf file contains:
- 4 bytes to indicate the size of the SWF in bytes
- 4 bytes to indicate the size of the garbage data in bytes
- Any number of random, useless bytes, as indicated by #2
- The SWF itself prefixed by the typical SWF header,
FWS
Whatâs next? Write a tool to generate the headers!
I chose to write in in Kotlin since it is a language I enjoy. The GUI code doesnât matter much, only the compressing / decompressing.
Hereâs the pseudocode to compress a .ssf:
def compress(file: SWF):
buffer = new ByteBuffer()
buffer += file.length as Int32 # we want to truncate it to 4 bytes
buffer += 0 as Int32 # 4 bytes for 'n' described above
# we don't need any garbage data since we set
# the length of the garbage data to 0 above
buffer += file.bytes
compressed = zlibCompress(buffer)
write(compressed, file.withExtension(".ssf"))
Pretty simple! Hereâs the pseudocode to decompress a .ssf:
def decompress(file: SSF):
bytes = zlibDecompress(file.bytes)
garbageLength = bytes[1]
swfBytes = bytes[garbageLength..]
write(swfBytes, file.withExtension(".swf"))
And thatâs it! Weâve got an SSF2 resource (de)compresser! There are other things
encrypted in the code, like what characters / stages are in what .ssf files,
but Iâll probably get to that soon.
Hereâs an example mod that changes Pichuâs name.

The code is available on GitHub. I made it in one night, so I didnât take time to make it look good or anything, but it works.
Thanks to the other SSF2 modders who introduced me to the game!