Cal*_*b C 3 video directx vram windows-8.1
我正在尝试在我的 Windows 8.1 笔记本电脑上运行一个旧游戏(Nascar Heat 2002)。我遇到的问题是游戏在启动前崩溃,并且在日志中报告没有可用的视频内存。这是日志文件:
41.37.114: data directory: C:\Program Files (x86)\Hasbro Interactive\NASCAR Heat\Data\
41.37.115: Config Dir: C:\Program Files (x86)\Hasbro Interactive\NASCAR Heat\
41.37.274: ddraw: created directdraw with aticfx32.dll (AMD Radeon HD 8650G + HD 8600/8700M Dual Graphics)
41.37.274: ddraw: version 0.0.0.0
41.40.904: vid: 0 meg card (reported:0.523438)
41.40.904: vid: using AGP textures (1397), total: 0
41.40.905: unsupported: 0 megs of vram"
Run Code Online (Sandbox Code Playgroud)
据我所知,包含 Windows 8.1 的 DirectDraw 版本与诸如此类的旧游戏不兼容。我曾尝试使用 WineD3D 的库,以及其他 ddraw 包装器/黑客,但无济于事。所以我的问题是:有没有办法在 Windows 或 ddraw 包装器中强制模拟数量的 vram(我的卡确实有视频 ram),以确保该游戏检测到它?我已更新到最新的催化剂驱动程序并拥有 Microsoft DirectX 9.0c 最终用户运行时
我可以闻到视频卡检测程序从这里变坏了。这与 Windows 和\或 DirectDraw 无关(部分确实如此,但与您的想法不同)。这只是一个旧游戏做出了不再有效的假设。这并不罕见。例如 Oni 游戏在现代显卡上崩溃:
此问题已被追溯到特定文本缓冲区的溢出 -
startup.txt文件中列出了 OpenGL 扩展的那个缓冲区。在编写 Oni 时,OpenGL 扩展列表转储要短得多,开发人员不允许更大的转储。现代显卡几乎总是导致这种溢出。
我没有 Nascar Heat 2002,但我下载了NASCAR Heat Demo,它显示了完全相同的问题。所以我打开了我的调试器和反汇编器,花了一个晚上试图找出游戏出了什么问题。
游戏实际上由两个可执行文件组成,通过信号量相互通信:主要的可执行文件(NASCAR Heat Demo.exe在我的例子中)和实际的游戏引擎 ( .\run\race.bin)。显卡检测例程在race.bin. 在游戏启动时,将主要的可执行文件复制race.bin到 Windows TEMP 文件夹heat.bin并从那里运行它。如果您尝试重命名race.bin到race.exe并运行它,它会搜索应该由主可执行文件创建信号量,如果它没有找到显示如下消息:

反汇编并快速查看字符串引用后,我发现了一个打印vid: 0 meg card (reported:0.523438)消息的函数调用。它实际上是显卡内存大小检测程序的一部分,在伪代码中看起来像这样(过于简化):
RawVidMemSize = GetVidMemSizeFromDirectDraw()
// Add 614400 bytes (600Kb - 640x480 mode?) to vidmem size (what for?!)
RawVidMemSize = RawVidMemSize + 614400
if (RawVidMemSize < 2000000)
{
MemSize = 0
}
else
{
if (RawVidMemSize < 4000000)
{
MemSize = 2
}
if (RawVidMemSize < 8000000)
{
MemSize = 4
}
if (RawVidMemSize < 12000000)
{
MemSize = 8
}
if (RawVidMemSize < 16000000)
{
MemSize = 12
}
if (RawVidMemSize < 32000000)
{
MemSize = 16
}
if (RawVidMemSize < 64000000)
{
MemSize = 32
}
if (RawVidMemSize > 64000000)
{
MemSize = 64
}
}
Run Code Online (Sandbox Code Playgroud)
对于感兴趣的人,这里是来自 IDA 的函数的实际控制流和我的评论。全尺寸图像onclick。
现在是时候实际看看这个过程中发生了什么。我使用了一个经典的 break & enter 技巧(用 修补了race.bin入口点的第一条指令int3),启动NASCAR Heat Demo.exe并等待调试器弹出。这就是事情变得清晰的时候。
从返回的显存大小GetVidMemSizeFromDirectDraw()为0xFFFF0000(4294901760 bytes = 4095MB),它是无关与真品(应该是1Gb的我的电脑)。事实证明DirectDraw 不太适合现代显卡\PC 架构
随着物理内存 RAM 和 VRAM 的增长,此 API 也遇到了应对问题,因为它返回大小为字节的 32 位 DWORD 计数。
并且倾向于报告任何感觉:
您的系统具有 1GB 或更大的视频内存,以及 4GB 或更大的系统内存 (RAM)。
您运行 Direct-X 诊断工具,它会报告显示选项卡上的近似总内存量意外低。
您可能还会看到某些游戏或应用程序的问题,不允许您选择最高细节设置。
DXDiag 用于近似系统内存的 API 并非旨在处理此配置中的系统
在具有 1GB 视频内存的系统上,以下值与关联的系统内存一起返回:
?????????????????????????????????????????????????????
? System Memory ? Reported Approximate Total Memory ?
?????????????????????????????????????????????????????
? 4GB ? 3496MB ?
? 6GB ? 454MB ?
? 8GB ? 1259MB ?
?????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
所以在我的情况下,它只是报告几乎适合 32 位整数的值。这就是事情变得糟糕的地方。还记得这条线吗?
?????????????????????????????????????????????????????
? System Memory ? Reported Approximate Total Memory ?
?????????????????????????????????????????????????????
? 4GB ? 3496MB ?
? 6GB ? 454MB ?
? 8GB ? 1259MB ?
?????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
变成这样:
RawVidMemSize = RawVidMemSize + 614400
Run Code Online (Sandbox Code Playgroud)
并且4295516160是54886532 位以上的值可以处理 ( 0xFFFFFFFF = 4294967295)。因此整数溢出,最终结果为548864。所以现在,游戏认为我的 vidmem 大小高达536KB并且拒绝运行。
您可以在此在线 x86 汇编仿真器中自行检查。输入下面的代码,在左上角单击Windows并选中Registers复选框。点击Step按钮,看如何0xFFFF0000在EAX寄存器成为0x00086000具有Carry标志。如果您单击寄存器值,它将在数字的十六进制和十进制表示之间切换。
mov eax, 0xFFFF0000
add eax, 0x96000
Run Code Online (Sandbox Code Playgroud)
DirectDraw 可能永远不会返回超过 32 位整数可以处理1 的值(无论实际内存大小如何,它似乎都被限制了。所以解决这个问题的最简单方法是RawVidMemSize = RawVidMemSize + 614400从代码中删除操作,所以它不会t 触发溢出。在可执行文件中,它看起来像这样:
add eax, 96000h0500600900要删除它,我们需要用NOP指令(十六进制:)替换它90。我已经知道文件偏移量,但它在您的可执行文件中可能有所不同。幸运的是,十六进制字符串0500600900在我的race.bin和可能在你的都是独一无二的。因此,获取十六进制编辑器(我推荐HxD:它是免费的、便携的且易于使用)并打开您的bin文件。
进行十六进制字符串搜索:

一旦找到十六进制字符串

将其替换为 90

保存文件。HxD 将自动创建文件的备份,如果出现问题,您可以恢复。
就我而言,这就足够了,我可以开始游戏了。以下是heat.log补丁的处理方式:
21.33.564:ddraw:使用 aticfx32.dll(AMD Radeon HD 5800 系列)创建 directdraw
21.33.564:ddraw:版本 0.0.0.0
21.34.296:vid:64 meg 卡(报告:4090.93.237
使用:4095.93237)AGP 纹理 (3231),总计:64
21.34.305:vid:三重缓冲开启
如果您的文件偶然包含多次出现的0500600900,请替换第一个,然后尝试开始游戏,如果不起作用,从备份中恢复文件并尝试下一步。不要一次更换所有东西,这不是一个好主意。
也已确认Viper Racing 中存在相同的错误。Viper Racing 使用的游戏引擎版本与 Nascar 略有不同(较旧?),但错误是相同的:它也尝试将614400字节添加到视频内存大小。要搜索的值不同,因为在这种情况下,编译器决定不使用寄存器而只从堆栈访问变量,即:
add [esp+18h+var_14], 96000h8144240400600900| 归档时间: |
|
| 查看次数: |
4935 次 |
| 最近记录: |