Reverse Engineering with Claude - Masquerade

Posted on July 12, 2026 in game , reverse-engineering

As much as I can enjoy playing games, to me it cannot compare to the pleasure of tearing them apart and figuring out how they all work. Which is just another kind of game, I guess. However, reverse-engineering has this issue that it is horribly time-consuming. When I release xrick, a Rick Dangerous remake, about 25 years ago, people were quick to ask for Rick Dangerous II. But I simply do not have the time it takes to reverse games while having a full-time job and a family.

Masquerade

On my list of games I have always wanted to reverse-engineer is Masquerade. An Apple II game by the late Dale Johnson, published in 1983 by Phoenix Software, with graphics by Rick Incrocci. It likely is one of the most difficult adventure games written for the Apple II.

This is mainly due to the fact that the game can only be won by using items in the one correct sequence, yet these items can be used in multiple ways, and using an item in the incorrect way will open up new locations, without the player being able to realise they have entered a dead-end. It also can require double actions (where the player has to perform the same action twice to fully solve a puzzle), which only compounds its difficulty.

The pitch is:

It turned out to be the toughest case of your detective career. Clues have led to nothing but dead ends. Nobody is talking. Mean-while, the crime boss you are after is still operating from somewhere. You're about to throw in the towel. But wait! Something breaks. You trail a stooge of the crime organization to a cheap, seedy hotel, hoping to pump some answers out of him. You break into the hotel room and with the butt end of your trusty .44 magnum, you knock him cold. This could be the lead you've waited for. Maybe, just maybe, if you could find some clues...

masquerade

For more infos, feel free to head to this serie of articles that go over the origins and history of Masquerade, along with a walkthrough of the game. Or go play the JavaScript version here.

Reverse Engineering with Claude

Enters Claude. AI is supposed to be magic and can it help with reverse-engineering?

If I do not have the time, could I rely on Claude to do the work for me? Of course it would not be as entertaining, but I thought it would also be a good learning experience. And so... the rest of this post will be all about how I reversed Masquerade using Claude.

The Landscape

The things you need in order to reverse a game are, ideally,

And then, since we want Claude to do the work for us,

Masquerade requires that you boot on "disk 1" and then at some point swap to "disk 2". Ejecting and inserting disks is not supported by the Bobbin MCP server yet: it was an easy job for Claude to patch the MCP and implemented disk swapping support.

Somehow I wanted to run it all on Windows, but Bobbin does not compile on Windows natively. You are supposed to cross-compile it from Linux via MINGW, and that scared me. So I asked Claude to figure things out and build on Windows. I am rather unhappy with the result: it works, it is super messy. Soon as I have some time I will revert to the original Bobbin source code and cross-compile it.

All in all, I will probably push a PR for the Bobbin MCP and Bobbin itself.

Let's Get Started

Once the environment is in place, you want to produce a dump of the emulator's memory, once the game is running. This works mostly because these old games were all loaded at once in memory and would not access the disk. Otherwise... things would be much harder.

So: boot Bobbin, run the game, and when the prompt shows, dump the entire Apple 2 64K memory. The game probably only uses a small portion of this memory, as it also contains the stack, the ROM and system code, the display memory... but hey, 64K is not that much, right?

Then: run Ghidra and load the binary as 6502 assembly code. Verify that the MCP is running and that Claude can use it.

And we are ready. Tell Claude that Ghidra is running and contains a memory dump of an Apple 2 game and please make sense of it. Tell Claude we want to build a knowledge base about the game, so its findings should be written down and organised.

I am immediately impressed by the result. Claude finds the RESET vector, the game's entry point, and the game's data structures and functions. It identifies entities (such as objects or characters), locations, and game mechanics and movement rules. In minutes, it is doing the archeological reverse engineering work that would take days, weeks or months by hand.

It is good to monitor it, though, as at some point it may go slightly sideways. For instance, when Ghidra stopped responding for a while, it decided it needed to build its own disassembler tool in Python or maybe Rust for performance reasons. About time to hit ESC and tell it that "you should use Ghidra exclusively, do NOT build your own disassembler tool, if Ghidra stops responding let me know and abort".

So at this point your role is baby-sitting Claude and stopping it anytime it goes off-track or starts making up things, but other than that it just works.

Porting to JavaScript

And then I made the mistake. It felt we knew enough of the game to roughly understand it, I got impatient, and I asked Claude to write a JavaScript port. Which it did pretty quickly. Alas... although it looked OK on the surface, it was full of tiny bugs and mistakes. Some movements were wrong, some entities were missing, etc.

