禁止发言
精华
|
战斗力 鹅
|
回帖 0
注册时间 2003-7-20
|
数据溢出
先解释一下数据溢出。游戏进行时,任何需要用到的数值以及即时计算出的数值都会保存在内存里。比如有时候是用1 byte的地址来保存,也就是能保存0-255(16进制FF)的数值。正常情况下,当某个数值超过这个范围时,系统会自动把数值调整到最大值。但在某些情况下,游戏程序员可能认为一些数值是不可能超过这个范围的,所以没做相应的检查和调整。此时,当一个数值比如257要保存到1 byte的地址时,就会自动去掉1 byte以上的部分,256归0,257就变成了1。这就是数据溢出现象。
我最早是在这个讨论FF6的Ultima伤害的帖子里知道这个现象的:(帖子里有某大王的斗嘴哦)
http://www.ffsky.com/ff/ffsky/bb ... A101&ID=1429961
有兴趣的可以看一下帖子,我在这里简单总结一下:
Tina的魔力140(包括装备),等级99,这样她使用Ultima的伤害为:
150×4+×140×99×150/32=600+64968=65568
这个数值已经超过了2 bytes的最大值65535(FFFF),实际伤害就变成了65568-65536=32,而不是传统的9999封顶。同时也说明了,伤害这个数值在FF6里是以2 bytes的内存地址保存的。
FF6要达到65535是相对来说是比较简单的,在正常通关里也容易发现。
说完了这些,我对数据溢出这个现象产生了一些好奇心,于是就找了些帖子和文章以及拿几作FF来实验一下,看看有没有类似的bug。主要实验的是伤害值,因为这是最容易测试以及最容易产生类似的bug的。FF的伤害一般9999封顶,而2 bytes是65535,可能差距比较大,所以游戏程序员都偷懒了。另外一些数据溢出也是由伤害部分引申而来。
这个实验也算是和研究极限伤害有点类似了。
注:虽然用到了内存查看和修改来测试,但以下所有现象都可以用正常的游戏方式达成。
FF4
http://www.ffsky.com/ff/ffsky/bb ... A101&ID=1541605
简单说就是:
让summoner在一场战斗中无限召唤,在这场战斗中打倒该怪物的只数,最大值是255,超过就会归0重头计算,此时钱和经验都归0重新算。
仅对sfc版有效。
FF6
上面已经说过了,可能还有其他方法可以达成,不过我没试过。
FF7
根据计算公式,想要达成65535非常简单。先用Power Source控制str以及升级,装备Yoshiyuki,随便挑个怪物,在同伴都活着的情况下,比如打出敌人7300的伤害,再砍死2个同伴,用2次Hero Drink,再用D.Blow砍敌人,伤害就达到了7300*1.6*3*2 = 70080。这个数据已经满足了溢出65535且没达到65535 + 9999(不然即使有数据溢出显示的还是9999)。很可惜,最终伤害还是9999,FF7伤害并没有数据溢出bug。换了一种方式,用Berserk代替D. Blow,再多用2次Hero Drink,再调整一下伤害,还是不会溢出。可能游戏使用了更长的地址来保存伤害,又或者已经有检查伤害是不是溢出的步骤。
是不是没有办法了呢?想起以前听Tifa说的HP absorb魔石有数据溢出现象,所以再次尝试。
随便用哪个人物,装备圆桌骑士+HP absorb,对任何普通杂兵时正常,吸收的HP是伤害显示/10,复数敌人的话累积,圆桌骑士只算最后一击,最多不超过敌人HP上限。然而,用此配置对红宝石发动圆桌骑士时却出现了奇怪的现象。最后一击的伤害是8500左右,照理说应该吸收850HP,但却显示吸收了1000多一点,而实际上却是吸收了9999(或以上,无法证实)!这个现象暂时无法解释,我暂且猜想原因也是数据溢出,虽然和普通的溢出不太一样。具体细节有待进一步研究。
FF8
FF8虽然伤害突破9999,但单击攻击力都很低,很多招数连9999也达不到,更别说65535了。我翻遍了资料,看到的最强的伤害值是召唤兽Eden的Eternal Breath60000,可惜离65535还是差一点。本来我以为没希望测试了,但没想到看到这帖:
http://www.ffsky.com/ff/ffsky/bb ... A104&ID=1487011
竟然在这种情况下找到了数据溢出的bug。
简单地说就是用Return Damage反弹Omega的最强招Terra Break。Terra Break虽然每击伤害都不算太大,但加起来是很可观的,而且很容易就超过了65535。正常情况下,没问题,但系统用这个总数值去计算Return Damage的时候却出现了问题,数据溢出,本来应该轻松反到9999的,现在却只有300多了。
FF9
FF9的伤害感觉上去不算大,9999技已经很厉害了,所以我很期待能看到FF9的数据溢出现象。参照伤害计算公式,实验很简单,用Sterner装备圣剑II,装备强化圣属性头盔,挑选圣弱点的敌人,再配合trance,很容易就把伤害控制在了65535到65535 + 9999的范围内。很可惜,数据并没有溢出。我再把trance换成最强技能Shock,还是不行。魔法系攻击最高伤害是最终召唤Ark 106 + 99颗石头攻击力,再加上属性强化伤害,然后伤害是(99+(99+99)/8) * (106+99)*1.5*1.5 = 57079。没有达到65535,放弃。
很可惜,我并没有发现任何FF9的数据溢出bug。
FFX
FFX本身就有伤害界限突破,所以至少要用到3 bytes来存储伤害,但实际情况很可能是用到了4 bytes。如果是4 bytes的话,想都不用想,那是不可能突破的。即使是3 bytes,3 bytes是16777215,我找遍了所有提升伤害的办法,还是没办法超过。这里就把我找到的最大伤害写一下:日版Auron,七耀武器,HP 1,str 255,战斗中用cheer加到260,给自己加狂暴,敌人不限,无任何状态,普通攻击如果是会心一击的话,伤害是(260^3÷32+30)*4.3*16/16*2*1.5 = 7085712,也就是说如果没有伤害封顶的话,Auron一击能打敌人700多万hp。国际版由于Auron的七耀武器伤害倍率减半,所以情况比较复杂,可能不再是最高了。
FFT
FFT伤害最高999封顶,这样的数据一般不会用1.5 bytes来存,所以猜测伤害还是用2 bytes的内存空间。FFT里要达到65535伤害的可能性只有一种,那就是空手。事实上在测试过程中,我发现了很特别的现象。FFT确实是用2 bytes来存储预测伤害值,显示伤害值(就是砍到敌人身上显示的数值)以及实际伤害值,但预测伤害值和实际伤害值存储的范围并不是通常的0-65535,而是-32767到+32767,而显示伤害值是0-65535。也就是说,只要伤害值超过32767就会不正常。所以当伤害值在-32767到+32767这个范围内就会有如下结果:

