解决帝国时代2在Win7下颜色不正确的问题

帝国时代2在Windows7下面运行的时候,会出现颜色不正确的问题:草地本来应该是绿的,但是它却充满了斑斑点点的红色,看起来十分恶心,不过除了颜色以外倒是也没有其他太大的问题。

对于一个游戏来说,看起来很难受是十分致命的。你看有多少游戏界面要搞得很华丽……网上搜索以后,各种解决方法好几种,但是分析一下,大多是让你很难受的那种解决方法:

  1. 结束explorer.exe进程然后再进入游戏。问题确实能解决,不过……难受不?
  2. 系统主题更换成Windows经典。比刚才那个不难受一点。但是说真的挺讨厌的……切换来切换去
  3. 有人写了一个工具,检测到游戏运行就把explorer.exe csrss.exe这类进程给suspend掉。比起结束进程要“温柔”一些,不过游戏过程中alt+tab切换出来,就知道有多难受了。
  4. 找了半天这个最靠谱:http://blog.macuyiko.com/2009/07/solving-color-problem-red-grass-purple.html

为了防止那个博客什么时候就开不开了,我还是把重要内容复制出来……

(9 - reliable) Thanks to this comment I found out that Windows 7 actually provides a compatibility hack build in to allow running old DirectDraw games in all their glorious colors. The HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\Compatibility\ registry entry (or HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DirectDraw\Compatibility\ for 64bit Windows) contains entries for some popular games, such as Age Of Empires and Starcraft.

 

Take a look at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\MostRecentApplication to find out the correct application ID and edit the registry entry manually accordingly.

 

Technical explanation

If you're interested in a little background on why this problem is happening, read on.
When I first encountered this problem, I already knew a little about DirectX, the GDI and the Windows API. Basically, back in the day, DirectX (which handles a lot of the graphics and multimedia workload in games and other program) included a component called Directdraw, used for rendering 2D graphics.
PCs back then weren't really powerful. Everything had to be as fast as possible, even color handling. So something which Directdraw did for you was maintaining a palette of 256 colors. Like a painter, programmers could fill this palette with 256 colors they would use: ten greens for grass, 6 blues for water, and so on. Some of these 256 colors are static (but then again, not always) and cannot be changed. If you're interested in the deep and dirty details: this page does a good job explaining it.
Now this is the thing: if you're a fullscreen game, you don't want other programs screwing up the system palette, changing your beautiful chosen colors to ugly greens and reds. And this is what's happening in Windows 7. If you read System Palette and Static Colors on MSDN, it states that "However, because changing the static colors can have an immediate and dramatic effect on all windows on the display, an application should not call SetSystemPaletteUse, unless it has a maximized window and the input focus." Alas, this is not enforced by Windows, and thus explorer.exe (which comes from Microsoft mind you) and other programs will happily call SetSystemPaletteUse and mess the poor fullscreen DirectDraw game up.
I googled a bit around to see if I could find any clues. This message at Stackoverflow describes the same problem. This message is actually posted by the maintainers of Worms: Armageddon. No-one provided an answer though. I opened up Visual Studio (which was still installed) to quickly throw something together in VB.NET to intercept the WM_SYSCOLORCHANGE, WM_PALETTECHANGED, WM_PALETTEISCHANGING and WM_QUERYNEWPALETTE messages and look at where they're coming from. Basically, three processes are fighting:

CHANGING from (0)  CHANGED from Age of Empires II Expansion (135458)  Device context: 16847861  Process: 4508: age2_x1  Got 256 palette size scr  [...]  CHANGED from GDI+ Window (917744)  Device context: 184626156  Process: 2452: explorer  Got 256 palette size scr  CHANGED from (65552)  Device context: 1744905863  Process: 540: csrss  Got 256 palette size scr  [...]

 

The game itself, explorer.exe, and csrss.exe.

好,我就用这个最靠谱的。靠谱是靠谱,对我来说操作也不会有太大问题,但是其他人呢?游戏很多人都会玩,改注册表就不是每个人都会改了。于是我写个工具来自动改注册表。

闲着没事想试一下wpf,结果这工具的界面就用wpf来写了。关于注册表里面的那些个flags值,其实我不知道它是什么,不过既然人家用00080000可以正常那我也用00080000就是了。

使用方法很简单,首先启动一下有问题的游戏(帝国2),然后退出游戏,打开这个工具,会发现最近运行的DirectDraw程序是刚刚开的那个游戏。OK,点Add按钮添加到下面那个列表。问题解决,再启动帝国2,进入游戏,草地的颜色正常了。

注意:游戏和这个工具都要用管理员身份运行。如果不以管理员身份运行,因为权限不足,可能无法正确更新注册表键值,最终造成无法读取最近启动的DirectDraw程序和无法写入修正键值。

最后:为什么是英文的?我在想会不会什么时候有国际友人会需要这东西呢(殴

点击 下载

内有程序和源代码,32位系统用的,64位系统对应的代码虽然有写但是是未经测试的……我没有环境。

memo:那个ID其实是EXE的PE头里面的timestamp(from riatre)

更新:
因为既然知道了那个ID是什么,所以我就又写了个程序,
这次可以不用先运行一次程序,而是可以直接添加程序了
也改用C++来写,C++和ATL,所以生成的EXE体积很小。

点击下载:directDrawFix

发表评论