(如果这是问这个问题的错误地方,我深表歉意。我认为这肯定与编程相关,但如果这属于其他网站,请告诉我)
我从小就玩神奇宝贝红和蓝,这些游戏非常有趣,但因存在许多可利用的故障而臭名昭著(例如,请参阅这个游戏的荒谬的速通 http://www.youtube.com/watch?v=cYHYL8JJsFo使用内存损坏将项目屏幕变成十六进制编辑器)。
最近,我发现了游戏中一个有趣的速通游戏,它使用了一个名为“ZZAZZ 故障”的故障来破坏重要的内存位置,并让玩家几乎立即赢得游戏。根据作者对速通的描述 http://tasvideos.org/2945S.html,ZZAZZ 故障的工作原理如下:
要开始训练师战斗,游戏需要加载大量数据,例如[...]如果失败他将承认的金钱。当它加载金钱时,事情就会变得非常糟糕。由于我无法理解的原因,金钱以完全不同的方式存储,游戏使用三个字节的数据结构,而不是将值转换为二进制,而是以“人类”表示形式存储。例如,$123456 将存储为 0x123456,而不是正确的转换 0x01E240。
[Trainer 表中的一些无效条目] 指向具有无效金钱数据的位置。当游戏尝试使用上述结构中的这些数据执行算术时,它会发疯并开始覆盖大部分 RAM。更具体地说,对于每个三个字节的块,其中两个将包含 0x9999(训练师可以给出的最大金额)。这种模式通过 RAM 重复多次。为了更好地看到这一点,我建议在面对 ZZAZZ 训练器后暂停模拟器上的视频,并将 VBA 的内存查看器设置为 0xD070。
这种分析是有道理的,但作为一名程序员,我忍不住想知道程序员到底是如何编写使这成为可能的代码的。如果输入不是有效的十六进制编码的十进制数,我能想到的编写将十六进制编码的十进制数转换为十进制数的函数的方法都不会开始用 0x9999 填充随机内存块。
我的问题是 - 没有专门设计算法以这种方式失败,是否存在从十六进制编码的十进制到十进制的转换的直接实现,当输入无效值时可能会导致这种内存损坏?
再次强调,如果这是题外话,我深表歉意。我的想法是,这个网站上的其他程序员可能也是玩这个游戏长大的,这听起来像是逆向工程中的一个有趣的练习,试图找出这样的故障是如何发生的。
老实说,我的猜测是,这只是某人在编写他们的第一个目标游戏时犯的一个愚蠢而令人讨厌的故障。 《口袋妖怪红/蓝》是该系列中的第一个,并且有很多其他故障,任天堂通常会排除批次测试,我想知道它是如何通过的。滚动屏幕移动问题是让我困扰的问题。无论如何,谁知道他们在想什么。也许这个区域是通过脚本写入的,因此存储的内容不同。也许位模式0x0101
用于显示内存已释放,并且该代码意外地在奇怪的地方变得疯狂。我可以翻阅 Z80 代码并在该平台上重温我自己的游戏开发时间,但是呃。试图解密他们的想法需要太多的工作。
不过确实赚了不少钱……
Edit 1:
好吧,你已经赏金了。我花了更多的时间仔细回忆,为你找到了一个花絮。 GBC/DMG 有一个称为DAA
。小数调整累加器 (A)。它的作用是将累加器中的值转换为BCD
格式。您所看到的内存区域已经在BCD
格式:http://en.wikipedia.org/wiki/Binary-coded_decimal http://en.wikipedia.org/wiki/Binary-coded_decimal
现在我可以告诉你,在我手工编写游戏 Z80 汇编程序的 4 年左右的时间里,我从来没有需要过这个操作码,只在我们制作的棒球游戏中见过它用于显示一些分数。虽然它是 1 周期算术指令,但我在正常编码中从未真正找到它的良好用途。唔。实际上我还保留着任天堂的 DMG 技术文档。想想看;)无论如何,除了它以时髦的方式与许多标志混淆之外,它也没有什么令人兴奋的地方。
我的猜测是该表被假定位于BCD
格式。将其更改为该格式之外的内容会导致内部数学变得极其混乱 - 在不应该设置的情况下设置进位和零标志。这会导致从一列溢出到下一列,从而导致计算非常大的数字。如果不直接查看读取该区域的相关操作码,我不能肯定地说,但我猜测这里有一个包罗万象的检查,表明在完成后是否仍设置进位BCD
数学,设置最大值而不是存储负值或越界值。那个或者那个DAA
指令,当接收垃圾数据正在返回时0x99
因为它有返回值,尽管我对此不太确定。
希望这可以帮助...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)