原文地址:https://www.gcores.com/articles/131031 原作者:OKATU

 

原文摘自由本人编写的“神奇宝贝百科”的“时钟电路漏洞”词条,有少量删节修改
概论
时钟电路漏洞,在海外多称为称树果漏洞(日文︰きのみ問題,英文︰Berry glitch),是一个最早在《宝可梦 红宝石/蓝宝石》中被发现的漏洞,是原始游戏卡时钟电路(RTC)的设计缺陷导致。由于旧有RTC的设计比较原始,再加上游戏设计者对游戏设计中没有提供一些便利的功能,理论上,早期带有RTC晶振的实时时钟的游戏都会遇到这个问题,只不过由于《宝可梦》系列游戏的知名度,这一问题在宝可梦领域反而是第一次被重视起来。
漏洞的技术原理概论
除了早期一些游戏以及廉价的盗版卡,大多数GBA游戏卡的存档都普及了EEPROM或FLASH,不再存在给SRAM供电的电池,《宝可梦》也不例外。但是《宝可梦 红宝石/蓝宝石/绿宝石》的正版卡带却带有一块电池,这块电池根本不是给存档供电的,而是在给实时电路供电。当然,盗版卡带为了节省成本依然在用SRAM。
另外说一个题外话:最早的《绿宝石》“盗版卡带”有在进入殿堂时掉档的BUG,是因为绿宝石的存档虽然是64Kbits的,但是游戏内有备份机制,所以正版卡的存档其实是保存了两份。而FLASH芯片的存档大小其实是128K,但是最早分析ROM的盗版商发现存档只有64K,于是盗版商只给卡带配了一块64K的SRAM芯片,《绿宝石》在进入殿堂后会有一次双覆盖存档的过程,就会导致存档损坏。
美版《绿宝石》卡带拆解图,图中RTC部分就是时钟电路
美版《绿宝石》卡带拆解图,图中RTC部分就是时钟电路
《宝可梦 红宝石/蓝宝石/绿宝石》的游戏卡拥有时钟电路使用精工S-3511 石英晶振进行电路驱动,但那个年代的GBA卡带中的晶振,既没有对时功能,也不能靠网络获取真实的日期时间对时,其时间计算方式是由一串规则计算而来的相对值:
  1. 游戏卡时钟电路启动时的基准时间为“2000年1月1日 00:00:00”,之后时钟电路会不断运作,并且在除电池电量耗尽的情况下会一直向未来运作。
  2. 而当玩家开始《红宝石/蓝宝石绿宝石》的新游戏,玩家需要在主角家中钟表上设定时间,钟表表面默认为上午10时,而玩家设定的时间会被作为“起始时间戳0时”,游戏的报告会用一个五位数(10进制)记录游戏流逝的时间,其中初始零时记为00000。
  3. 之后游戏内在每次存档时,会与时钟比对,在此基础上将时钟电路上从“起始时间戳”开始,经过的日、时、分、秒数(年月全部换算为日数)以及星期转化为一串数字,并作为时间戳存储在游戏的报告内,这个经过时间是随着现实时间流逝,与实际游戏时间无关,在游戏关闭的时候,游戏的“经过时间”(并非是游戏的实际游玩时间)依然会向后运作。
  4. 每次游戏内种植树果和进行周期性事件后,存档会记录下下次事件刷新和树果成熟的时间戳,直到时钟电路的时间运行到这个刷新的时间戳之后,所有的事件才会刷新,树果也会成熟。
