植物大战僵尸 · 崩溃问题修复和users.dat格式简介

今天花了一上午的时间,研究了我Steam上正版植物大战僵尸(Plants Vs Zombies)在Win10上启动报错Failed reading file的问题,最后问题被我顺利地解决了……一半 ,正版软件受害者身份坐实了

修复游戏崩溃

在Steam上,这个游戏全名是《Plants vs. Zombies: Game of the Year》,发行日期2009年5月6日,宝开公司非常经典的一款益智游戏。我在很小的时候就玩过了,去年趁打折花了¥5在Steam补了票。在学校一直只有Mac用,没有bug玩的很开心,直到macOS从Mojave升级到了Catalina,万恶的苹果公司停止了对同样万恶的32位程序的支持,就……就玩不了了。

本来以为就算被Mac放弃了,在Windows上总能正常游戏了吧!毕竟出色的向后兼容性一直是win党的骄傲,几十年前的win32程序仍然能在最新的windows上运行等等。然而……

熟悉的旋律响起,一卷绿色的草皮从左向右滚过……🙃弹出了一个警告窗口:Failed reading file,点完确定之后程序直接退出,没有操作余地,没有提供任何解决措施。

failed reading file

在Steam社区已经有数十个帖子在讨论这个问题,说明不止我一个人遇到这种情况。浏览过这些帖子之后发现大家用的都是win10,而且字里行间可以发现大家都用过mac,百度贴吧上更有甚者,说自己一直玩的好好的,上午刚用mac玩完,下午win10的就打不开了。难道说……

植物大战僵尸mac版生成的存档无法被win10版正确打开,所以当mac存档上传至Steam之后……win10版就炸了,无论你重装还是怎么弄,就是打不开。

可能有人要问了,既然这样,我把Steam同步关掉、本地存档删掉之后为什么还是不能用?

C:\ProgramData\Steam\PlantsVsZombies\下有两个文件夹,userdatauserdata_backup,应该分别是存档和备份。但是Steam版的userdata是空的,是不是因为存到Steam去了呢?

Failed reading fail 修复方法

参考资料

这是Steam社区里面一篇比较靠谱的回答,大致操作就是把userdata_backup里的文件复制到userdata里面。游戏启动的时候如果发现userdata里有文件,就会出现这个界面:Choose Saving

我们在Steam Cloud里存了你的存档!但是本地也有一份!你想用哪份呢?

这时候你选择本地存档(第一个按钮),就能用刚刚复制到userdata文件夹的存档替换Steam的存档,崩溃的问题也就随之解决了。

Fatal error 修复方法

当然了,Steam版的植物大战僵尸在Win10上的问题可远不止这一个。有些人打开之后游戏报错:Fatal error!,这怎么解决呢?

首先这个问题跟全屏有关,可以通过设置注册表关掉游戏全屏,游戏即可正常打开。

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\SOFTWARE\PopCap\PlantsVsZombies]
"ScreenMode"=dword:00000000

[HKEY_CURRENT_USER\SOFTWARE\SteamPopCap\PlantsVsZombies]
"ScreenMode"=dword:00000000

这个问题虽然与全屏有关,但是并不是说真的不能全屏游戏。这个问题其实可以通过切换至英文输入法完美解决。在设置→时间和语言→语言,添加English,然后按Win + 空格切换到英文输入法(注意不是拼音输入法的英文模式,是英文输入法,任务栏显示"ENG"而不是"英”)。这时候打开游戏全屏就不会Fatal error了。

存档文件格式

前面已经提到存档储存在C:\ProgramData\Steam\PlantsVsZombies\目录下的userdatauserdata_backup里。(Mac版的在~/Library/Application Supoort/PopCap/PlantsVsZombiesMac/),看一下都有哪些文件:

userdata_backup
├── game1_0.dat
├── game2_0.dat
├── game2_1.dat
├── game2_23.dat
├── game2_4.dat
├── game2_60.dat
├── game2_70.dat
├── user1.dat
├── user2.dat
└── users.dat

其中users.dat储存了所有用户的列表,包括他们的用户名和用户ID,根据用户ID可以找到对应的用户数据,比如1号用户对应的就是user1.dat文件。
每个用户的userN.dat则储存了玩家的详细信息,包括游戏进度、金币、商店等等。
每个gameN_M.dat则负责储存N号玩家在场景M的进度,M的值代表白天、黑夜、泳池等等。

用户列表users.dat文件

$ hexdump -C users.dat
00000000  0e 00 00 00 02 00 05 00  54 61 6c 65 74 03 00 00  |........Talet...|
00000010  00 02 00 00 00 04 00 54  6e 7a 65 02 00 00 00 01  |.......Tnze.....|
00000020  00 00 00                                          |...|
00000023

所有数据都是小端序的。其中前4个字节固定为0e 00 00 00,其后两个字节为用户总数,我这里有2个用户,所以是02 00

每个用户数据由用户名、一个未知的int32以及用户ID三个部分组成。以05 00 54 61 6c 65 74 03 00 00 00 02 00 00 00为例,
最前面的05 00为用户名长度(此处为5),接下来5个字节代表用户名54 61 6c 65 74 (Talet)
紧接着四个字节03 00 00 00据网上说并无查明用处,也不用管。
再之后02 00 00 00为用户ID(此处为2),表示这个用户的数据储存在user2.dat这个文件中。

紧跟着是第二个用户,格式同上,读出来是{Tnze, 2, 1}。

这就是users.dat文件的格式,非常简单。