We're maintaining an old video game that uses a full-screen 256-color graphics mode with DirectDraw. The problem is, some applications running in the background sometimes try to change the system palette while the game is running, which results in corrupted graphics.
我们正在维护一个使用DirectDraw的全屏256色图形模式的旧视频游戏。问题是,在后台运行的某些应用程序有时会在游戏运行时尝试更改系统调色板,这会导致图形损坏。
We can (sometimes) detect when this happens by processing the WM_PALETTECHANGED message. A few update versions ago we added logging (just log the window title/class/process name), which helped users identify offending applications and close them. MSN Live Messenger was a common culprit.
我们可以(有时)通过处理WM_PALETTECHANGED消息来检测何时发生这种情况。在几个更新版本之前,我们添加了日志记录(只记录窗口标题/类/进程名称),这有助于用户识别有问题的应用程序并关闭它们。 MSN Live Messenger是一个常见的罪魁祸首。
The problem got worse when we found out that Windows Vista (and 7) does it "by itself". The WM_PALETTECHANGED parameters point towards CSRSS and the desktop window. In Vista, a workaround that often worked was to open any folder (Computer, Documents, etc.) and leave it open while running the game. Sounds ridiculous, but it worked - in most cases. In Windows 7, not even this workaround worked any more. Users found that stopping some services (Windows Update and the indexing service) also resolved the problem on some configurations.
当我们发现Windows Vista(和7)“单独”完成它时,问题变得更糟。 WM_PALETTECHANGED参数指向CSRSS和桌面窗口。在Vista中,经常使用的解决方法是打开任何文件夹(计算机,文档等)并在运行游戏时保持打开状态。听起来很荒谬,但在大多数情况下都有效。在Windows 7中,甚至这种解决方法都不再适用。用户发现停止某些服务(Windows Update和索引服务)也解决了某些配置上的问题。
Some time ago I just started trying random things in hope of finding a solution. I found that setting the GDI palette (using Create/SelectPalette) before setting the DirectDraw palette (using IDirectDrawPalette::SetEntries) would restore the palette after it became corrupted (WM_PALETTECHANGED handler). SetSystemPaletteUse and calling SetPalette on the primary surface helped some more. However, there is still perceivable flickering when an application tries to steal the palette, which is especially prominent during fades.
前段时间我刚开始尝试随机的东西,希望能找到解决方案。我发现在设置DirectDraw调色板(使用IDirectDrawPalette :: SetEntries)之前设置GDI调色板(使用Create / SelectPalette)会在调色板损坏后恢复调色板(WM_PALETTECHANGED处理程序)。 SetSystemPaletteUse并在主表面上调用SetPalette帮助了更多。然而,当应用程序试图窃取调色板时,仍然可以感觉到闪烁,这在渐变期间尤其突出。
Question: is there a way to get a "real" exclusive palette, which completely disallows other applications changing the Windows palette as long as our game retains focus?
问题:有没有办法获得一个“真正的”独家调色板,只要我们的游戏保持关注,完全不允许其他应用程序更改Windows调色板?
5 个解决方案
#1
Someone actually found a registry entry fix for this, here:
实际上有人为此找到了一个注册表项修复,在这里:
Look for "scrambled colours" on that page and you'll get to the part with the fix you need.
在该页面上查找“乱序颜色”,您将获得所需的修复部分。
Since online resources are fleeting, though, here's the full explanation:
但是,由于在线资源稍纵即逝,以下是完整的解释:
Make a new key under "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\Compatibility\" for the program.
为程序在“HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ DirectDraw \ Compatibility \”下创建一个新密钥。
If the program you're applying the compatibility for is a 32-bit program, and you're on a 64-bit system (either applying it manually or through a 64-bit program), don't forget to add the "Wow6432Node" between "Software" and "DirectDraw" to compensate for that.
如果您正在应用兼容性的程序是32位程序,并且您使用的是64位系统(手动或通过64位程序应用它),请不要忘记添加“Wow6432Node” “软件”和“DirectDraw”之间用来弥补这一点。
In that key, set these values:
在该键中,设置以下值:
- "Flags" (REG_BINARY) : [00,08,00,00]
- "Name" (REG_SW) : File name of your program. No path, just the executable file name.
- "ID" (REG_BINARY) : DirectDraw ID of the application.
“旗帜”(REG_BINARY):[00,08,00,00]
“名称”(REG_SW):程序的文件名。没有路径,只有可执行文件名。
“ID”(REG_BINARY):应用程序的DirectDraw ID。
To get the required DirectDraw ID, run the program and then check this registry key:
要获取所需的DirectDraw ID,请运行该程序,然后检查以下注册表项:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\MostRecentApplication
Again, if you're on a 64 bit system and the program you're doing this for is a 32-bit one, add the "Wow6432Node" after "Software".
同样,如果您使用的是64位系统,并且您正在执行此操作的程序是32位系统,请在“软件”之后添加“Wow6432Node”。
The ID in that key is four bytes. Reverse their order to get the bytes to put in the ID value. 32dd83d5 becomes d5,83,dd,32.
该密钥中的ID是四个字节。反转它们的顺序以获取要放入ID值的字节。 32dd83d5变为d5,83,dd,32。
#2
What you can do is a 'simple' workaround. Since your game is an old game it is probably no match to current hardware, which is why this trick will work:
您可以做的是一个“简单”的解决方法。由于您的游戏是旧游戏,它可能与当前硬件不匹配,这就是为什么这个技巧将起作用:
- Blit everything to an offscreen buffer (memory)
- convert the 8bit buffer to 16 bit(or 32 bit) using the current palette (so also done in memory)
- copy the contents of the 16 bit(or 32bit) buffer to the backbuffer of the screen
- flip the screenbuffer.
将所有内容都显示到屏幕外缓冲区(内存)
使用当前调色板将8位缓冲区转换为16位(或32位)(因此也在内存中完成)
将16位(或32位)缓冲区的内容复制到屏幕的后备缓冲区
翻转屏幕缓冲区。
This will require minimal changes to your game, and will get rid of palette issues completely, though your game can still use all it's palette trickery
这将需要对您的游戏进行微小的更改,并且完全摆脱调色板问题,尽管您的游戏仍然可以使用它的所有调色板技巧
R
#3
Apparently "an application should not call SetSystemPaletteUse, unless it has a maximized window and the input focus". Perhaps some other program is misbehaving. That description makes it sound very much like Microsoft hope all programs will cooperate and offer no way to compel them to do so. It's like being back on Windows 3.1. :)
显然“应用程序不应该调用SetSystemPaletteUse,除非它具有最大化窗口和输入焦点”。也许其他一些程序行为不端。这种描述听起来非常像微软希望所有程序都能合作,并没有办法强迫他们这样做。就像回到Windows 3.1一样。 :)
Random suggestion: have you tried SetSystemPaletteUse with the SYSPAL_NOSTATIC256 parameter?
随机建议:您是否尝试过使用SYSPAL_NOSTATIC256参数设置SetSystemPaletteUse?
You could also see if your palette contains the 20 Windows reserved colours; if so, it means that any other palettised program that just uses Windows colours will not need to change the palette in order to render itself, as I understand it.
您还可以看到您的调色板是否包含20种Windows保留颜色;如果是这样,这意味着任何其他只使用Windows颜色的palettised程序将不需要更改调色板以呈现自己,正如我所理解的那样。
#4
I don't know DirectX at all, but I'd suggest trying to do your rendering off-screen then converting to the display depth... I imagine you can get Direct2D to do all that for you...
我根本不知道DirectX,但我建议尝试在屏幕外渲染然后转换到显示深度...我想你可以让Direct2D为你做所有这些......
#5
All you have to do is set your PC to 16 bit
colours in Control Panel and the game comes right, works on Original Command and Conquer
for me :D
所有你需要做的就是在控制面板中将你的电脑设置为16位颜色,游戏正确,适用于我的原始命令和征服:D
#1
Someone actually found a registry entry fix for this, here:
实际上有人为此找到了一个注册表项修复,在这里:
Look for "scrambled colours" on that page and you'll get to the part with the fix you need.
在该页面上查找“乱序颜色”,您将获得所需的修复部分。
Since online resources are fleeting, though, here's the full explanation:
但是,由于在线资源稍纵即逝,以下是完整的解释:
Make a new key under "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\Compatibility\" for the program.
为程序在“HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ DirectDraw \ Compatibility \”下创建一个新密钥。
If the program you're applying the compatibility for is a 32-bit program, and you're on a 64-bit system (either applying it manually or through a 64-bit program), don't forget to add the "Wow6432Node" between "Software" and "DirectDraw" to compensate for that.
如果您正在应用兼容性的程序是32位程序,并且您使用的是64位系统(手动或通过64位程序应用它),请不要忘记添加“Wow6432Node” “软件”和“DirectDraw”之间用来弥补这一点。
In that key, set these values:
在该键中,设置以下值:
- "Flags" (REG_BINARY) : [00,08,00,00]
- "Name" (REG_SW) : File name of your program. No path, just the executable file name.
- "ID" (REG_BINARY) : DirectDraw ID of the application.
“旗帜”(REG_BINARY):[00,08,00,00]
“名称”(REG_SW):程序的文件名。没有路径,只有可执行文件名。
“ID”(REG_BINARY):应用程序的DirectDraw ID。
To get the required DirectDraw ID, run the program and then check this registry key:
要获取所需的DirectDraw ID,请运行该程序,然后检查以下注册表项:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\MostRecentApplication
Again, if you're on a 64 bit system and the program you're doing this for is a 32-bit one, add the "Wow6432Node" after "Software".
同样,如果您使用的是64位系统,并且您正在执行此操作的程序是32位系统,请在“软件”之后添加“Wow6432Node”。
The ID in that key is four bytes. Reverse their order to get the bytes to put in the ID value. 32dd83d5 becomes d5,83,dd,32.
该密钥中的ID是四个字节。反转它们的顺序以获取要放入ID值的字节。 32dd83d5变为d5,83,dd,32。
#2
What you can do is a 'simple' workaround. Since your game is an old game it is probably no match to current hardware, which is why this trick will work:
您可以做的是一个“简单”的解决方法。由于您的游戏是旧游戏,它可能与当前硬件不匹配,这就是为什么这个技巧将起作用:
- Blit everything to an offscreen buffer (memory)
- convert the 8bit buffer to 16 bit(or 32 bit) using the current palette (so also done in memory)
- copy the contents of the 16 bit(or 32bit) buffer to the backbuffer of the screen
- flip the screenbuffer.
将所有内容都显示到屏幕外缓冲区(内存)
使用当前调色板将8位缓冲区转换为16位(或32位)(因此也在内存中完成)
将16位(或32位)缓冲区的内容复制到屏幕的后备缓冲区
翻转屏幕缓冲区。
This will require minimal changes to your game, and will get rid of palette issues completely, though your game can still use all it's palette trickery
这将需要对您的游戏进行微小的更改,并且完全摆脱调色板问题,尽管您的游戏仍然可以使用它的所有调色板技巧
R
#3
Apparently "an application should not call SetSystemPaletteUse, unless it has a maximized window and the input focus". Perhaps some other program is misbehaving. That description makes it sound very much like Microsoft hope all programs will cooperate and offer no way to compel them to do so. It's like being back on Windows 3.1. :)
显然“应用程序不应该调用SetSystemPaletteUse,除非它具有最大化窗口和输入焦点”。也许其他一些程序行为不端。这种描述听起来非常像微软希望所有程序都能合作,并没有办法强迫他们这样做。就像回到Windows 3.1一样。 :)
Random suggestion: have you tried SetSystemPaletteUse with the SYSPAL_NOSTATIC256 parameter?
随机建议:您是否尝试过使用SYSPAL_NOSTATIC256参数设置SetSystemPaletteUse?
You could also see if your palette contains the 20 Windows reserved colours; if so, it means that any other palettised program that just uses Windows colours will not need to change the palette in order to render itself, as I understand it.
您还可以看到您的调色板是否包含20种Windows保留颜色;如果是这样,这意味着任何其他只使用Windows颜色的palettised程序将不需要更改调色板以呈现自己,正如我所理解的那样。
#4
I don't know DirectX at all, but I'd suggest trying to do your rendering off-screen then converting to the display depth... I imagine you can get Direct2D to do all that for you...
我根本不知道DirectX,但我建议尝试在屏幕外渲染然后转换到显示深度...我想你可以让Direct2D为你做所有这些......
#5
All you have to do is set your PC to 16 bit
colours in Control Panel and the game comes right, works on Original Command and Conquer
for me :D
所有你需要做的就是在控制面板中将你的电脑设置为16位颜色,游戏正确,适用于我的原始命令和征服:D