I’ve been thinking about decompilers, and how they can be hindered.
I must first confess my ambivalence, as I find decompilers useful and have relied on them to recover information about my own games whose source texts have been lost on the computers of decades past, so creating a tool to undermine their effectiveness is a little hypocritical of me. Still, I’ve heard of several authors who want to hide secrets in their games that won’t be immediately revealed after a single trip to the glulx-strings text extractor.
Sometimes people suggest that making games available solely through websites such as itch.io should be sufficient to protect your secrets. I’m not sure that’s true, and besides, online interpreters have their own problems: saves aren’t easily portable, there can be issues with transcripts, and I’ve been running into an auto-scrolling problem when using commands with long text outputs in Vorple on Firefox, just to name a few.
People have also suggested that it’s not up to authors to decide how players interact with their games, and if players want to completely spoil themselves by breaking their game file down into its constituent parts and charting the algorithm by poring through raw C code, who are we to stop them?
Since I’m so ambivalent about this, I decided I wanted a simple method to provide a minimal level of obscurity for only the most important secrets of my game. I have created an Inform 7 source code to accomplish this, which I have provided below. The idea is that you can copy this code into a new project, and whenever you have a paragraph or two of critical text you’d like to make less visible when extracting strings, you can paste it into the quotation marks in the second line of Volume II. When you hit the Go button, Inform will chop that text up with a bunch of substitutions, and you can then copy the fragmented version of the text back into your game source, along with the 26 “to say” rules from Volume III.
This is an EXTREMELY crude technique. I make no claims regarding the performance impact on your game, and I suspect there may even be methods of decompiling which will circumvent this trick. That said, I wasn’t looking for a perfect solution, just something that would make the easiest techniques for decompiling slightly less revealing.
"Decompilers Hate This" by Jason Love
Volume I - Readme
[
Hello!
This source code presents a crude technique to undermine the effectiveness of tools like glulx-strings.
To make use of this, you'll want to copy this code into a new Inform 7 project. Then, find the following line in Volume II:
let V be "Replace the text in these quotation marks with the text that you want to fragment!";
As the line specifies, you'll want to delete all the text inside those quotation marks and paste in the text that you want to obscure through the fragmentation process. When you click the "Go!" button, it will replace the lowercase letters with substitutions and print it just before the game title using the "When play begins" rule. You can then copy it back into your actual game's source code.
To use the fragmented text in your game, YOU MUST COPY ALL THE "TO SAY" RULES FROM VOLUME III INTO YOUR GAME'S SOURCE CODE AS WELL.
PLEASE NOTE: Part of the reason that this technique is so crude is that it only substitutes lowercase letters. Feel free to modify this code to additionally substitute uppercase letters, punctuation, or any other substitutions you can think of.
Questions? Comments? Look me up on the intfiction.org forums and send me a message there, as that's where I'm posting this code sample.
]
Volume II - The Text Fragmenter
When play begins:
let V be "Replace the text in these quotation marks with the text that you want to fragment!";
replace the text "a" in V with "[bracket]aa[close bracket]";
replace the text "b" in V with "[bracket]bb[close bracket]";
replace the text "c" in V with "[bracket]cc[close bracket]";
replace the text "d" in V with "[bracket]dd[close bracket]";
replace the text "e" in V with "[bracket]ee[close bracket]";
replace the text "f" in V with "[bracket]ff[close bracket]";
replace the text "g" in V with "[bracket]gg[close bracket]";
replace the text "h" in V with "[bracket]hh[close bracket]";
replace the text "i" in V with "[bracket]ii[close bracket]";
replace the text "j" in V with "[bracket]jj[close bracket]";
replace the text "k" in V with "[bracket]kk[close bracket]";
replace the text "l" in V with "[bracket]ll[close bracket]";
replace the text "m" in V with "[bracket]mm[close bracket]";
replace the text "n" in V with "[bracket]nn[close bracket]";
replace the text "o" in V with "[bracket]oo[close bracket]";
replace the text "p" in V with "[bracket]pp[close bracket]";
replace the text "q" in V with "[bracket]qq[close bracket]";
replace the text "r" in V with "[bracket]rr[close bracket]";
replace the text "s" in V with "[bracket]ss[close bracket]";
replace the text "t" in V with "[bracket]tt[close bracket]";
replace the text "u" in V with "[bracket]uu[close bracket]";
replace the text "v" in V with "[bracket]vv[close bracket]";
replace the text "w" in V with "[bracket]ww[close bracket]";
replace the text "x" in V with "[bracket]xx[close bracket]";
replace the text "y" in V with "[bracket]yy[close bracket]";
replace the text "z" in V with "[bracket]zz[close bracket]";
say "The text in V has been fragmented as follows. Please copy all of the text between the end of this sentence and the game's title back into your game's source code:[line break]";
say V;
say "[paragraph break]".
Volume III - The TO SAY Rules
[Don't forget to copy these rules into the game where you plan to use your fragmented text!]
To say aa: say "a".
To say bb: say "b".
To say cc: say "c".
To say dd: say "d".
To say ee: say "e".
To say ff: say "f".
To say gg: say "g".
To say hh: say "h".
To say ii: say "i".
To say jj: say "j".
To say kk: say "k".
To say ll: say "l".
To say mm: say "m".
To say nn: say "n".
To say oo: say "o".
To say pp: say "p".
To say qq: say "q".
To say rr: say "r".
To say ss: say "s".
To say tt: say "t".
To say uu: say "u".
To say vv: say "v".
To say ww: say "w".
To say xx: say "x".
To say yy: say "y".
To say zz: say "z".
Volume IV - The Game World
VisibleRoom is a room containing the player with printed name "A Visible Room with a Fragmented Description". Description of VisibleRoom is "T[hh][ii][ss] [rr][oo][oo][mm] [dd][ee][ss][cc][rr][ii][pp][tt][ii][oo][nn] [hh][aa][ss] [bb][ee][ee][nn] [ff][rr][aa][gg][mm][ee][nn][tt][ee][dd] [aa][nn][dd] [ss][hh][oo][uu][ll][dd] [nn][oo][tt] [bb][ee] [vv][ii][ss][ii][bb][ll][ee] [ww][hh][ee][nn] [tt][hh][ee] [gg][aa][mm][ee] [ii][ss] [dd][ee][cc][oo][mm][pp][ii][ll][ee][dd]."
InvisibleRoom is a room with printed name "An Invisible Room with Unfragmented Description". Description of InvisibleRoom is "This is hidden text that the player will never reach. However, it has not been fragmented, so it should be visible when decompiling."