GFXtract Refactor

Nov 3, 2017

So I’ve recently been working on my project GFXtract, which I haven’t touched in over a year. For those who aren’t familiar with it, GFXtract is a script-based image conversion and/or extraction tool. While in theory it should be usable for a range of things, the focus is on reading weird image formats from games, and saving them as easy-to-use PNGs. The instructions for how these images are to be read are in scripts, essentially in a simple kind of programming language, GSL (GFXtract Scripting Language). If you’ve ever used QuickBMS, the concept is more or less the same (GSL is also heavily based on BMS).
The reason I’m making this is because I have to make an entire program every time I want to convert or extract image formats from a game. This often involves a lot of boilerplate crap and is just overall a clunky way of going about it. While QuickBMS solves this problem for archive formats, I wanted a solution for image formats too. So I figured I’d make it myself, maybe helping other people in the process.

So yeah, I’ve been working on this recently. As you can imagine the majority of the code and the main challenge has been parsing and interpreting the scripts, since it’s essentially writing an interpreter for a programming language. Previously my way of doing so had been fairly unsatisfactory; basically everything was in one big file, I was running the script during interpretation, and if statements and loops were just kinda hacked in.

After having done a bit of language interpretation at university in Haskell, I got a better idea of how to go about it. The concept is that it first reads in the whole script and stores it as a list of steps, using a hierarchical set of objects. This catches any syntax errors before trying to run the script. It might also allow for static checking to some extent, although that’s something I don’t think matters right now.
What I really like about this is that after this step, I don’t have to worry about how the script is written. It completely separates parsing from computation, and I end up with a bunch of objects that are well-defined in my system.

The details are still being ironed out; at the moment I’m trying to implement some basic commands and fleshing out the rest of the system from there. My main issues seems to be designing the type system. I have values, but do variables count as values? What about the types I’m reading in (byte, short, long, etc)? I’m trying things and seeing what both works and “feels” best.
Once I’ve got this stuff nailed down I should be able to implement the rest of the commands I had before and release a usable version (most likely version 1.0). Then I can go ahead and add a bunch of extra things I wanted to for a while, which I’m hoping should be easier with this new system.

I do expect v1.0 to have some breaking changes, but luckily I seem to be the only one who’s made any scripts for GFXtract so far, haha :P