【发布时间】:2016-08-09 22:20:52
【问题描述】:
我正在做一个项目,为旧游戏添加功能;这个想法是添加选项以窗口化运行它(最初它只支持 800x600 全屏)。
到目前为止,我修改了 directDraw 的初始化以删除全屏独占模式并使其能够与 GDI 一起使用,创建了一个剪辑器并正确设置了所有内容,关键是,游戏将全屏模式设置为 8 位色深,运行它窗口导致它会像这样输出垃圾:
到目前为止,我尝试使用 GetDIBits 和 SetDIBits 做一些技巧来解决问题,但没有成功。
该游戏使用非常旧的 directDraw 版本(根本没有关于此版本的文档,我的大部分工作都是基于猜测和测试)。
游戏使用 BltFast 将信息显示到屏幕上。
这是一段为尝试使用 DIBits 解决问题而编写的代码
PrimarySurface = 游戏主表面本身
patch_1:
; Blt interface
CALL DWORD [EDX+1Ch] ;<--- Surface->BltFast() Outputs game screen, params pushed to stack elsewhere
pushad
; Get diBits and transform it properly to display
push surfaceDC
mov eax, [PrimarySurface]
mov edx, [eax]
push eax
call dword [edx+44h] ; Surface->GetDC(&surfaceDC)
test eax, eax
je patch_1_abort
invoke FindWindowA, 0, 'Rising Lands'
mov [windowHandle], eax
invoke GetDC, eax
mov [windowDC], eax
invoke CreateCompatibleDC, [surfaceDC]
mov [compatibleDC], eax
invoke CreateCompatibleDC, [windowDC]
mov [compatibleWindowDC], eax
invoke CreateCompatibleBitmap, [windowDC], 800, 600
mov [zbitmap], eax
; Get screen header
invoke GetDIBits, [compatibleWindowDC], [zbitmap], 0, 0, 0, bitmapHeader, 0
; Get game screen data
invoke GetDIBits, [compatibleDC], [zbitmap], 0, 600, bbuffer, bitmapHeader, 0
; Copy content back to screen
invoke SetDIBits, [compatibleWindowDC], [zbitmap], 0, 600, bbuffer, bitmapHeader, 0
; Release
push [surfaceDC]
mov eax, [PrimarySurface]
mov edx, [eax]
push eax
call dword [edx+68h]
patch_1_abort:
popad
; Original code finalization
MOV EDX,EAX
TEST EAX, EAX
jmp [p1r]
surfaceDC dd 0
windowHandle dd 0
windowDC dd 0
compatibleDC dd 0
compatibleWindowDC dd 0
zbitmap dd 0
bitmapInfo dd bitmapHeader
dd 0
bitmapHeader:
hSize dd endHeader - bitmapHeader
hWidth dd 0;800
hHeight dd 0;600
hPlanes dw 0;1
hBitCount dw 0;32
hCompression dd 0
hSizeImage dd 0
hxPPm dd 0
hyPPm dd 0
hClrUsed dd 0
hClrImp dd 0
endHeader:
bbuffer rb 800*600*10
有什么方法可以直接从缓冲区转换 8 位颜色格式,方法是更改对 BltFast 的调用以正确输出到屏幕?
将输出重新路由到另一个 DC,然后使用 GetDIBits/SetDIBits 修复图像是更好的解决方案吗?
【问题讨论】:
-
看起来您的源格式不是您期望的格式,或者您的目标格式不是。你确定游戏没有使用 800x600x4(16 色)吗?无论如何,我认为你的做法是错误的,我根本不会使用 GDI。我只是编写一个 DirectDraw 包装器,它使用 DirectDraw 窗口模式模拟独占模式。无需修补可执行文件或使用程序集。只需将您自己的 DDRAW.DLL 转储到同一目录中即可。至少已经有一个程序,我不知道他的名字,它已经做到了。
-
我是 DirectDraw 的新手,所以我真的不知道如何基于全屏模拟窗口模式,您对此有什么参考吗?另外,游戏使用了一个非常旧的ddraw版本,我猜windows会切换到一些兼容版本(如果你使用游戏分发的ddraw,什么都不会起作用)
-
DirectDraw 7 仍然在线记录:msdn.microsoft.com/en-us/library/windows/desktop/gg426124.aspx
-
我找到了“DirectDraw hack”,这似乎是您提到的修复方法;它不适用于我正在使用的游戏,但我会尝试使其适应我的情况。不过,我想将 8 位图像转换为 32 位应该更容易,我只是不知道到目前为止如何正确地得到这个
标签: windows assembly gdi directdraw