Wrappery dll - czy jest sens pisać o tym artykuł?

4

Cześć.

Tym razem nie pytanie, a ankieta. Pytanie jak w temacie. Ponieważ ostatnio przy okazji odpowiadania wspominałem o tym. To chciałem się Was poradzić. Za pewne zagadnienie jest Wam znane. Ale może nie wszystkim. Ja nie mam w tym aż takiego doświadczenia. Ale mógłbym podzielić się kilkoma kodami źródłowymi swojego autorstwa. Oczywiście raczej tylko w Delphi. I klepane bardziej pod kątem WinAPI oraz w Delphi 7.

Za pewne znany jest Wam wrapper na ddraw.dll dla kilku gier jak C&C Red Alert czy prosty i może mało elegancki "myk" w ddraw.dll napisany w Delphi oryginalnie stworzony pod kątem Worms Armageddon. Ale czy warto rozwijać temat. Niby artykułów nigdy dość, ale czy moja lemerska, rozpisująca się osoba spasionego "bonka" podoła i chcecie to później czytać?

Docelowo zamieszczone było by to albo na moim blogu albo jako art na 4p. Oczywiście jak najwięćej kodu źródlowego i ewentualnie screenów. Jeżeli macie dodatkowe opinie / pytania / komentarze - proszę piszcie.

0

Moze napisz co rozumiesz pod pojeciem wrapper do gier.

Jedno jest pewne artykulow nigdy za wiele.

0

Dawaj dawaj ;-)

Co do tego DirectDraw, to kiedyś nad tym też siedziałem. Doszedłem do takich wniosków:

• Problem jest pod Vistą i Win7 (nie wiem jak Win8).
• Dotyczy wielu starszych gier 2D.
• Dotyczy tylko trybu graficznego 8-bitowego - 256 kolorów.
• I tylko gdy użyjemy niestandardowej palety (póki program nie rusza palety jest ok).
• Objawem jest gubienie palety własnej na rzecz systemowej (kolory się kaszanią).
• Błąd jest w 100% odtwarzalny we własnym, prawidłowo napisanym kodzie.
• Nic nie pomaga, żadne krążące po necie wpisy w rejestrze, żadne dodatkowe komunikaty (we własnym kodzie).
• Rozwiązaniem jest programowa emulacja 8-bitowego koloru w 32 bitach, czy to przez wrapper na ddraw.dll czy modyfikację kodu źródłowego gry/programu.
• Jeśli piszemy nowy program, to zapomnijmy po prostu o istnieniu czegoś takiego jak 8-bitowy kolor i palety.

0

@lampasss: dziękuję za reakcję. Otóż przez wrapper dll (nie koniecznie do gry, może być do jakiegoś programu) rozumiem własną dllkę, która pod odpowiednią nazwą "udaje" jakąś charakterystycxną dla systemowej / DirectX'owej. To się o ile orientuje właśnie fachowo nazywa wrapper. Przykłady takie jak podałem. Choćby to: http://hifi.iki.fi/cnc-ddraw/ - autor wprawdzie nazywa to hackiem. Może to i hack.

Bardziej chodzi mi o rozwiązanie, polegające na tym, że nasza dllka ma odpowiednio eksportować odpowiednie funkcje tak przekierowane na te z oryginalnej dllki, żeby gra czy program ją akceptowała. Natomiast pozostały kod operował by na grze czy programie używającym dllki, ewentualnie na systemie. Tak aby poprawić zachowanie gry, poprawić pewne rzeczy lub udoskonalić. Chociaż mam tutaj na myśli proste modyfikacje okna gry czy jakiś ustawień kompatybilności. Chociaż jeśli moze @Azarien albo ktoś inny doświadczony w C++ pomógł by - o ile się da, stworzyć taką dllkę ddraw.dll, która działa jak ta do C&C. Jednak pod Delphi i to na zasadzie nie wstrzymywania procesu explorera, można się obejśc bez tworzenia okna dla gry z możliwością resize'u.

Przydało by się napisać coś, co umożliwia uniwersalne użycie w starszych grach DirectX tak aby kolory się nie psuły. Nieogarniam jednak za bardzo DX'a oraz interface'ów, ale jakby to wspólnymi siłami okiełznać. To można by później podzielić się kodem, a i przy okazji na ten temat też napisać artykuł. Póki co jednak chcę się skupić na prostych przykładach. Jak powinny wyglądać przekierowania na oryginalne funkcje API.

