Community material · Claude Code × Godot

Tekken 3 from scratch in less than a week: vibe reversing a PlayStation game and a remake in Godot

Author: n0madic · October 1, 2026

Author's illustration for the topic: Tekken 3 from scratch in less than a week: vibe-reversing a PlayStation game and a remake on Godot
Illustration created with AI · Vibe Coding
Published with permission from the author. The original text and section order are preserved; only the web formatting has been changed. Original source on Telegraph.

How Claude Code and I deconstructed a 1998 disc, found over 60 bugs in the original, and built a full remake that matches the original frame by frame.

How it all began

On September 26, I gave Claude Code one big task. It sounded something like this: "Create a remake of Tekken 3 for PSX from scratch on a modern engine. To start, deconstruct the original discs, document all data formats, 3D models, animation, sounds, effects, and all game logic."

I wrote almost no code. My role was reduced to three things: setting goals, making decisions at crossroads, and watching the result through the eyes of a player. The agent did everything else. Below, I describe how it looked from the inside, where the AI excelled and where it failed.

For scale. The repository currently contains approximately 45,000 lines of GDScript in 215 files, 35,000 lines of Python reversing tools, another 5,000 in the disc converter, 35 Markdown documents on game formats and logic, and over 170 tests. The main Claude Code session, which covered the research and the first five milestones, accounts for over 46,000 agent messages and about 23,000 tool calls.

Step 1. Vibe-reversing: how to deconstruct a game without source code

Reversing a PlayStation game consists of two tasks. First: understanding file formats (models, animations, textures, sound, video). Second, much harder: understanding the logic, i.e., exactly what happens during a single combat frame, how a hit is calculated, and how the CPU opponent "thinks."

Tools. The agent deployed the pipeline itself:

  • Ghidra in headless mode with PsyQ library signatures (it recognized 929 library functions) and scripts that import the binary file and all ten game overlays;
  • Unicorn (MIPS processor emulator) plus a custom software model for the GTE coprocessor, which handles 3D geometry on the PlayStation;
  • Python scripts that unpack discs into a working tree, and decompiled C.

The core idea of the method. We don't need a full PlayStation emulator. We need the ability to run individual functions of the original machine code and compare their results with our implementation. Therefore, for each subsystem, the agent followed a single cycle: read the decompilation, write a Python port, run the original function in Unicorn on thousands of random inputs, and compare memory byte by byte. As long as there is even one divergent byte, the format or rule in the documentation is marked as inferred, not confirmed.

Yes, for example, the animation pipeline (49 channels, splines) matches the game bit-for-bit across 314,290 frames of all 22 move banks. The camera is verified across 86,058 frames. The entire AI opponent is ported and verified in 19 scenarios without a single discrepancy.