时钟页面,由于《宝石》系列设计的对时只有这一次,再也没有对时机会,所以这就是问题最根本的起因。
时钟页面,由于《宝石》系列设计的对时只有这一次,再也没有对时机会,所以这就是问题最根本的起因。
举个栗子:游戏卡的时钟电路启动后3小时(电路时间为2000年1月1日3时0分)玩家开始了新游戏,而玩家一开始在主角家中调整钟表的时间为上午12点(距离游戏内钟表默认时间上午10点相差2小时),并在此时存档,游戏会以此时作为“起始时间0时”开始计算游戏的经过时间,
而在5天后的下午1点再开机并存档的时候,此时时钟电路的时间则是2000年1月6日4时0分,即便游戏实际只运行了1分钟,游戏存档的时间戳记录的时间仍然是5天1小时。
如果在此时种下一颗橙橙果,而第三世代中橙橙果的成熟时间是12个小时,那么时间戳会记录下这株橙橙果的成熟时间戳是“5天13小时”,当时钟电路走到“2000年1月6日16时”的时候,这株橙橙果便会成熟。
当年盗版玩家永远享受不到的乐趣
当年盗版玩家永远享受不到的乐趣
用表格表达就是:
《红蓝宝石》的时钟漏洞
《红宝石/蓝宝石》中的时钟漏洞是有官方说明的一个BUG,并且被官方承认。
BUG产生的原因在于程序员将时间戳的记录方式搞错(“技术领先”的Gamefreak),导致晶振时间在“2000年”(不等于现实的2000年)的时候,存档的时间戳反而会忽略累积年份。
这一问题直接导致存档时间戳记录到“第367天”的时候(2000年是闰年),漏洞会导致该时间戳不是“启动后第367天”,而是自动重置到“启动后第1天”,游戏存档时间戳会立刻早于晶振367天。
最终的结果就是:在“第366天”前触发的周期性事件和种下的树果,本应在“第367天”刷新和成熟,但由于时钟电路的“第367天”错误的变为“第1天”,因此所有事件的刷新和树果的成熟将因为没有到达重置的时间而被冻结,直到366天之后,时钟电路进行到“2002年1月2日”之后,存档时间戳再度累积到“第367天”到来的时候才会解除。 而游戏启动时时钟电路已经运行到2001年1月1日之后的存档则不会触发漏洞。
用表格表达就是:
这个BUG如果对于经常搞程序的程序员应该不太陌生:它与计算机的时间不同步的问题有着许多共同点,即当硬件的时钟与系统文件的时间印记不同步的时候,可能会导致系统内对文件的修改变为无效。
不过计算机可以通过调整硬件的时钟来解决问题。但GBA游戏卡却没有给出官方的调整硬件时钟的手段,这就导致问题会一直出现。
衍生漏洞:电池耗尽与换电池
由于整个时钟电路全是靠一块电池驱动,所以不可避免的出现电池耗尽的情况, 当时钟电路的电池耗尽的时候,时钟电路会被强制重置为2000年1月1日 00:00:00,正常电池耗尽的游戏会在标题屏幕有警告信息来警告时钟无法运作。相反,触发了时钟电路漏洞的游戏反而不会出现这条警告信息。 而游戏虽仍可正常运作并记录,但无法体验时间系统的相关内容。
直到今天,几乎所有的GBA带时钟的卡带的时钟电池都是没电的,所以广大玩家基本都尝试采用了把旧电池拆掉换上新的焊脚电池,当然这里比较推荐的是CR1616贴片电池座(网上有售),可以完美放进卡带内,又不用频繁更换焊脚电池。
我个人的《绿宝石》卡带
我个人的《绿宝石》卡带
但是更换电池后,在游戏内又会触发一个官方并未在意的新漏洞,民间一般称为新电池漏洞。
因为在更换电池后,时钟电路依然会重置,而开始从2000年1月1日 00:00:00开始重新计算,
而与《红蓝宝石》官方漏洞不同,这里的问题是:时钟电路远早于早于报告的时间戳导致时间错位,而当错位发生的时候,时钟电路无法到达游戏存档的时间戳的下一个刷新时间,导致所有的事件都被冻结,直到时钟电路的时间再度运转到和游戏时间戳一致或快于游戏时间戳,然后再运行到时间戳设定的刷新时间之后才会再度恢复正常。
举个栗子:
假设游戏的“起始零时”是时钟电路的2000年1月1日0时,而时钟电路已经走到2011年1月1日0时,时间戳则记录为4018天0时,此时种下一颗橙橙果,那么时间戳会设定下一次橙橙果成熟的日期是4018天12时。而假设此时电池突然耗尽,那么更换电池后,时钟电路回到了2000年1月1日0时,那么时钟需要再经过4018天12时,也就是11年零12个小时,这株橙橙果才会成熟,而且时间戳才会更新下一次事件的刷新时间。
用表格表达就是:
于是树果变成了千年老山参……
理论上,这个漏洞的危害远高于早期的《红蓝宝石》树果漏洞,因为这一漏洞不仅《红宝石/蓝宝石》会触发,包括没有漏洞的《绿宝石》也会触发这种新电池漏洞,而由于此漏洞在游戏发售后多年,时钟耗尽时才会发生,因此官方并未针对这种问题给出解决办法,官方的修复程序也无法修复此漏洞。
官方修复树果漏洞
由于是宝可梦第一次出现大规模且必定会发生的恶性漏洞,因此任天堂多次对此漏洞进行了批量修复,首先在新版本的《红蓝宝石》上,已经修补了此漏洞,而对于已经销售的早期版本,也提供了多种修复方式,除此之外,玩家还可以将游戏卡寄至任天堂进行修复(寄送维修服务已于2016年9月停止支援)。
修复程序的修复原理是将位于2001年之前的时钟电路强制调整为2001年1月1日,并将存档时间戳一并后延,以跳过发生漏洞的2000年。
首先, 任天堂在《火红/叶绿》和《绿宝石》自带修复程序,需要玩家用以下操作进行修复:
  1. 将一台GBA连接到游戏连接电缆的1P上,插入并打开《火红/叶绿》或《绿宝石》,在游戏标题按select和B,进入修复程序,按A。
  2. 另一台GBA连接到游戏连接电缆的2P上,插入《红宝石/蓝宝石》,按住select和start开机,进入修复程序,根据提示进行修复。
  3. 每次重新进行游戏或更换过电池重新进行游戏后,需要再度进行修复。
