我正在开发一个为旧游戏添加功能的项目;这个想法是添加选项以窗口化运行(最初它只支持 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
有什么方法可以通过更改对 BltFast 的调用以正确输出到屏幕来直接从缓冲区转换 8 位颜色格式?
将输出重新路由到另一个 DC 然后使用 GetDIBits/SetDIBits 修复图像是否是更好的解决方案?