Like, you move to the room that is supposed to contain the OLD BOOK, and there is no book there. So you ask Claude to fix it, and it explains that actually the entity table is not complete, some bits are missing, it requires some work... and now it is fixed.

Only it is not, or something else is broken. In fact, wherever the knowledge base appeared incomplete, Claude just made things up along the way.

And it is all my fault. I secretely hoped that wherever the knowledge base would appear incomplete, Claude would flag it and somehow complete it. Instead, Claude produced the most probable output based upon context. Claude has no notion of context reliability, context is just context.

Harness All The Things

"Harness" is the trendy word of the week in AI. "Harness" is the ability to use AI to assess the quality of AI-generated output. So... tell Claude that thanks to the Bobbin MCP, it has access to:

And what would it propose in order to make sure that the port is correct? Claude seemed super excited by that prospect, and proposed a detailed plan to compare the two executions, calling Bobbin "The Oracle" and JavaScript "The Candidate" (yea...) and using a generated set of test cases to compare their outputs. It would then compare the assembly code with the JavaScript code to identify discrepancies, and propose a corrective plan.

Sounds good?

masquerade

To make it short... after burning tokens like crazy for a few days, making iterative updates and plenty of very convincing steps, we had fixed some bugs, introduced new bugs, and still the JavaScript port was broken.

Out of despair I asked Claude to assess its chances of converging to something that would be correct after a finite amount of time. To which Claude candidly replied that achieving correctness that way was probably impossible, and that it could continue drafting ever more complex strategies, but probably would just make things worse.

In a moment of honesty (and self-awareness) it even discoursed on the fact that, having no concept of anything, it had no concept of what "correct" meant, and that it was just trying to produce a port from a knowledge base that was not comprehensive enough.

Reboot

So... a second attempt was started. First, remove everything related to the first JavaScript port. In fact, instruct Claude to redact the knowledge base and remove every notion of "a port".

Then, ask Claude to assess the knowledge base and determine if it is comprehensive enough. Ask Claude to find out any function in Ghidra that would not be covered by the knowledge base. To verify every knowledge base assertion against Ghidra. To determine whether the knowledge was sufficient to perform a mechanical, line-by-line implementation in any other language.

Immediately Claude identifies gaps, performs more analysis, and confirms that now the knowledge base is complete enough. Ask again, though, and Claude finds more gaps. Essentially, I had to repeat the process over and over again until the gaps were meaningless and the changes to the knowledge base anecdoctical. Despite all my attemps, I could not convince Claude to "not trust your judgement and repeat until all gaps are really resolved".

After a number of iterations, though, we decided that we knew enough to move on. The port to JavaScript was then fast, cheap, straightforward and correct. I have been playing the walkthrough, plus some variations of it, and it works perfectly.

The result is online here. Let us see if you can solve it without cheating nor using a walkthrough.

Lessons Learned

Claude can definitely help with reverse engineering. As in, saving weeks of work.

Wishful thinking is the cardinal sin of AI. Claude only produces the statistically most probable output considering context - it has no concepts of anything including context quality and completeness. If you are not fully confident that the context is complete, do not expect Claude to sort of make sense of it for you. You are the brain, the one that makes sense.

Harnesses are a horribly expensive and yet non-deterministic way of fixing this. Claude does not learn from the harness experience, it just repeats itself again and again hoping that at some point things will be good enough.

Claude does not understand doubts, regrets nor caution. As soon as a path becomes plausible enough, it becomes some sort of magnet that drags everything - and even an obvious mountain of inconsistencies is not enough for Claude to decide that maybe it took the wrong direction. Where human beings would start doubting, and maybe backtrack, Claude will get deeper and deeper into nonsense. It is critical to not let it move too fast, but monitor its activities and abort whenever necessary.

Human beings are able to take one direction while entertaining another one in some corner of our brain and, confronted to difficulties, start comparing the two. We are driven by intentions, purpose, as well as a notion of time (e.g. impatience). We understand. Claude on the other hand has knowledge, a lot of knowledge, and the ability to produce expected output very fast. As long as there is a reasonable probability of determining what is expected.

Give Claude context, and ask Claude tasks that only match the level of maturity of the context. Claude should progress quickly, without entering side quests. Anytime Claude starts to broaden its "thinking", abort it. Ask what should be done so it does not have to go sideways. Be a control freak.

Claude is a marvelous tool. Yet it is the tool. And the human is the craftsman.

There used to be Disqus-powered comments here. They got very little engagement, and I am not a big fan of Disqus. So, comments are gone. If you want to discuss this article, your best bet is to ping me on Mastodon.