Jak wymusić na grze działanie "w oknie"?

2

Robiłem jakiś czas temu m.in. wymuszenie działania w oknie dla pewnej gry. Używała DirectDraw.
Najpierw robimy jakiś DLL injecting i przechwytujemy CreateWindow oraz DirectDrawCreate. W tej pierwszej funkcji ustawiamy sobie style okna takie jak chcemy oraz ew. wołamy AdjustWindowRect i zachowujemy HWND. W tej drugiej funkcji, wołamy naszą oryginalną już na początku, ale lekko modyfikujemy otrzymane nam IDirectDraw, a dokładnie jego vtable. Pod indeksem 21 znajduje się tam wskaźnik do metody SetDisplayMode, którą nasza gra wołała przy uruchomieniu oraz przy żądaniu zmiany rozdzielczości w opcjach gry. Przechwytujemy tę funkcję i wołamy tam sobie AdjustWindowRect i SetWindowPos na naszym zachowanym HWND.
O tym, że gra wywołuje takie, a nie inne funkcje dowiedziałem się robiąc disassembling głównego exe-ka gry, a o 21. indeksie buszując w nagłówkach SDK DirectX.

Najciekawsze, czyli przechwycenie SetDisplayMode może wyglądać tak:

HRESULT WINAPI MyDirectDrawCreate(GUID *lpGUID, LPDIRECTDRAW *lplpDD, IUnknown *pUnkOuter)
{
    HRESULT result = DirectDrawCreate(lpGUID, lplpDD, pUnkOuter);

    IDirectDraw *directDraw = *lplpDD;

    void** vtable = *(void***) directDraw;
    vtable[21] = &SetDisplayMode;

    return result;
}

(w sumie to powinno się najpierw przeanalizować ten result)

0

@olesio adlaczego w tym fixie masz Sleep(1); ?

zabijcie explorer.exe to dobry pomysl na rozwiazanie problemow ze starszymi grami na Windows 7.

0

Zdaje się, że Sleep był konieczny lub wzięty z oryginalnego źródła fixa do Wormsów Armaggeddon, bazującego na tej metodzie. Na pewno nie jest ona idealna. Ponieważ po Ctrl+Alt+Del mamy okno w "skopanych" kolorach. Prawidłowo napisane dllki do spoofnięcia robią to bardziej profesjonalnie. U mnie czasem okno się nie zamknie i są inne nieprzewidziane problemy. Jednak ja od zera takiej porządnej dll w Delphi czy C++ nie umiem stworzyć.

Wiem, że @Azarien bawił się kiedyś źródłem ddhacka do Wing Commander 4, który w wielu grach sprawdza się świetnie. Tylko niektóre tekstury na fragmencie obrazu migoczą. Ale nie wiem co mu z tego wyszło, by spróbowac zrobić uniwersalną dllkę dla wielu starczy gier. Zdałem się na Niego. Gdyż nie mam w ogóle doświadczenia z DX.

0

Pod indeksem 21 znajduje się tam wskaźnik do metody SetDisplayMode, którą nasza gra wołała przy uruchomieniu oraz przy żądaniu zmiany rozdzielczości w opcjach gry. Przechwytujemy tę funkcję i wołamy tam sobie AdjustWindowRect i SetWindowPos na naszym zachowanym HWND.

Brzydki hack ;-) Ładniej jest napisać własne IDirectDraw które wywołuje metody oryginalnego z wyjątkiem tej jednej funkcji...

...aaaale, to nie zadziała tak jak byś chciał. DirectDraw operuje zawsze na pełnym ekranie, przy bieżącej rozdzielczości i głębi kolorów.
Podstawowa powierzchnia ekranu (IDirectDrawSurface) odzwierciedla cały ekran nawet w trybie okienkowym. To aplikacja musi pilnować, by nie rysować poza własnym oknem (jest to zautomatyzowane za pomocą IDirectDrawClipper).
Okienkowy program pod DirectDraw jest możliwy, ale różni się więcej niż tylko wywołaniem SetDisplayMode.

Zazwyczaj robiono tak, że za pomocą SetDisplayMode ustawiano rozdzielczość (najczęściej 640x480x8) i już dalej aplikacja na sztywno zakłada, że ma taką pełnoekranową rozdziałkę i 8-bitowy kolor.

Trzeba więc napisać dobry kawał całego DirectDraw na nowo, by przejąć kontrolę nad oknem tak, by aplikacja nie zauważyła różnicy.

Ale nie wiem co mu z tego wyszło, by spróbowac zrobić uniwersalną dllkę dla wielu starczy gier.
To nie jest takie proste, ale projekt nie jest zarzucony ;) /niedawno odkryłem sfall i zawarte tam co-nieco związane z ddraw/

0

@olesio jesli dobrze rozumiem, to ten fix wstrzmuje explorer.exe gdy gra jest aktywna a podczas alt+tab proces ten jest wzniowiony i cos tam odswiezane. Tak?

0

No mniej więcej tak. Hook jest po to, żebym wykryć - chociaż nie zawsze skutecznie - zamknięcie aplikacji. Odświeżenie te było konieczne, ponieważ czasem zostawał nam przykładowo zielonkawy przycisk Menu Start w klasycznej kompozycji pod Windows 7. Lub inne glitche graficzne na ekranie. Fix ten jest jak wspomniałem badzo malo profesjonalny. I należało by się mocno nakombinować, tak jak robią to dedykowane hacki dla konkretnych tytułów starszych gier.

0

@mca64: zdaje się przy większym sleepie miałem jakieś problemy. Zostawiłem więc tak, jak było zdaje się w oryginalnym kodzie. Wstrzymanie procesu oczywiście może doprowadzić do sytuacji, że nie będziemy mieli dostępu do paska, gdy coś się zcrashuje itp.

Także sposób mocno inwazyjny. Jednak przy wielu grach skuteczny i dla mnie wystarczający. Jednak lepiej mieć uruchomiony też jakiś File Manager i pod ręką na przykład w %PATH% takiego batcha nazwanego er. Od explorer reload dla szybszego wywołania przez wpisanie ;)

@echo off
taskkill /im explorer.exe /f
start %WINDIR%\explorer.exe

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0