that doesnt sound too terrible to be honest. TIL that 8am-2pm is 2x usage.
I don't think I ever made it to the cathedral though.
> I didn’t want to do a function-by-function port. First, APIs may be copyrightable - and copying a binary that closely might implicate copyright more than an approach closer to clean-room design. But it was clear that I needed some level of feedback from the ground-truth binary in order to provide a hill for the LLM to climb on the reimplementation.
Interesting, but isn't this what, say, the Ocarina of Time reverse engineer port does[1]? I imagine the fact that this hasn't been served a takedown notice from Nintendo is a proof that it's defensible? Or at least that there's precedent, ha.
Anyway, this is really cool. I genuinely think the only thing that's missing for me to waste an afternoon here is the sound effects!
There was a little-known sequel to SimTower called Yoot Tower (named after Yoot Saito). It was a commercial flop, but I played it in the 2000s and again in the 2010s and very much enjoyed it! It had a lot of added customizability (more choices of restaurants and shops, for one thing). I would love to see that game recreated.
If the first tile you build is a lobby in the bottom left corner, it is supposed to double your starting money. :)
I'm gonna Google that and see what I got wrong
...however I don't think that the source was ever published anywhere, considering that the repository still doesn't have the source code yet. ("Please check out the YootTower repo, where I'll publish the source code once it's cleaned up, reviewed and approved by Yoot, and relicensed with the MIT licensed.")
I’ll have to check this out!
This perfectly describes what feels off to me about Opus 4.7 (unsure if that’s what you are using). It seems to go down an incorrect path, I correct it, but it still references things from it. Trying to direct it back becomes a mess.
Has anyone experience this as well or am I going crazy? Doesn’t happen with 4.6 for me.
EDIT: Nevermind... [sigh]
Didn't Google v. Oracle disprove this?
I never knew this!!
Man, pre big-internet was so hard to find information on games. I remember for the original tomb raider a friend needed a guide, so I wrote and printed out them a guide for the full game, since I played it pretty obsessively.
I’m probably holding it wrong, but I think a given a sufficiently advanced AI it would essentially be impossible to use it incorrectly. Feels like a step backwards in this regard.
https://www.youtube.com/watch?v=qq8o7gg87k4
Condom Duck:
https://youtu.be/qq8o7gg87k4?t=211
Psycho Party:
https://youtu.be/qq8o7gg87k4?t=381
Cursor Camp (recent hn discussion and neil.fun link):
https://news.ycombinator.com/item?id=47949939
Also, LGR did these great reviews of SimTower and Yoot Tower, which he truly loves, so he disclaims that they are not exactly non-biased:
LGR - SimTower - PC Game Review (15 years ago):
https://www.youtube.com/watch?v=_4ToEDrhxo0
LGR - Yoot Tower: The Sequel to SimTower (5 years ago):
https://www.youtube.com/watch?v=CqNECXCd9iU
Yoot interviewed many interesting people for MACWORLD Japan, like Joanna Hoffman, Bill Atkinson, Steve Wozniak, Douglas Engelbart, and Alan Kay. Here's a transcript of Yoot Saito's interview of Alan Kay that he shared with me and I cleaned up and linked out:
https://github.com/YootTowerManagement/YootTower/blob/main/Y...
A Journey Through Computing History with Yoot Saito and Alan Kay
Yoot towers wisely,
Alan constructs the future --
foundations of change.
IntroductionIn this captivating interview from 1993, recently unearthed and previously published only in Japan, renowned game designer Yutaka "Yoot" Saito of MACWORLD Japan engages with computing pioneer Alan Kay in a deep exploration of technology's past and future. This dialogue, captured on a cassette tape and transcribed, spans the evolution of personal computing, highlighting groundbreaking advancements and visionary ideas that have shaped modern technology. Yoot Saito, celebrated for his innovative approach to game design, and Alan Kay, known for his seminal contributions such as the development of the graphical user interface and the concept of the Dynabook, offer profound insights into both the historical trajectory and the potential futures of the digital world. This interview serves as a treasure trove of historical anecdotes, philosophical reflections, and forward-looking innovations, capturing a moment when two brilliant minds discussed the dynamics of technological progress.
----
I'd love to find all of Yoot's original interviews published in MacWorld Japan. Yoot was very active introducing and working with technology and researchers from the US with Japan in the early days of the Mac, and he pioneered psychological chat based AI games using voice recognition and synthesis, like Seaman.
Seaman - Sega's Strangest Expedition Into Artificial Intelligence:
https://www.youtube.com/watch?v=VV0zpPSXOx4
Yoot Saito on His Classic Sega Game Where You Take Abuse from a Fish:
https://www.vice.com/en/article/yoot-saito-on-his-classic-se...
I found a couple of MacWorld Japan CDROM archives on Internet Archive, but my Mac says it can't mount the iso files. It appears to be an old HFS file system -- does anybody know how to to mount these treasures on a modern mac, with an emulator maybe? Or have the actual magazines lying around?
https://archive.org/details/macworld-japan-vol-1-1995-01
https://archive.org/details/macworld-japan-vol-2-1995-09
MACWORLD-VOL-1-1995-01.iso: Apple Driver Map, blocksize 512, blockcount 460003, devtype 0, devid 0, driver count 0, contains[@0x200]: Apple Partition Map, map block count 2, start block 1, block count 2, name Quick TOPiX by OMI, type Apple_partition_map, valid, allocated, readable, contains[@0x400]: Apple Partition Map, map block count 2, start block 3, block count 460000, name MACWORLD-ROM Vol. 1, type Apple_HFS, valid, allocated, readable
Reading the process in TFA, it's very much dependent on the comprehensiveness of the testing framework. And apparently, the tests never built a lobby in the bottom left corner...
Anything else it didn't try, is probably also not documented and not implemented.
With the growing use of AI in reverse engineering, we might need to shift our goals to more strongly verifiable ones, such as matching decompilation.
I agree that you need to be able to produce source code that matches the original binary before you can start porting things.
Meanwhile I'm working on Micropolis (based on the original SimCity Classic code, cleaned up, and compiled with Emscripten into WASM), and also reimplementing The Sims character animation system and content management and creation system in TypeScript with WebGPU and MOOLLM. ;)
Micropolis WASM + WebGL tile renderer demo:
MicropolisCore repo:
https://github.com/SimHacker/MicropolisCore
Micropolis design docs:
https://github.com/SimHacker/MicropolisCore/tree/main/design...
Sims character animation demo with WebGPU renderer:
Source code:
https://github.com/DnfJeff/SimObliterator_Suite/tree/main/vi...
Design docs:
https://github.com/DnfJeff/SimObliterator_Suite/tree/main/vi...
Designs for creating LLM driven Sims content editing and creation tools, uplifting and simulating The Sims in MOOLLM, and downloading The Sims content back into the original game:
https://github.com/SimHacker/moollm/tree/main/designs/sim-ob...
>"What would your Sims say if they could finally talk to you?"
>Two-way bridge between The Sims 1 save files and MOOLLM. Characters, objects, and pets step between a 26-year-old game VM and an LLM-powered universe, retaining and synchronizing their parallel existences.
>The One-Line Version
>Drag a 25-year-old Sims save file in. Watch the character wake up. Have a conversation with them. Send them home changed.
The Uplift: Sims ↔ MOOLLM Character Bridge
https://github.com/SimHacker/moollm/blob/main/designs/sim-ob...
It's all still a work in progress that I hack on when I have spare time (and spare money for tokens), so no ship date known! ;)
Here is a deep dive "podcast" he generated (presenting Claud's analysis in a conversational format) that describes the work. I listened to it, and it got the important trademark and licensing issues right, was quite comprehensive and technically accurate, up until the end where they said maybe there's something to learn about city planning from SimCity! ;)
https://drive.google.com/file/d/1SGAkLIb4CQMPKU7TJ2sRdEjc0Dh...
It pretty much parallels the analysis docs in his repo, which are also quite accurate:
https://github.com/FabianWesner/micropolis/tree/master/docs
This lightning talk I gave at HAR 2009 goes into what you can actually learn from playing SimCity/Micropolis (and reading and extending the code), thanks to Seymour Papert's and Alan Kay's philosophy of Constructionist Education, and it's much wider and more generally useful than just city planning:
https://donhopkins.medium.com/har-2009-lightning-talk-transc...
To save you the indignity of LinkedIn scraping your browser extensions, here is a copy of Fabian Wesner's post and my response with the link spying urls resolved:
https://www.linkedin.com/posts/fabian-wesner_micropolis-simc...
Fabian Wesner | CTO | Passionate about AI and Entrepreneurship | 1 month ago
Claude Code is extremely good at documenting legacy software. That's a huge blessing, especially when the original developers are no longer around or are finally ready to retire.
If you haven't tried this, you might be missing out. So I did it for you.
#Micropolis is the open-source release of the original #SimCity, published by Electronic Arts in 1989. EA released the source code under GPLv3 in 2008 for the One Laptop Per Child project. The codebase is decades old, and there's likely no one left who knows it inside out.
SimCity was one of the very first games I played, back in 1990 on my father's 286. Just a few months after the Wall fell. So this one is personal.
I let Claude Code read the entire codebase and write a full documentation. As far as I can see, it looks correct and complete. I'm no expert on this particular codebase, but that's exactly the point: there might be no expert left on earth. I have tried this on other software where I am an expert, and the results are surprisingly accurate.
You can find the resulting docs and the prompt here: https://github.com/FabianWesner/micropolis/tree/master/docs
I also converted the docs into a podcast episode for easier consumption:
https://drive.google.com/file/d/1SGAkLIb4CQMPKU7TJ2sRdEjc0Dh...
Enjoy!
I know I’m not the first to use Claude Code on this treasure and - of course - I already rebuilt the game with JavaScript.
More on this tomorrow!
Don Hopkins | Full Stack Generalist AI Engineer
Although I may have two feet firmly planted in mid-air, I am still on Earth and know the code. I reviewed it and am I'm impressed with this documentation, which even caught my experimental Eliza chatbot easter egg in the PyGTK version! Importantly it correctly covered all the licensing and trademark issue, and mentioned that active development has moved on to the cleaned up and renovated MicropolisCore repo.
https://github.com/SimHacker/MicropolisCore
Here are the latest design docs:
https://github.com/SimHacker/MicropolisCore/tree/main/design...
The documentation you generated does a good job at mapping out and comparing the several different versions of the code. Albert Hofkamp and I cleaned up and refactored the code into C++ MicropolisCore (which I integrated with Python with SWIG, and later WebAssembly with emscripten/embind), and we wrote Doxygen comments and documentation in the code.
Chaim Gingold deeply studied multiple versions of the SimCity source code for his PhD thesis in Play Design, and interviewed many people involved, then wrote the definitive magnum opus "Building SimCity". Chaim is the one person on Earth who understands SimCity better than Will Wright!
https://direct.mit.edu/books/monograph/5791/Building-SimCity...
>Building SimCity: How to Put the World in a Machine
>A deep dive into the trailblazing simulation game SimCity, situating it in the history of games, simulation, and computing. Building SimCity explores the ...
Good grief you can't hide easter eggs any more!
"Additionally, the web version includes: PacBot -- an AI robot that follows roads toward heavy traffic and "eats" cars, reducing traffic density. This was an early experiment in programmable game avatars."
PacBot appears one minute into this video:
https://youtu.be/8snnqQSI0GE?t=56
>Micropolis Online (SimCity) Web Demo. A demo of the open source Micropolis Online game (based on the original SimCity Classic source code from Maxis), running on a web...
This is kind of the perfect use case though -- it's a game who cares if it's right or not.
https://drive.google.com/file/d/1SGAkLIb4CQMPKU7TJ2sRdEjc0Dh...
[
](https://phulin.me/blog/simtower)
I woke up the other day and asked: could an LLM reverse engineer a modern clone of my favorite childhood video game? So I did it. towers.world is live today and allows collaborative, coop play on a perfect clone of the original game.


Thanks to this retrospective for the image.
At its core, the game is an elevator simulator. It starts getting hard when your tower grows and your sims contend with each other on getting where they want to go. For example, offices grow your tower the fastest, but they come with 6 sims on a synchronized 9-5 schedule that heavily loads your elevators. As a result, you have to manage very tightly what floors your elevators go to and when.
Unfortunately, the game is now basically impossible to play without an emulator. You could reimplement it if the engine were fully described somewhere—but it isn’t. My original idea was to have the LLMs reverse engineer the binary into a complete spec, and then use that spec to reimplement the game. I was inspired by Simon Willison’s posts on translating programs from one language to another—after all, assembly language is a programming language like any other, with well-defined semantics. Then I could add features like collaboration and better UI (primarily a build-a-grid-of-rooms feature).
So I did it. I started with the general binary reverse-engineering framework I’ve built, reaper. It’s a simple harness around a coding agent for static analysis: what can you learn about the binary from reading its disassembled code?
reaper uses a set of prompt templates and a skill to enable the AI of your choice to connect to Ghidra. Over multiple prompting sessions, the AI builds up understanding of the binary, beginning with low-level, easy-to-identify functions and data structures that compose into the higher-level logic. This process has worked for me on smaller programs, and I was hoping to use the output as the foundation of the clean-room spec.
That was my theory, at least. I had dramatically underestimated the complexity of a full specification. Each room’s sims have 10-15 possible states and a complex transition function requiring precise tracking of information. And due to the optimizations necessary at the time, the game aggressively caches and stores any computation it can, often in packed bitfields or other obscure structures. The results? I’d say they approached a functioning simulation. But the simulation never got to a point that was playable, and certainly never got to behavioral parity.
Static analysis did teach me three specific failures of the current AIs.
First, the AI makes premature conclusions about subsystems, records them, and then struggles to figure out when to abandon its earlier guesses. Worse, it struggles with what level of specificity to use. It would frequently choose bizarre abstract terms like “runtime entity” to describe a sim or “queued-car continuation” to describe a sim getting in line at the elevator. In the first pass, it found the multi-floor lobby code and called it the “lower-atrium band,” a term I haven’t yet been able to fully excise from the Ghidra database and notes (because it’s everywhere).
It also gets lazy about recording its conclusions, often neglecting to name parameters and local variables as instructed. My prompts are very clear that it should analyze function-by-function, and make sure every local variable and every parameter is named, but it just doesn’t do it. The models have been getting better at this every iteration, but they aren’t there yet.
When constructing the spec, it had trouble splitting apart the conceptual design of the simulation from the specific implementation details of the binary. I was looking for a clean-room design spec, not a description of data structure layout—but if I asked it not to include binary details, it would move to a conceptual level that was not detailed enough to reimplement.
Many of these challenges are driven by a lack of tools to manage the context window. Disassembly and decompiler output are just too verbose for an LLM starting from scratch. While I do think there are ways to handle this by making the exploration more LLM-native, using a single Ghidra database is a difficult environment for the LLM to work in. Over and over, I watched the LLM compact and compact, forgetting the details of what it just explored. Unlike text-processing tasks, to reverse engineer you need to have all the precise details in working memory. Compacted summaries don’t cut it.
Still, I persevered. I spent about a week guiding the LLM to refine the spec, discard its incorrect guesses and build tests for the rewritten simulation. I repeatedly asked it to review and improve the spec, pointed to specific deficiencies that needed to be filled in. But I never got there.
So what next? A friend pointed me to this February post about SimCity, which described engineer Christopher Ehrlich’s efforts to compare a function-for-function SimCity port to the original via input/output comparisons. Ehrlich’s original tweets in turn cited a user named banteg’s post on the game Crimsonland.
I didn’t want to do a function-by-function port. First, APIs may be copyrightable - and copying a binary that closely might implicate copyright more than an approach closer to clean-room design. But it was clear that I needed some level of feedback from the ground-truth binary in order to provide a hill for the LLM to climb on the reimplementation.
An immediate problem: the whole justification for this project is that we can’t run SimTower on modern hardware. Unlike banteg’s project, which used WinDbg, we need some kind of emulator. Off-the-shelf whole-system emulators are not the best option, as you often end up sifting for the program behavior you’re interested in through millions of instructions of operating system cruft. A quick search reminded me of the existence of unicorn, an emulation framework that uses the JIT code-generation logic from QEMU to allow arbitrary emulation pipelines.
I had Claude Code build a Unicorn emulator with a custom mock for each of the 195 Windows 3.1 API functions called by the game. My prompt to Claude was barely more detailed than this sentence. The work took all of about a half an hour and was 99% correct, except for one nasty bug in the loader Claude built that did cause some downstream issues (of course, Claude found the bug later and fixed it). I did almost no work to make this happen. Honestly, I found the resulting success (which took basically zero guidance) to be yet another shocking LLM progress moment.
I then had Claude specify a bunch of small tower configurations, call functions inside the emulated binary to build the rooms, and record snapshots of tower state every few game ticks to enable comparison with the reimplementation. Once I had the state traces, I could direct the AI to autonomously fix any issues that were causing divergence from the emulated binary behavior.
Of course, this meant I needed to make sure every detail matched precisely: most irritatingly, the RNG and the ordering of processing sims each step had to match. RNG parity means that every function that uses the RNG needs to run in the same sequence, or e.g. the wrong sim will be dispatched and lead to a cascading chain of mismatched state. The original binary allocates sims using something like a slab allocator, and some rooms “claim” space in then table and then release it. To get RNG parity, you need to replicate this pattern somewhere so that RNG calls triggered by sim iteration happen in the same order.
From there, it was just repeated improvements to the trace test coverage and letting Claude Code run for hours and hours (my longest run without any prompting was about 8 hours, and it autonomously fixed 5 parity bugs and committed its changes during that time).
As I worked further the game converged on a closer and closer reproduction of the original binary’s structure, violating my original not-function-by-function constraint. But I think that’s OK. Once we have a perfect reproduction, with comments and named functions and variables in a high-level language, we can use the AI to translate again if we need to.
The cool thing is that emulation and state-matching provide an excellent verification target. The LLM can hill-climb piece by piece as more of the trace matches, and it knows enough about code to autonomously debug and solve issues. The big lesson—one I keep relearning—is that the LLMs need to be in a closed loop when doing complex tasks. They are just not capable (yet) of executing an abstract task like clean-room design from static analysis reliably. Repeating “make it better” does not solve the problem: you need the dynamic-analysis verification on the backend.
There are also a number of specific harness patterns I found helpful. The best way I’ve found to get current LLMs to operate autonomously is to have a high-level coordination thread that runs for a long time and low-level subagents for specific tasks.
This project used an absolutely ridiculous number of tokens. I had to upgrade to the Claude Code $200/month plan and carefully avoid usage in the 8 AM-2 PM 2x peak window. While autonomous hill-climbing is a great pattern for LLMs, it is not something you can do cheaply. They want to experiment and fill up their context window with information they might need to know from your project. You can very carefully engineer your way around some of this, but lots of unavoidable. There are some interesting approaches for disassembly in the academic literature, e.g. custom formats to reduce the verbosity, but none address the fundamental problem.
In conclusion: I did this, and you can do it too! You can translate code from machine code to a modern language. There are terabytes of abandoned machine code out there. For the first time, we have a tool that lets us economically modify and reuse that software in a sustainable way. That’s an incredible advance.
towers.world is available now. Play it!
I did all this work while a participant at the Recurse Center, a retreat for programmers in NYC and one of my favorite places in the world. If you’re wondering whether to apply, you should!