Pamiętać należy, że czasem możemy potrzebować "podczepić" się pod funkcję obsługi komunikatów jakiejś gry. Jak wiemy jednak dla obcego procesu jest to niemożliwe. Jedynie injekcja wchodzi w grę. A czasami z injekcją w niektóre procesy moze być problem. Injektor może być wykryty jako malware w używanym przez nas programie antywirusowym. Poza tym zdaży się proces 64 bitowy i problemy ze skuteczną injekcją. A tak wiele spraw może ułatwić taki wrapper. Czasem możemy sobie napisać nawet - nie wiem - symulujące ruchy ułatwienia czy prosty trainer z reakcją na klawisze bez przełączania się później na Cheat Engine.

EDIT: @Azarien: dziękuję za odpowiedź. Z tym, że właśnie skoro robiłeś rekonesans. A masz łeb do C++. To może wspólnymi siłami dało by się napisać uniwersalny wrapper w Delphi. Lub samemu może nawet byś to zrobił w C++. Ważna tylko poprawność działania. Właśnie o ile da się napisać uniwersalne rozwiązanie dla wielu gier. Testować by to można było nie wiem na jakichś polskich przygodówkach jak "Wacki" czy "Książe i Tchórz". Albo na zagranicznym "Heart of Darkness". Tak na szybko te tytuły przyszły mi do głowy. A sam stwierdziłeś, pewnie słusznie, że suspendowanie wątku explorera jest mało eleganckie. Czasem też może się zdarzyć, że po zamknięciu gry jest on nadal wstrzymany i zachodzą problemy dla szarego usera. A może chodzi właśnie żeby ogarnąć tylko ten przedostatni podpunkt, który wymieniłeś. Tylko czy da się dla większości starszych gier z "problemem kolorów"?

0

shut_up_and_take_my_money-t2.jpg

0

Technika podmiany istniejącej DLLki na swoją własną (o tej samej nazwie) nazywa się "DLL Spoofing". W gamedevie funkcjonuje też nazwa "proxy dll". Więcej info: http://vexillium.org/?sec-dllsp

Kiedyś bawiłem się w podmianę jednej z funkcji DirectX, i z tego co pamiętam to funkcje te często zwracają obiekty np. u mnie była to funkcja DirectInputCreateA, która zwracała obiekt kontrolujący obsługę myszki. Mając obiekt trzeba było jeszcze zmodyfikować funkcję odpowiadającą za odczyt współrzędnych (GetDeviceState). Ogólnie problem był dość złożony, ale ostatecznie wszystko się udało :)

Szkielet mojej DLLki:

type
TDirectInputCreateA = function(
      hinst: THandle; 
      dwVersion: DWORD;
      out ppDI: pointer; 
      punkOuter: IUnknown) : HResult; stdcall;
PDirectInputCreateA = ^TDirectInputCreateA;

var
    pDICA: PDirectInputCreateA;

function DirectInputCreateA(
      hinst: THandle; 
      dwVersion: DWORD;
      out ppDI: pointer;  //IDirectInput;
      punkOuter: IUnknown) : HResult; stdcall;
begin
    // TODO: modyfikacje parametrow
    messagebox(0,'DirectInputCreateA','',MB_OK);
    // wywołanie oryginalnej funkcji
    if pDICA(hinst, dwVersion, ppDI, punkOuter) = DI_OK then
    // TODO: modyfikowanie wyniku
        messagebox(0,'DirectInputCreateA','',MB_OK);
end;

procedure DllMain(code: integer);
begin
if code = DLL_PROCESS_ATTACH then
    // pobranie adresu oryginalnej funkcji
    pDICA:= PDirectInputCreateA (getprocaddress(LoadLibrary('c:\windows\system32\dinput.dll'),'DirectInputCreateA'));
end;

exports DirectInputCreateA;

begin
    DllProc:=@DllMain;
    DllMain(DLL_PROCESS_ATTACH);
end.
0

Może i racja. Mi z wikii pasował jednak też termin wrapper. A Twój kod może się i sprawdzał, ale ścieżka bezwzględna to słaby pomysł.

2

Osobiście jestem za napisaniem takiego artykułu; Baza wiedzy się powiększy, a i chętni na pewno się znajdą; Sam też przeglądnę/poczytam - nadmiar wiedzy nie zaszkodzi :]

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