解构神奇宝贝毛刺? [英] Deconstructing Pokémon glitches?

查看:159
本文介绍了解构神奇宝贝毛刺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我很抱歉,如果这是错误的地方问这个,我认为这绝对是编程相关的,但如果这属于其他网站,请让我知道)



我长大了玩神奇宝贝红色和蓝色,这些游戏非常有趣,但由于存在大量可利用的故障而出现臭名昭着(例如,请参见

最近,我发现了这个游戏的快速运行,使用内存损坏将项目屏幕变为十六进制编辑器。一个有趣的快速运行游戏,它使用称为ZZAZZ小故障的故障来腐蚀重要的内存位置,并允许玩家几乎立即赢得游戏。根据作者对speedrun的描述,ZZAZZ小故障的工作原理如下:


要开始训练师战斗,游戏需要加载大量数据,例如他击败后会承认的金钱。当它加载钱是事情可以变得非常丑陋的地方。由于我无法理解的原因,钱以完全不同的方式存储,游戏使用三个字节的数据结构,而不是将值转换为二进制,它将其存储为人表示形式。例如,$ 123456将存储为0x123456,而不是0x01E240,即正确的转换。



[Trainer表中的一些无效条目]指向带有无效货币数据的位置。当游戏试图在所述结构中使用这些数据执行算术时,它变得疯狂并开始覆盖RAM的大部分。更具体地说,对于三个字节的每个块,其中两个将包含0x9999(教练可以提供的最大金额)。这种模式通过RAM重复多次。为了更好地理解这一点,我建议在ZZAZZ教练面对之后在模拟器上暂停视频,并将VBA的内存查看器设置为0xD070。


这种分析是有道理的,但是作为程序员,我不禁想知道程序员如何编写代码来实现这一点。如果输入不是一个有效的十六进制编码的十进制数,编写一个将十六进制编码的十进制数转换为十进制数的函数将无法开始用0x9999填充随机存储块。



我的问题是 - 没有专门设计算法以这种方式失败,是否存在从十六进制编码的十进制转换为十进制的直接实现,可能会导致此类内存损坏如果以无效价格喂食?



同样,如果这是脱离主题,我的道歉。我的想法是,这个网站上的其他程序员可能也已经长大了玩这个游戏,这听起来像是一个有趣的反向工程练习,试图找出这样的故障是如何可能的。

解决方案

神秘解决了!它看起来像用户TheZZAZZGlitch找出了导致此问题的原因



当游戏尝试计算一个非常大的整数时触发毛刺。在内部,游戏有一个例程,它反复增加值来模拟乘法。它看起来像写入字节一样,在输出写入位置上移动。该代码旨在切断任何超过0x009999的值,以便玩家在教练的战斗中获得的收益不超过9999美元(值以十六进制编码的十进制数存储)。然而,游戏在这种情况下忘记重置输出指针,所以如果产生一个非常大的数字,游戏将通过移动写入指针并将0x99写入每三个字节中的两个字节来重复地在RAM上写入模式0x009999。



希望这有助于!


(I apologize if this is the wrong place to ask this. I think it's definitely programming related, though if this belongs on some other site please let me know)

I grew up playing Pokémon Red and Blue, games that were great fun but are somewhat notorious for having numerous exploitable glitches (for example, see this ridiculous speedrun of the game that uses memory corruption to turn the item screen into a hex editor).

Recently, I found an interesting speedrun of the game that uses a glitch called the "ZZAZZ glitch" to corrupt important memory locations and allow the player to almost immediately win the game. According to the author's description of the speedrun, the ZZAZZ glitch works as follows:

To start a Trainer battle, the game needs to load a lot of data, such as [...] the money he'll concede if defeated. When it loads the money is where things can get really ugly. For reasons that are beyond me, money is stored in a completely different manner, the game uses a data structure of three bytes and instead of converting the value to binary, it stores it in "human" representation. For example, $123456 would be stored as 0x123456 instead of 0x01E240, the proper conversion.

[Some invalid entries in the Trainer table] point to location with invalid money data. When the game tries to perform arithmetic with these data in said structure, it goes nuts and starts overwriting huge portions of RAM. More specifically, for every block of three bytes, two of them will contain 0x9999 (the maximum amount of money a trainer could give). This pattern repeats itself many times through RAM. To see this better, I recommend pausing the video on the emulator after the ZZAZZ trainer is faced and set VBA's memory viewer to 0xD070.

This analysis makes sense, but as I programmer I can't help but wonder how on earth the programmers wrote the code that would make this possible. No approach I can think of for writing a function that converts a hexadecimal-encoded decimal number to decimal would ever start filling random blocks of memory with 0x9999 if the input wasn't a valid hexadecimal-encoded decimal number.

My question is - without specifically designing the algorithm to fail this way, is there a straightforward implementation of a conversion from hexadecimal-coded decimal to decimal that could result in this sort of memory corruption when fed in an invalid value?

Again, if this is off-topic, my apologies. My thoughts are that other programmers on this site may have also grown up playing this game, and it sounds like an interesting exercise in reverse-engineering to try to figure out how a glitch like this could be possible.

解决方案

Mystery solved! It looks like user TheZZAZZGlitch figured out what causes this.

The glitch is triggered when the game tries to compute an extremely large integer. Internally, the game has a routine that repeatedly adds values to simulate a multiplication. It seems to write bytes as it goes, shifting over an output write position. The code is designed to cut off any value that exceeds 0x009999 so that the player doesn't earn more than $9999 from a trainer battle (the values are stored in hexadecimally-coded decimal). However, the game forgets to reset the output pointer when this occurs, so if an extremely large number is generated, the game will repeatedly write the pattern 0x009999 across RAM by shifting the write pointer over and writing 0x99 to two out of every three bytes.

Hope this helps!

这篇关于解构神奇宝贝毛刺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