Reversing challenges

  • The decompiler often lies. Game overlays (mode and screen code load into the same addresses) Ghidra deconstructs poorly: it merges adjacent functions and "collapses" constant tables. Solution: for complex areas, the agent switched to the Capstone disassembler and ported from assembly rather than decompilation.
  • The agent had its own memory. The context window ended in the main session about 67 times. Everything that would be lost, the agent wrote to memory files and into CLAUDE.md: the pipeline, known traps, and decisions made. Without this, the work would fall apart after the very first "forgetting."
  • The emulator also has its own "quirks." When dividing by zero, Unicorn does not return what a real R3000 does (there it is -1 or +1). I had to train the verifiers for this. And attempting to rewrite the original code "on the fly" via hooks simply crashed the emulator with a segfault, leading to a rule: never touch the code via hooks.
  • Original traps. In some places, the game reads from address 0 (the console's RAM mirror) or uses a register value left over "from the BIOS." This cannot be reproduced without a real console, so such places are separately marked and described.

Byproduct: the original's bug registry

I asked to record every found defect in game-bugs.md: where, what the original does, what effect, and how to fix it. There are 61 entries to date. A few of them:

  • The AI opponent "remembers" hits, but only compares them to the zero slot of an eight-slot history, so the "learning" doesn't work as intended;
  • character unlocking in the arcade is calculated by a loop through bit positions instead of a mask: after the 11th character passed, progress simply "stops moving";
  • in Tekken Ball, the opponent should prefer the least encountered characters, but due to a sorting error, the selection is uniform;
  • in Tekken Force, enemy timers are 16-bit: after ~9 minutes on one level, they are all considered "expired";
  • the result clearing loop clears the same entry ten times because the pointer does not advance (fortunately, without consequences).

The policy is simple: we do not reproduce bugs that have no impact on the game; bugs that affect gameplay are left as default and fixed with a single option Gameplay fixes. Thus, the "authentic" mode remains authentic.

Step 2. Engine choice and plan

When the documentation matured, I asked: which modern engine would be best for a fighting game so that it is open, lightweight, and runs on desktop, mobile, and web. The agent suggested options, we discussed them, and I chose Godot 4 of GDScript. The main argument: Godot 4 C# projects do not export to web, and web was a goal.

Before any code, we wrote a large implementation plan: architecture, layers, graphics decisions, and milestones M0–M5. Two key ideas:

  1. A simulation core without Nodes. A deterministic game at 60 Hz, using integers and fixed-point (4096 units per rotation, 4.12), no floats or engine physics. Everything that goes outward (sounds, effects, vibration) is output as frame events. The presentation only reads the state.
  2. The code is not literal, but idiomatic, yet verified by "golden traces." Python ports, verified against the original, generate reference frame recordings. Godot tests play the same inputs through the core and compare state field by field every frame. One of the results: 32 full matches match the original in every field of fighters, camera, timer, random number generators, and sound and vibration calls.

Step 3. Godot port: milestones

  • M0, the foundation. Python disk-to-Godot format converter, a test scene with one fighter.
  • M1, intro. NAMCO PRESENTS, video, title screen, demonstration fight on stage. Matches the original code run in the emulator, frame for frame: 3549 frames for each of the three scenarios.
  • M2, fight. Two players, all characters, all arenas.
  • M3, CPU, and the game. Menu, Ogre arcade, results, ranking, Theater, saves.
  • M4, Tekken Force, and Tekken Ball.
  • M5, platforms. Android, iOS, web, Windows, Linux, macOS, touch controls, DualShock/DualSense, texture packs.

Working with the agent was convenient: I would write "fully implement M3 from the plan," then review the result, play, and report flaws: "fighter doesn't fall out of the ring," "Esc doesn't work in Command List," "medkit isn't picked up."

Interesting porting issues

  • Models could not be put into glTF. In the game models, the seam angles are a 50/50 mix of two body parts that never align in a single pose. Therefore, each corner stores two local positions, and the shader blends them itself. Animations are baked frame-by-frame; Godot does not calculate splines.
  • "Plastic" hair on Law and Lei. The reason turned out to be in Godot: even weak specular on black polygons is amplified by the Fresnel term to ~70%. In the original, the lighting is purely diffuse (Gouraud via GTE), so the specular was removed.
  • Music started twice, the HUD appeared over the Ogre scene. The agent also caught these small details by comparing them with the behavior of the original code.
  • One disc instead of two. The agent built an "address mapping" system (layouts/<реліз>.json): any of the three releases (Japan Rev.1, original Japan, USA) is translated into the Rev.1 address space, and the game is built from any one of them. The repository contains only numbers and hashes, no Namco data.

Refactoring: "is this a literal translation?"

For a long time, I worked with the code without looking inside. Then I took a look and saw that a large part of the remake looks like a literal translation of decompiled code: constants like 0x800B9554, conditions like slot == 0xD41. I asked if it made sense to rewrite it idiomatically.

The agent answered unexpectedly honestly: the core should not be rewritten "the Godot way" (Node, signals, Tween, float) because it would break determinism. Instead, it is worth replacing magic numbers with enum-s and names, and breaking up monolithic functions. Trace tests protect here: after every step, a full set is run, and all fields must match the original on every frame. That's what we did: over two dozen "refactor: ..." commits introduced Character, GameMode, RoundState, BankType, names of state bits, buttons, and branch conditions for moves. The behavior didn't change, but the code became much easier to read.

The role of AI and where the vibe ends

What worked well:

  • Iterations with verification. Every hard fact was confirmed by running the original code. This is the best "anti-hallucination fuse": if the agent invents a rule, memory comparison will show it.
  • Memory and documentation as an extension of thought. CLAUDE.md, memory files and Markdown documents allowed surviving dozens of context resets.
  • Breaking into milestones and "fix all remarks." Short commands like "implement M4," "fix everything," /code-review gave surprisingly much.

Where a human is needed:

  • Decisions. Engine, bug policy, "one interface instead of two," prohibition of resource duplication, etc. The AI advises, but the author decides "where."
  • Player expectations. The agent reliably compares numbers but doesn't see that a fight "doesn't feel right." All complaints like "mountains like wallpaper," "jittering in the video," and "I see plastic" came from me.
  • Quality control of the work. The agent made mistakes itself: the first plan of fixes included complex emulation of load caches just to stop the music, and I rejected it; the code review found screen crashes that the tests "didn't notice." After this, a rule appeared in my memory: "never restore a copy over changes made by someone else."

Conclusions

  1. Vibe-reversing works if there is an "oracle." Original machine code that can be run and compared turns hallucinations into test errors. Without such an oracle, we would have beautiful but unverified documents.
  2. Strong boundaries and tests are more important than beautiful prompts. The "core / presentation" layers, determinism, and golden traces made both refactoring and mass fixes possible.
  3. Write context into files. For an agent, a long project is a series of introductions from scratch. CLAUDE.md and memory make it a colleague.
  4. The author remains the director. AI wrote almost everything, but the human defined the project's meaning (precise, not just "similar").

The project does not contain or distribute game data: a custom disk image is required, and the converter transforms it into remake resources itself. All Namco data remains with you.

Other community materials · Discuss in Telegram

Was this helpful? Pass it on

Send it to someone with a similar task.

Share in Telegram ↗

Read via RSS · Weekly newsletter in Ukrainian

Discussion

Share your opinion or ask about the material. Your nickname and comment text will be visible to everyone.

Loading comments...

Telegram chat ↗