2016-08-05 39 views
0

Ich arbeite an einem Projekt, um Funktionalität zu einem alten Spiel hinzuzufügen; Die Idee ist, die Option hinzuzufügen, um es windowed zu starten (ursprünglich unterstützt es nur Vollbild 800x600).DirectDraw Ausgabe Anpassung

Bisher habe ich die DirectDraw-Initialisierung geändert, um den exklusiven Vollbildmodus zu entfernen und mit GDI zu arbeiten, einen Clipper erstellt und alles richtig gesetzt, ist der Punkt, das Spiel setzt den Vollbildmodus auf 8bit Farbtiefe, läuft es gefenstert zur Ausgabe von Müll verursacht es wie dieses Bild:

Game output running windowed

i, um das Problem zu arbeiten, einige Tricks GetDIBits und SetDIBits zu tun mit, aber ich hatte keinen Erfolg Bisher versuchen.

Das Spiel funktioniert mit einer sehr alten DirectDraw-Version (es gibt keine Dokumentation über diese Version, der Großteil meiner Arbeit basiert auf Vermutungen und Tests).

Das Spiel verwendet BltFast, um Informationen auf den Bildschirm zu bekommen.

Hier ist ein Stück des Codes, der das Problem mit Di-Bits

PrimarySurface = Spiel primäre Oberfläche selbst

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 

Gibt es eine Weise, die ich umwandeln kann das 8-Bit-Farbformat zu beheben wurde geschrieben, um zu versuchen, direkt aus dem Puffer, indem Sie den Aufruf von BltFast ändern, um korrekt auf den Bildschirm auszugeben?

Ist es eine bessere Lösung, die Ausgabe zu einem anderen DC umzuleiten, um dann GetDIBits/SetDIBits zu verwenden, um das Bild zu reparieren?

+3

entweder Format ist Ihre Quelle sieht nicht, was Sie es sein oder Ihr Ziel erwarten nicht. Bist du sicher, dass das Spiel nicht 800x600x4 (16 Farben) verwendet? Auf jeden Fall glaube ich, dass du diesen falschen Weg eingeschlagen hast, ich würde GDI überhaupt nicht benutzen. Ich würde nur einen DirectDraw-Wrapper schreiben, der den exklusiven Modus im DirectDraw-Fenstermodus emuliert. Keine Notwendigkeit, die ausführbare Datei zu patchen oder Assembly zu verwenden. Werfen Sie einfach Ihre eigene DDRAW.DLL im selben Verzeichnis auf.Es gibt schon mindestens ein Programm, dessen Name mir entgeht, das tut das schon. –

+0

Ich bin irgendwie neu zu DirectDraw, also habe ich wirklich keine Idee, wie ich Fenstermodus auf dem Vollbild emulieren würde, haben Sie irgendwelche Hinweise darauf? Außerdem verwendet das Spiel eine extrem alte Version von ddraw, die Windows auf eine Kompatibilitätsversion von Windows umschaltet (wenn du dd draw benutzt, wird nichts funktionieren) –

+0

DirectDraw 7 ist noch online dokumentiert: https: // msdn.microsoft.com/en-us/library/windows/desktop/gg426124.aspx –

Antwort

1

Nach vielen Recherchen fand ich einen Wrapper (wie von Ross Ridge vorgeschlagen), der den Trick macht und das Spiel mit openGL arbeiten lässt und auch viele nette Features ermöglicht und sogar mit dem ersten kompatibel ist Versionen von ddraw

https://sourceforge.net/p/dxwnd

0

Das ursprüngliche Spiel ist 8-Bit, so dass es auf einer Palette beruht. GetDIBits verwendet die aktuelle Palette, die seinem DC zugeordnet ist, um die 8-Bit-Pixelwerte in die 32-Bit-Werte zu konvertieren, die Sie mit dem BitmapHeader anfordern.

Ich denke, das ist der erste Teil des Problems, da die DC des Spiels wahrscheinlich nicht die Palette ausgewählt und realisiert hat. Da DirectDraw im exklusiven Modus verwendet wurde, wurde die Palette wahrscheinlich direkt in der Grafikkarte festgelegt, und GDI hatte keine Ahnung, was diese Palette war.

Um dies zu lösen, müssen Sie nach dem Code suchen, der die Palette erstellt und ändert, und diese Palette dann explizit im DC des Spiels auswählen und realisieren, bevor Sie die GetDIBits ausführen.

Danach ist mir unklar, wie Sie die Pixel zum Fenster DC bekommen. Sie scheinen einen Speicher-DC zu erstellen, der mit dem Fenster kompatibel ist, und verwenden dann SetDIBits, um die Daten dorthin zu bekommen, aber ich sehe nicht, wo Sie dann vom Speicher-DC zum tatsächlichen Fenster DC blit.

+0

Der Screenshot zeigt das Spiel ohne den eigentlichen Fix mit dem Dibits-Ansatz (wie gesagt, es hat nicht wirklich funktioniert)); Meine Idee war, den DC von der Oberfläche zu bekommen, dann das Zielfenster BitmapInfo zu bekommen, um das DIB-Format zu spezifizieren, um schließlich Daten zu kopieren. Hätten Sie ein Codebeispiel über den von Ihnen erwähnten Ansatz? Das Spiel erstellt eine Palette und ich habe Zugriff darauf. –

+0

Ich habe kein Codebeispiel, aber das Grundmuster besteht darin, CreatePalette aufzurufen und dann mit SelectPalette in den DC auszuwählen. Nachdem Sie es ausgewählt haben, müssen Sie möglicherweise RealizePalette aufrufen, aber ich bin mir nicht sicher, ob dieser letzte Schritt für den DC-Typ, den Sie haben, notwendig ist. –

+1

Um die Daten in das Fenster zu bekommen, können Sie möglicherweise den Speicher DC überspringen und SetDIBitsToDevice verwenden, um die Pixeldaten direkt in das Fenster DC zu bekommen. –