我正在开发一个项目来为旧游戏添加功能;我们的想法是添加运行窗口的选项(原来它只支持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来修复图像是否是更好的解决方案?
答案 0 :(得分:1)
经过大量的研究,我发现了一个包装器(正如Ross Ridge所建议的那样)可以解决这个问题并强制游戏与openGL协同工作,并且还可以实现许多简洁的功能,并且即使与第一个版本兼容也是如此ddraw
答案 1 :(得分:0)
原始游戏是8位,所以它依赖于调色板。 GetDIBits将使用与其DC相关联的当前调色板,以便将8位像素值转换为您使用bitmapHeader请求的32位值。
我认为这是问题的第一部分,因为游戏的DC可能没有选择和实现调色板。由于它是在独占模式下使用DirectDraw,它可能直接在视频卡中设置调色板,而GDI没有关于调色板是什么的概念。
要解决这个问题,我认为您需要找到设置和修改调色板的代码,然后在执行GetDIBits之前明确选择并在游戏的DC中实现该调色板。
之后,我不清楚你是如何将像素带到窗口DC的。你似乎创建了一个与窗口兼容的内存DC,然后使用SetDIBits来获取数据,但是我没有看到你从内存DC到实际窗口DC的位置。