如何使较新的Unity游戏向后兼容OS X 10.9“ Mavericks”?

2021-03-01 13:02:01

崩溃日志表明游戏正在寻找一个名为getattrlistbulk的函数。由于小牛不具备此功能,因此游戏不知道该怎么办,然后崩溃。因此,为了使游戏能够运行,我们必须给它想要的东西-getattrlistbulk函数的副本。

(换句话说,我们需要编写一些代码。请确保您已安装Apple的Xcode命令行工具!)

getattrlistbulk是内核的一部分,这意味着我绝对不了解它的作用。但是,如果我不必—如果Unity游戏实际上不需要getattrlistbulk来处理任何重要的事情,并且/或者需要一个备用代码路径来处理意外的值怎么办?如果真是这样,可能是getattrlistbulk不需要为运行游戏实际做任何事情,它只需要存在即可。

#include< sys / attr.h> int getattrlistbulk(int dirfd,结构attrlist * attrList,void * attrBuf,size_t attrBufSize,uint64_t选项){返回0;}

现在,我们需要使游戏加载该库,使用DYLD_INSERT_LIBRARIES环境变量应该很容易做到。在终端中运行:

Dyld错误消息:找不到符号:_getattrlistbulk引用自:/ Users / USER / Desktop / Sayonara Wild Hearts.app/Contents/MacOS/../Frameworks/UnityPlayer.dylib预期在:/usr/lib/libSystem.B.dylib

让我们再次查看崩溃报告。 UnityPlayer并不希望getattrlistbulk随处可见,它希望它位于/usr/lib/libSystem.B.dylib中,因此也不希望查看UnityFixer库的内部。这是由于一个称为两层名称空间的概念,您可以并且应该在此处了解更多信息。而且,尽管可以通过DYLD_FORCE_FLAT_NAMESPACE = 1来关闭两级命名空间,但没有它,Unity游戏将无法工作。

让我们尝试其他事情。如果我们让游戏代替libSystem.B.dylib加载我们的库UnityFixer.dylib,该怎么办? Apple的install_name_tool命令使此操作变得简单!将UnityFixer.dylib复制到应用程序包的Contents / Frameworks目录中,然后运行:

特定于应用程序的信息:dyld:启动,正在加载依赖的库Dyld错误消息:找不到符号:dyld_stub_binder引用自:/ Users / USER / Desktop / Sayonara Wild Hearts.app/Contents/MacOS/Sayonara Wild Hearts预期存在于:/ Users / USER / / Users / USER / Desktop / Sayonara Wild Hearts.app/Contents/MacOS/Sayonara Wild Hearts中的桌面/ Sayonara Wild Hearts.app/Contents/MacOS/../Frameworks/UnityFixer.dylib

嘿,至少这次崩溃日志已更改!您可能已经猜出了为什么这没用。 libSystem.B.dylib本质上在Mac上等同于Linux的libc,因此,它包含许多功能。 UnityFixer仅包含getattrlistbulk。因此,尽管该游戏现在可以访问getattrlistbulk,但它却缺少了其他所有内容!

我们想要的是UnityFixer库除了提供自己的库以外,还提供所有其他libSystem函数-也就是说,我们应该使libSystem.B.dylib成为UnityFixer.dylib的子库。

(在编译时可能有一种更干净的链接方式,但是我无法弄清楚它是如何工作的,而optool的工作原理。)

答:是的。我最初尝试1,但是这导致一些游戏分配所有可用内存,并且一旦没有剩下的就崩溃了。

答:不。据我所知,它将允许任何Unity 2018/2019游戏启动,但没有人说任何有关正常工作的信息!游戏非常复杂,显然这些游戏以前从未在Mavericks上进行过测试,因此它们可能还会出现其他故障。 Timelie是游戏的一个示例,该游戏在技术上可以解决此问题,但是存在非常严重的图形问题。

A:也许吧? Internet™说getattrlistbulk是getdirentriesattr的替代品。 因此,我曾尝试过: #include< sys / attr.h> #include< unistd.h> int getattrlistbulk(int dirfd,struct attrlist * attrList,void * attrBuf,size_t attrBufSize,uint64_t选项) unsigned int basep; unsigned int newState; 返回getdirentriesattr(dirfd,& attrList,& attrBuf,attrBufSize,& count,& basep,& newState,options);} 这是通过对开发人员文档中的getattrlistbulk和getdirentriesattr的示例代码进行模式匹配来编写的。 它确实可以正常工作(在游戏运行时),但是返回0也是如此,所以我真的没有办法测试代码。 在这种情况下,返回0似乎更安全。