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
是548865
32 位以上的值可以处理 ( 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, 96000h
0500600900
要删除它,我们需要用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], 96000h
8144240400600900
归档时间: |
|
查看次数: |
4935 次 |
最近记录: |