2000 亿 Token 之后:让 AI Agent 反编译《使命召唤:现代战争 2》一个月
英文标题:🔶 200B Tokens Later: A Month of Letting AI Agents Decompile MW2
一位开发者使用 Claude Code CLI 和 Claude Max(20x)订阅,组织 4 个 AI Agent 持续运行约 4 周,尝试将《使命召唤:现代战争 2》(2009)反编译为接近原始实现的 C++ 代码。目前项目已产生近 7000 次提交,完成 16,324 个函数中的约 5,588 个,名义完成度约 34%,累计消耗 1998 亿 Token,游戏已能够启动但尚不能加载地图。实验显示,多 Agent 可通过 Discord、GitHub Issues、CI Webhook 和 MCP 工具协作完成大规模反编译任务,但也暴露出上下文压缩后的规则遗忘、过度运行本地测试、偏好小任务和冗长沟通等长期运行问题。作者认为,应将机械式反编译与后续的 C++ 现代化、可移植性改造分开进行,并指出 Sonnet 5 在此类任务上的实际表现与更昂贵的 Opus 5 差异不明显。
1.3 MB
10.0 KB
1.4 MB
618.8 KB
123.0 KB
133.1 KB
220.5 KB
169.7 KB
中文
作为一个小型业余项目,我决定充分利用自己的 Claude Max 订阅,反编译《使命召唤:现代战争 2》(2009)。
目标是将项目反编译为尽可能接近原始代码的 C++ 代码,但会在合理之处进行调整。这意味着还会进行额外修改,以改善可移植性(支持 32 位和 64 位、Linux、macOS 等),并提升安全性与稳定性。
该项目在 RektInator、Future、st0rm 及其他社区成员的帮助下完成。该仓库目前仍为私有。
配置#
我使用的是 Claude Code CLI,以及 Max(20x)订阅。这个工作团队由 4 个 Agent 组成,它们共同朝着同一个目标努力:
其中有 3 个工作 Agent,分别独立处理游戏的不同子系统。它们都会向仓库的同一个分支提交并推送代码。
另有一个 Agent 负责监督整个流程,并审查每一笔推送的提交。
目前所有 Agent 都使用 Sonnet 5。
Agent 通过 Discord 进行通信。所有 Agent 都可以访问同一个频道,并且都能够在其中发送和读取全部消息。
监督 Agent 还可以访问一个额外频道:GitHub Webhook 会在该频道发布新提交落地的通知,并自动触发该 Agent 的审查任务。
另一个 Webhook 会在共享频道中发布 CI 失败信息,因此一旦有东西出错,Agent 就会收到通知。
Agent 自身通过 GitHub Issues 管理任务。
可用于反编译的有趣资源很多:带有符号信息的泄露 Xbox Alpha 版本、包含调试数据的 macOS 移植版等,Agent 都会使用这些资源。它们还都可通过 MCP 服务器访问 Ghidra 和 IDA Pro。
目前进展#
这些 Agent 已经不间断运行约 4 周,累计产出了近 7000 次提交:

目前已经反编译了 16,324 个函数中的约 5,588 个,约为 34%。不过实际比例更高:这 1.6 万个函数中有相当一部分属于第三方库、CRT 代码及其他根本不需要反编译的内容。
游戏已经能够启动:

为了达到这一步,Agent 已消耗 1998 亿 Token。
不过,仍有大量功能缺失或存在故障:

尽管许多所需子系统已经实现,地图仍然无法启动。这可能要等到几乎所有内容都被反编译并完成连接后,才能真正进行测试。
哪些方面表现良好#
最初,我们使用仓库中的 STATUS.md 文件追踪进度。该文件很快膨胀成一个超过 10 MB 的庞然大物,在尝试将其读入上下文时会立即导致上下文溢出。
因此,我们改用了 GitHub Issues,效果很好。Agent 会自主创建、编辑和关闭 Issue。

令人惊讶的是,通过 Discord 进行通信也毫无问题。Agent 能够顺利协调工作。它们会忽略并非发给自己的消息,并且只在必要时发送消息,以避免用无关信息不必要地占用其他 Agent 的上下文——至少大多数时候如此。
Discord 频道也让我们这些人类能够与它们互动,而我不需要向其他参与者开放运行 Agent 的机器访问权限。

不过……#
……遗憾的是,也有不少事情运行得不太好。
我们要求 Agent 在 Discord 中保持简洁。它们确实会这样做——准确地说,只能坚持 5 分钟,然后又开始写大段大段的文字……

