首页
/
新闻
/
Can you run every line of code in Super Mario Bros.?
Can you run every line of code in Super Mario Bros.?
摘要
A speedrunner attempts to execute every byte of the 32KB ROM in Super Mario Bros. using glitches and exploits, covering most of the code including unreachable paths, while documenting the remaining unexecuted bytes.
<p><a href="https://lobste.rs/s/qa7i6t/can_you_run_every_line_code_super_mario">Comments</a></p>
查看缓存全文
缓存时间:
2026/07/06 14:06
**TL;DR:** 一位速通玩家尝试在《超级马里奥兄弟》中运行全部32KB ROM的每一行代码和每一个字节,通过多种漏洞和操作,最终成功覆盖绝大部分内容,并发现了一些理论上的不可达代码。
## 挑战目标:运行每一行代码
《超级马里奥兄弟》的程序ROM包含32,768个字节,其中22,790个是CPU指令,其余是关卡、音乐、动画等原始数据。在典型的“100%完成度”通关中,玩家会游玩所有关卡、击败所有Boss、收集所有道具。但本挑战更进一步:不仅完成这些内容,还要让CPU读取ROM中的**每一个字节**——从每个数据表中读取、执行每条指令。作者称之为“ROM极限挑战”。
启动主机后,标题画面、马里奥移动、碰撞检测等程序已经运行了16%的ROM。让标题画面自动演示,播放屏幕滚动、加载敌人、板栗仔程序、撞击砖块、收集蘑菇、受伤、死亡等,共计覆盖31.9%的ROM。
## 初次尝试:双人模式与“穷举”
作者选择了双人模式,触碰屏幕边缘、撞击砖块、蹲下、收集1UP蘑菇、将板栗仔变成诺库龟……尽量执行各种操作,包括一些可能触发bug的动作,比如图形缓冲区溢出。主要目标是先跑遍所有房间,再回头补漏。
大约一小时后,作者以路易吉身份救出公主,以马里奥身份获得一个游戏结束,并开始了二周目(板栗仔被替换成硬壳龟)。但初次运行仍有459个字节未运行。
## 有趣的部分:被忽视的代码路径
### 振荡平台与红色诺库龟
如果只为速通快速冲刺,振荡平台(oscillating platform)和红色诺库龟(red Koopa)不会完成一次完整的振荡周期。同样,飞行泡泡鱼(flying Cheep-Cheep)和刺龟(Spiny)的部分代码也需要特定条件:例如,当马里奥的水平速度为零时,它们的行为会不同。
### 飞行泡泡鱼的随机性
飞行泡泡鱼有16个随机出现位置和12种随机进入速度。作者花了几乎整个关卡的时间才集齐所有组合。
### 刺龟重生与不可达代码
刺龟属于“无限生成”的敌人。当有空精灵槽位时,它会检查并重生在第一个空槽位。但逻辑上存在一个保护性分支:当所有精灵槽位都满时,会执行一条BMI指令中止。然而,要触发这条BMI,需要同时满足“有一个槽位为空”和“所有槽位都被占用”的矛盾条件——这是典型的不可达代码。作者认为,只有通过任意代码执行(ACE)漏洞才能运行它,但速通规则禁止卡带插槽操作(必须正确插入),从而封死了所有已知ACE方法。
## 旗杆旗帜消失:诺库龟的神奇冒险
正常通关时,马里奥降下旗杆上的旗帜。但游戏中有一个安全措施:如果旗帜缺失,马里奥会直接跳下。如何让旗帜消失?作者咨询了前世界纪录保持者GTAce(未获明确回答),但自己分析出原理:旗杆旗帜始终占据最后一个精灵槽位。通关后出现的小星形旗帜,如果找不到空槽位,会覆盖旗杆旗帜。因此,需要在到达旗杆时让屏幕上同时存在5个敌人,使星形旗帜的优先级高于旗杆。
问题在于,楼梯很难把敌人带到旗杆处。关键在于“诺库龟的神奇冒险”:当敌人低于地面水平时,它们会停止检测墙壁;如果踩扁它们,会表现出仿佛在地板上的行为。作者选择8-2世界(有大量诺库龟和坑洞),用TAS工具让五个精灵槽位全部进入“神奇冒险”模式,然后无阻挡走完关卡。最终导致旗帜消失,运行了三个新字节。
## 平衡平台的速度限制与精灵继承
平衡平台(balancing platform)有速度限制(每帧3.5像素),但代码中存在一个错误:当速度等于限制时不会触发限制,只有大于时才触发。因此需要让平台达到每帧4.5像素才能运行那段代码。作者尝试利用“精灵继承”技巧:平衡平台会追踪配对平台的精灵槽位;如果配对卸载,新加载的任意物体都会被当作另一半(即使不是平台)。通过诺库龟的神奇冒险,可以让振荡平台表现得像平衡平台,并带出屏幕外。但速度限制代码依然无法触发——作者认为这是不可达的。
## 背景图块与屏幕编号Bug
背景的灌木和云朵图块包含未使用的零字节。背景每三个屏幕重复一次。游戏使用循环减3的方式决定绘制哪个屏幕。但代码使用了`BMI`指令(有符号分支),而不是`BCC`(无符号进位清除)。因此,当屏幕编号为负数(-125到-1)时,仍会触发分支,导致从未使用的背景图块中读取数据。
如何向右跑过131个屏幕?利用卡进地板、击碎砖块、触摸旗杆的bug,马里奥会无限向右跑。作者最终手动复位,但已读取了那些未使用的字节。
## 精灵初始化跳转表与短火焰棒
精灵初始化程序的跳转表中有大量未读字节。食人花通常不由屏幕滚动初始化(而是由水管图块生成程序激活)。此外,还有“短火焰棒”这种变体,它的初始化代码包含额外字节,但需要特定条件才能触发。
## 水下关卡数据损坏:一次性读取多个未用字节
在双人模式下,若一名玩家在水下关卡死亡,另一名玩家在攀爬藤蔓时死亡,会损坏水下关卡的敌人数据。具体原理:攀爬藤蔓时设置标志使下一个房间生成藤蔓,藤蔓占用精灵槽位5,然后初始化气泡的代码假设X寄存器为0,但此时X=5,导致写入气泡位置数组越界,覆盖了敌人数据指针的低字节。于是游戏从世界1-4的图块数据表中读取,将其当作敌人数据,从而产生一堆能够触发未使用敌人初始化程序的垃圾数据。
重复该操作于所有水下关卡的检查点,可以运行以下未使用的敌人类型:已踩扁的红色诺库龟、已踩扁的绿色诺库龟、食人花、未使用的火焰棒以及一个蘑菇。
## 结论:仍有部分字节未运行
作者认为已经做到了极限。剩余未运行的部分包括:
- 平衡平台速度限制的向上重力子程序(认为不可达)
- 刺龟重生代码中的BMI指令(因无ACE而不可达)
- 每个城堡关卡结尾的终止符字节(在触摸斧头后,精灵槽位被蘑菇头占据,永远不会读取终止符)
- 部分背景图块数据(可能无法通过正常或bug方式读取)
此外,视频未涉及字符ROM的图形数据,但作者在结尾简要提及。
Source: [Can you run every line of code in Super Mario Bros.?](https://www.youtube.com/watch?v=o0gOALTvkcc)
相似文章
Lobsters Hottest
The article explores Nix's laziness, showing how attribute paths can lazily generate infinite trees, and turns this into a fun hack where each button press in Super Mario Bros. 3 is a separate Nix derivation with the store as savestate history.
X AI KOLs Following
一条推文报道,有人一边照顾新生儿,一边使用 DeepSeek Flash 0731 在手机上对《Super Smash Bros Melee》进行了反编译和逆向工程,将其转换为大约 5000 行 C 代码。
Hacker News Top
一篇技术博文,解释了虚拟机中将字节码偏移量映射回源代码行的技术,使用游程编码减少内存开销,具有 O(r) 内存和 O(n+r) 顺序访问,并讨论了随机访问的前驱问题。
Hacker News Top
作者宣布,任天堂64游戏《Snowboard Kids 2》现已完全反编译,意味着所有函数都有了对应的C语言实现,并能够编译回原始汇编代码。该项目耗时近两年,功劳归于N64反编译社区以及AI编程助手(Claude、GLM、Codex)的加速作用。
Fabien Sanglard
对超级任天堂卡带的详细技术分析,涵盖 CIC 复制保护、ROM 容量分布、带电池备份的 SRAM 以及 Super FX 等增强处理器。