2016-08-05 15 views
0

나는 기존 게임에 기능을 추가하는 프로젝트를 진행하고 있습니다. 아이디어는 창을 실행하는 옵션을 추가하는 것입니다 (원래 800x600 전체 화면 만 지원함).DirectDraw 출력 변환

지금까지 DirectDraw의 초기화를 수정하여 전체 화면 단독 모드를 제거하고 GDI와 함께 작동하도록 설정하고 클리퍼를 만들고 모든 것이 올바르게 설정된 경우 게임이 전체 화면 모드를 8 비트 색 깊이로 설정하고 창을 실행합니다 이 같은 이미지 출력 쓰레기로 발생합니다

Game output running windowed

지금까지 내가이 문제를 해결하려면 GetDIBits 및 SetDIBits를 사용하여 몇 가지 트릭을하려고 노력하지만 난 어떤 성공도 없었다.

게임은 아주 오래된 directDraw 버전에서 작동합니다 (이 버전에 대한 설명서가 전혀 없으며, 대부분 내 작업은 추측과 테스트를 기반으로합니다).

게임은 BltFast를 사용하여 정보를 화면에 표시합니다. 여기

내가 8 비트 컬러 포맷을 변환 할 수있는 방법 쌍 비트

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에 대한 호출을 화면에 올바르게 출력하도록 변경하여 버퍼에서 직접?

다른 DC로 출력을 다시 라우팅하여 GetDI 비트/SetDIBits를 사용하여 이미지를 수정하는 것이 더 나은 솔루션입니까?

+3

버전 중 하나를 소스 형식은 당신이 될 것으로 기대 또는 목적지가 아닌 것이 아니다. 게임에서 800x600x4 (16 색)를 사용하고 있지 않습니까? 어쨌든, 나는이 잘못된 길로 가고 있다고 생각합니다. 나는 GDI를 전혀 사용하지 않을 것입니다. DirectDraw 윈도우 모드를 사용하여 독점 모드를 에뮬레이트 한 DirectDraw 래퍼를 작성합니다. 실행 파일을 패치하거나 어셈블리를 사용할 필요가 없습니다. 그냥 같은 디렉토리에 자신의 DDRAW.DLL을 덤프.이미 적어도 하나의 프로그램이 있습니다. 누가 이름을 지었고, 이미이 일을 처리합니다. –

+0

나는 DirectDraw에 좀 새로운 것이므로 전체 화면을 기반으로 창 모드를 에뮬레이트하는 방법을 알지 못한다. 또한, 게임은 ddraw의 극단적으로 오래된 버전을 사용합니다. Windows가 일부 호환 버전으로 전환한다고 생각합니다 (게임과 함께 배포 된 ddraw를 사용하는 경우 아무 것도 작동하지 않습니다). –

+0

DirectDraw 7은 여전히 ​​온라인으로 문서화되어 있습니다. https : // msdn.microsoft.com/en-us/library/windows/desktop/gg426124.aspx –

답변

1

많은 연구 끝에 Ross Ridge가 제안한 래퍼가 트릭을 실행하고 OpenGL과 함께 작동하도록하고 또한 많은 멋진 기능을 사용할 수 있으며 첫 번째 일러스트 ddraw

것 같습니다

https://sourceforge.net/p/dxwnd

0

원래 게임은 8 비트이므로 팔레트를 사용합니다. GetDIBits는 8 비트 픽셀 값을 bitmapHeader로 요청한 32 비트 값으로 변환하기 위해 DC와 관련된 현재 팔레트를 사용합니다.

게임의 DC에 팔레트가 선택되어 실현되지 않았기 때문에 이것이 문제의 첫 번째 부분이라고 생각합니다. 독점 모드에서 DirectDraw를 사용하고 있었기 때문에 팔레트를 비디오 카드에 직접 설정하고 있었고 GDI는 그 팔레트의 개념을 전혀 알지 못했습니다.

이 문제를 해결하려면 팔레트를 설정하고 수정 한 코드를 찾아서 GetDI 비트를 수행하기 전에 해당 팔레트를 게임의 DC로 명시 적으로 선택하고 실현해야합니다.

그런 다음 어떻게하면 픽셀을 창 DC로 가져올 지 명확하지 않습니다. 창과 호환되는 메모리 DC를 만든 다음 SetDIBits를 사용하여 데이터를 가져 오는 것 같지만 메모리 DC에서 실제 창 DC로 블릿 (blit) 한 곳은 표시되지 않습니다.

+0

스크린 샷은 Dibits 접근법을 사용하여 실제 수정없이 실행되는 게임을 보여준다.); 내 생각은 표면에서 직류를 얻은 다음 목적지 창 BitmapInfo를 가져 와서 DIB 형식을 지정하여 최종적으로 데이터를 복사하는 것이 었습니다. 언급 한 접근 방식에 대한 코드 샘플이 있습니까? 게임은 팔레트를 만들고 그것에 접근 할 수 있습니다. –

+0

코드 샘플이 없지만 기본 패턴은 CreatePalette를 호출 한 다음 SelectPalette가있는 DC로 선택하는 것입니다. 전화 번호를 선택한 후에 RealizePalette를 호출해야 할 수도 있지만 DC 유형에 필요한 마지막 단계가 있는지 확실하지 않습니다. –

+1

창에 데이터를 가져 오려면 메모리 DC를 건너 뛰고 SetDIBitsToDevice를 사용하여 픽셀 데이터를 창 DC로 직접 가져올 수 있습니다. –