raine's void to shout into

17 May 2025

Triode

by Raine

Triode: A Transistor/GSGE package editor

See the source code here: raineycat/Triode

What is it?

Triode is a tool to edit package files from Transistor and (eventually) other games using its engine. The project consists of a library to work with the files, a command-line tool to interact with them and eventually a GUI editor.

I also wrote a bunch of documentation on the file formats as I went through, available on the README :3

Why did I make it?

  1. Curiosity
  2. I was bored for a while
  3. I hadn’t seen any other (user-friendly) ways to do this
  4. Weird file formats make me really interested

How did I make it?

The project started with me looking through the game’s code in dnSpy, and getting distracted by several rabbit holes, until I ended up in the GameAssetManager class. It took quite a while of head-scratching before I got anywhere though; even though C# is trivial to decompile, a lot of control structures like switch statements get mangled during compilation.

I started out by writing a parser for package manifests, having to re-implement several of the engine’s texture atlas types. Eventually I could see all of the manifest entries printed out, and I celebrated appropriately (I silently cheered and then sat back down ^w^)

triode_manifest_print

This wasn’t it though. There were still the much larger package files to tackle. From the code, they followed a similar format to the manifest files, with the chunk-type format. This meant I could copy some of the previous code I wrote, just adding the two extra chunk types in. (below)

triode_chunk_types

However, it wasn’t this easy…

After digging into the decompressed package files, I could see that the actual image data is stored in XNB containers. This was slightly annoying, as I don’t want to make my tooling depend on the whole XNA framework, but I was also a bit tentative to write my own parser. However, I decided to just get on with it and wrote a basic parser for XNB files. Thankfully, since the format is quite old now, there was plenty of documentation and reference to look at.

One major hurdle I ran into was image loading, as sometimes the XNA content pipeline decides to compress textures. In all of the files I checked from transistor, either no compression or DXT5 is used. Since compression is complicated:tm:, I used a library called LibSquishNet to decompress them.

At this point, after lots of troubleshooting, I finally had PNG files being written to my output folder! The only issue was, thing looked a little too blue…

It turns out, while LibSquishNet outputted RGBA images, uncompressed XNB textures were stored as BGRA. This meant only some of the textures had their red and blue channels mixed up! It was a nightmare to figure out, but after lots of pain I managed to get the images extracting properly!

Finally, I had a way to dump all the assets from package files! I added a function to print out the names of external (Bink) video files that were being referenced, as well as telling me when a package tried to include another. While the extractor doesn’t (and won’t) handle these automatically, it’s interesting to know how the game is structured.

triode_dump_assets

Now, for the fun stuff!

While exploring Transistor’s package files, I’ve found some really interesting content left in the game! :3 Here are some of my favourites…

1. Pet Me!

triode_pet_me

In the file called Dev.pkg, we can see a bunch of textures that were presumably used as placeholders during development. Things like “Missing texture”, “Replace me” and “Script Target”. However, one stood out to me. In the inconspicuously named atlas called Dev_Textures01.png, theres one image of a cat with the text “Pet Me” above it. First of all, CUTE! Second of all, wonderful choice of placeholders :3 It would be fun to find out whose cat this is though, if anyone at Supergiant wants to hit me up ;3

2. Priests

triode_priest_tex3

If you’ve played Transistor before, you’ll recognise these guys as enemies called “Weeds”. They heal the other enemies around them, and at later levels do AOE damage to the player. However, I saw a file called Priest.pkg and got really curious. What could it be? Now I can finally open these files up, I could see that it was actually the internal name for these long bois! It’s really interesting to see reminders like this of how games are constantly iterated upon, and how things change so much from prototype to release.

3. Cut abilities?

triode_cut_abilities

While looking through the GUI.pkg file, containing all of the UI sprites for the game, these two icons stood out to me. They’re stored in a folder called GUI\Icons\Powers, which has the icons for all of the functions (abilities/upgrades) in the game, but the visual style seemed off. My best guess is that they were meant to be upgrades for the player, but were cut as they don’t seem like they would fit with the function system at the core of the game. Correct me if I’m wrong of course, but I think this is pretty cool :3

Wrapping up…

Of course there’s more I could mention here; datamining is one of my favourite hobbies after all! However:

  1. I’m a little worried about posting too many extracted files here, especially larger texture atlases.
  2. Going through the files is really fun, and I think you should definitely take a peek yourself if you enjoy the game :3

As the project (hopefully) evolves more, I might post updates on the tooling and also the things I find ^w^ I want to study the Hostess protocol at some point, as well as the map/object data format :3

Thank you all for reading, and goodnight ^w^

tags: projects - reverse-engineering - datamining - triode