Melee GCI Compiler is an application and scripting language that makes it easy for Super Smash Bros. Melee mod developers to inject custom code and data into Melee save files.
compiler.py should be refactored so that functions don't modify the state of non-local variables unless they are part of a class.
Possible solutions:
Put most of compiler.py in an encapsulating class so that the functions are modifying its own members, rather than something out of scope
Use a functional approach so that any mutable data belongs to the top-level function, and other functions return a "write table" instead of directly writing to the mutable data
This might read a bit weird, but I'm in the habit of offering random refactorings to people so that I don't get too rusty with my Python.
I wanted to check if there's interest in PRs before going ahead, though. Still, one of the parts I thought about touching up is command-line args processing, e.g. by switching to argparse, which should improve that section's readability compared to the additional logic you have to use for getopt to give equivalent results.
In the provided example !string "UCF Datafile" is placed in a 12-byte region of memory. This does not leave room for the null terminator, and the filename ends up overflowing. As a result, if you try to create a savefile after executing the payload, it crashes on console. In emulator, it throws a warning which can be ignored... but console behavior is a crash.
One possible fix to this would be to just choose a string which is 11 characters or less, leaving room for the null terminator. "UCF Datafi" was tested and works flawlessly on console. Other fixes are of course possible, but that would be the quickest and easiest in the provided example.
Thanks to @UnclePunch for figuring debugging the underlying reason for this.