《火红叶绿》修复程序
《火红叶绿》修复程序
之后在《竞技场》系列发售后, 《红宝石/蓝宝石》与宝可梦XD 暗之旋风 黑暗洛奇亚进行联动后,将会自动下载修复程序。
而日本方面随杂志附赠特制专用E卡也可以来刷入修复程序。
修复E卡
修复E卡
新电池漏洞的探究
对于新电池的漏洞的研究最早由Furlock’s Forest Wiki的维护者Adam提出(由于作者网站出现了问题,目前只有首页和软件下载了,关于研究页面只有备份) 。最终发现自己编写的自制程序,读取《红宝石/蓝宝石/绿宝石》游戏卡内部时钟电路的时间,将其运转的时间设置为晚于游戏存档的时间戳,之后再存档一次刷新时间戳,即可解除问题。
GBA的RTCread程序
GBA的RTCread程序
而后作者公布了源代码,但是GBA版程序需要配合GBA烧录卡,并在运行后插拔换卡,之后作者rikten又以此源代码制作了NDS版本,这样NDS玩游戏的玩家可以在不换卡的情况下修改时钟。
 NDS版RTC read
NDS版RTC read
理论上,这个软件可以解决一切带有时钟的GBA游戏的时间错位问题
但此方法虽然能够解决《宝石版》的时间运转问题,却会导致游戏内的时钟变得与真实时间不一致。
主角家中的这个时钟的时间会乱掉
主角家中的这个时钟的时间会乱掉
如果需要把时钟表面也对准,需要进行下一步:修改存档。
先利用第三方设备(如月光宝盒、Retro Freak)或者软件(如配合NDS使用的GBA Backup)提取游戏存档,再利用存档修改程序将报告的“起始时间戳0时”设置为0天0时0分0秒,时间戳设置为当前时刻距离2000年1月1日的天数和时间,然后再导入游戏卡内。之后利用Furlock’s Forest Wiki的程序将时钟电路运转的时间设置为等于或略晚于游戏报告的时间戳,即可让时间电路的时钟和游戏存档的时间戳同步。
虽然“魔法师软件”很不道德,但是利用时钟修改功能也是不得已为之
虽然“魔法师软件”很不道德,但是利用时钟修改功能也是不得已为之
这样游戏内的钟表也会与现实时间一致了,当然如果不是强迫症的话,只要修改晶振时间就好了。
后记
这一漏洞的根本原因在于官方并未给《宝石》版游戏提供游戏内的实时时钟对时功能,导致游戏一旦出现时钟错位,就会立刻导致连锁反应。而官方从第四世代宝可梦开始,宝可梦游戏的时间和日期获取不再交由游戏卡自己的时钟电路,而是交由主机底层系统的时间,系统记录的是真实的时间,而且根据时间变化记录内的时间戳还可以同步刷新(错位后在游戏存档时立刻修改时间戳),从而根本上避免了这一漏洞的继续发生。
当然,这也是《动森》这类游戏的时空穿越者出现问题的原因。虽然是奇怪的知识,但是写出来也挺有意思的。
奇怪的知识增加了!
奇怪的知识增加了!