预测伤害值显示不正常,显示伤害值还是999,而实际结果是给对方加hp,如果伤害值为65535,就是给对方加1hp,如果伤害值为65534,就是给对方加2hp,以次类推。如果再增大伤害值超过65535,那就是普通的数据溢出结果了,预测伤害值,显示伤害值以及实际伤害值都溢出,都得减去65536。我本来猜想那一半负数是用来处理加血的,不过事实上并不是这样,具体比较复杂。实际情况差不多是这样,通过计算预测数字存储在一个变量A,是伤害还是回复存在其它地址里,我没研究过。然后,如果是伤害,那就再在变量B里存储这个预测数字,变量C为0;如果是回复,那就是在变量C里存储这个数字,B为0。实际伤害另算。也就是说伤害和回复存储在不同变量里,其实这一半负数值是被完全浪费掉的。
随后,我又试了一下状态魔法的命中率,计算命中率可以达到255以上,不过没有出现数据溢出现象。
顺便说一下FFT里的极限单击伤害值(不包括会心一击):空手装备格斗或者转拳术师,和对方相同星座相同性别,在战斗中先把自身AT提高到99,勇气提升到100,把对方变青蛙并让其睡眠,再给自己加狂暴。最后伤害值为99*1.5*1.5*1.5*1.5*1.5*99,过程需要舍去小数,最终结果为74052。
这篇东西就写到这里了,其实就是些无聊的数字游戏而已,而且基本都很早被发现了,我只是在这里总结一下。大家有兴趣的话也可以在其它游戏里寻找并试验一下。参考了很多资料,比如GameFaqs上的各作数据计算公式,就不一一列出了。 |
|