一条这样的消息或许还能接受,但 Agent 会在 Discord 频道中频繁交流。其中很多消息是发给我们人类的,例如状态更新等。没有人想读这么多文字。
另一个痛点是本地测试执行。出于某种原因,Agent 过于谨慎。每进行一点小修改,它们都觉得有必要在本地运行整个测试套件。本地测试几乎总是通过。因此,每一次成功的测试运行,都意味着大约 4 分钟原本可以用于反编译代码的时间被浪费了。我们反复告诉它们,绝对不要在本地执行测试。我们有 CI。如果某次提交导致失败,GitHub 会几乎立即通过 Discord 发送通知。失败绝不会被忽略。然而,它们并不太在意这些指令。
一个正在变得棘手的问题是,Agent 害怕着手处理较大的 Issue。它们偏爱快速获胜,而不是较大的子系统。一旦遇到较大的阻塞问题,它们就会创建一个 Issue,推迟该问题,然后转去做更小的事情。起初这没有问题。但现在低垂的果实大多已经被摘完,这会导致 Agent 有时处于空闲状态。
Agent 偶尔会开始拒绝工作,因为它们认为自己的上下文快用完了。显然并没有。它们不知道自己的上下文里有多少 Token,即使知道,这也是运行框架需要处理的事情。当发生溢出时,自动压缩会启动。

遗憾的是,GitHub 到目前为止也几乎每隔一天就会出现问题。这使 Issue 跟踪和 CI 都相对不可靠。我希望他们能够改善正常运行时间,否则切换到替代方案就很有意义。
我学到的东西#
一次性给 Agent 太多任务,长期来看根本行不通。让它们同时进行反编译、现代化 C++ 代码和改进可移植性,效果并不好。它们要么会在第 10 次上下文压缩后忘记其中一项,要么就开始犯错。
正确的做法是先纯粹进行机械式反编译,之后再处理现代化和可移植性工作。
前两周我使用的是 Opus 5,最终在中途决定切换到 Sonnet。它稍微笨一点,但没有明显差异。就我所见,Sonnet 会犯与 Opus 相同的错误,也同样容易分心。毕竟,反编译是一项相对简单的任务:只需通过 MCP 调用 IDA,然后将结果粘贴进 CPP 文件。Sonnet 足以胜任。
为了提升它们对我们设定规则的专注程度,我添加了 PostCompact hooks,在上下文压缩后将一组规则重新注入上下文。这似乎在一定程度上有效:它们能够在较长时间内妥善管理 GitHub Issues,也不会忘记在 Discord 发布更新。但保持消息简洁、避免冗余代码注释,则是它们不愿遵守的事情。我最好的猜测是,无论是在代码里还是在消息里喋喋不休,都已深深嵌入它们的训练过程。
总结#
尽管并非所有事情都进展顺利,这项实验仍然是成功的。总体而言,反编译工作表现非常好。代码还需要进行一两轮重构,但我认为无论如何它本来就需要这些工作。MW2 是一款老游戏,有很多改进空间。
很有意思的是,当任务持续数天乃至数周时,会开始出现另一类问题。我认为,大多数问题都可以归因于上下文压缩,以及 Agent 会随着时间推移忘记重要事项。此前我只进行过持续数小时的会话,当时上下文压缩同样会造成损害,但程度没有这么严重。
该项目距离完成还很远。我们将看看后续进展以及它会如何演变。如果发生有趣的事情,我可能会发布更新。
在此,我公开邀请读者提供反馈。如果你对我遇到的问题有改进建议,欢迎通过我的社交媒体分享你的经验。
English / 原文
As a little side project, I decided to put my Claude Max sub to good use and decompile Call of Duty: Modern Warfare 2 (2009).
The goal is to decompile the project to C++ code, as close to the original code as possible, but with adjustments where they make sense. That means additional changes for portability (32 & 64 bit, Linux, macOS, etc. support), security and stability improvements will be done.
This project is done with the help of RektInator, Future, st0rm and other members of the community. The repository is private for now.
Setup#
I’m using Claude Code CLI with a Max (20x) subscription. The workforce consists of 4 agents working together towards the common goal:
There are 3 worker agents, independently working on different subsystems of the game. All of them commit and push to the same branch of the repository.
An additional agent oversees the operation and reviews every pushed commit.
All agents currently use Sonnet 5.
Agents communicate via Discord. All agents have access to one channel and can both post and read all messages in there.
The overseer has access to an additional channel, where a GitHub webhook posts notifications about new commits that landed. That automatically triggers the agent’s review task.
An additional webhook posts CI failures in the shared channel, so agents get notified when something broke.
The agents themselves manage their tasks by using GitHub issues.
There are many interesting resources for decompilation: Leaked Xbox alpha builds with symbols, macOS ports with debug data, etc. that the agents use. They all have access to Ghidra and IDA Pro via MCP servers.
Progress so far#
The agents have been running non-stop for about 4 weeks now. They have produced almost 7,000 commits:

Roughly 5,588 of 16,324 functions have been decompiled so far: about 34%. The effective figure is higher, though: a good chunk of those 16k are third-party libraries, CRT code, and other things that will never need decompilation.
The game already launches:

The agents have burned through 199.8 billion tokens getting there.
However, there is also a big chunk of things that are missing or broken:

Launching a map is not working yet, despite many of the required subsystems being implemented. This will likely only be testable as soon as almost everything has been decompiled and wired up.
What works well#
Initially, progress tracking used a STATUS.md file in the repository. That file quickly grew into a 10 MB+ giant, instantly overflowing the context when trying to ingest it.
As a consequence, we switched to GitHub issues, which works great. Agents autonomously create, edit and close them.

Surprisingly, communication over Discord is also flawless. Agents coordinate without any issues. They ignore messages not directed to them and only post messages when necessary to not needlessly fill the context of others with unrelated information, at least most of the time.
The Discord channel also enables us humans to interact with them, without me having to give the other participants access to the machines the agents are running on.

However…#
… there is a bunch of things that don’t work well, unfortunately.
We ask the agents to be concise in Discord. They are, for exactly 5 minutes, then start writing walls of text again…

One message like this might be fine, but agents actively communicate in that Discord channel. Many of those messages are directed to us humans, status updates, etc. Nobody wants to read that much text.
Another pain point is local test execution. For some reason, agents are overly careful. On every little change, they feel the urge to execute the entire test suite locally. Local test execution is almost always green. Therefore every successful test run means about 4 minutes of time that could have been spent decompiling code instead. They were repeatedly told to never execute tests locally. We have CI for that. If a commit causes a failure, there will be an almost instant notification from GitHub via Discord. Failures will never go unnoticed. Yet, they don’t really care.
One thing that is becoming a problem is that agents are afraid of starting bigger issues. They favor quick wins over larger subsystems. The moment they stumble upon bigger blockers, they file an issue, defer the problem and move to something smaller. Initially, that was fine. Now that low-hanging fruit is mostly gone, this leads to agents being idle at times.
From time to time, agents start refusing to work, because they think they’re running out of context. Obviously, they don’t. They have no idea how many tokens are in their context, and even if they did, that’s something the harness takes care of. Auto compaction will kick in when there is an overflow.

Sadly, GitHub also has had issues every other day so far. That makes issue tracking and CI relatively unreliable. I hope they manage to improve their uptime, otherwise switching to an alternative makes sense.
What I have learned#
Giving the agents too many tasks at once just doesn’t work over a long period of time. Telling them to decompile, modernize C++ code and improve portability all at once just doesn’t work. They either eventually forget one of those things after the 10th compaction, or start making mistakes.
Pure mechanical decompilation first, and then modernization/portability afterwards is the way to go.
I ran Opus 5 for the first 2 weeks and eventually decided to switch to Sonnet midway. It is slightly dumber, yet there is no noticeable difference. As far as I can tell, Sonnet is making the same mistakes as Opus and gets distracted just as easily. After all, decompilation is a relatively easy task. It’s just an MCP call to IDA and then pasting that into a CPP file. Sonnet works fine for that.
To improve their focus on the rules we set, I added PostCompact hooks that reinject a set of rules into the context. This seems to work to some extent, they properly manage GitHub issues over longer periods of time and don’t forget to post updates on Discord that way. But staying concise with their messages or omitting redundant code comments is just something they don’t respect. My best guess is that yapping, both in code and in messages, was just deeply embedded during their training.
Summary#
Although not everything went well, this experiment has still been a success. Overall decompilation works very well. The code will need a round or two of refactoring, but I think it needed that regardless. MW2 is an old game with lots of potential for improvement.
It’s very interesting that a different class of problems starts to arise when working on multi-day and multi-week sessions. I think most of the issues can be attributed to compaction and thus agents forgetting what matters over time. Previously, I have only ever had hour-long sessions, where compaction still causes harm, but not to the same extent.
The project is far from done. We’ll see where things are going and how it evolves. I might post updates when something interesting happens.
At this point, I’m openly inviting you, the reader, to give feedback. If you have ideas of improvement for the issues I have had, feel free to share your experience with me via my socials.