Poprawienie skompilowanego kodu aby grafika była ok pod Windows 7.

Odpowiedz Nowy wątek
2011-07-24 16:23
0

Witam. Nie wiem czy to równie często czytany przez wielu dział jak Newbie, ale mam taką nadzieję :) Otóż chciałem zapytać, czy ktoś z Was próbował, a może są na ten temat jakieś artykuły, ktorych nie wiem jak wygooglować - poprawić jakąs grę czy program działąjący pod DirectX albo Allegro tak by na pełnym ekranie nie było problemów z kolorami i grafiką pod Windows 7? Wiadomo, można ubijać explorer.exe, a po uruchomieniu procesu gry poczekać na jego zamknięcie i ponownie uruchomić explorer.exe. Jednak może da się z pomoca nie wiem OllyDbg i Hex Edytora poprawić wywołanie jakiś funkcji nie mając kodu źródłowego, a jedynie niespakowany i niezaszyfrowany plik exe gry? Wiem, że kiedyś człowiek nazywający się Arek Rataj poprawił exek do fajnej polskiej przygodówki "Książe i Tchórz", dzięki czemu gra chodzi pod XP i nowszymi. Ja później na podstawie Jego exeka, który został odszyfrowany zrobiłem zmianą może 5 bajtów wersję no CD. Jednak pod Windows 7 jest problem z grafiką. To samo tyczy się innej polskiej przygodówki "Wacki". Wiadomo jak gra jest exek nie jest zaszyfrowany albo niespakowany zrobienie patcha no CD - to na ogół pikuś, ale nie mam doświadczenia w poprawianiu innych funkcji które odpowiadają za grafikę. Jeśli chodzi o gry to zastanawiam się jak ugryżć właśnie tę kwestię w grach pisanych w czasach Windows '98 czyli: "Die By The Sword", "Kświążę i Tchórz" oraz "Wacki - Kosmiczna Rozgrywka". Wszystkie pisane w okolicach 1998-1999 roku pod dostępną wówczas wersję DirectX. A z programów to na przykład emulator ZX Spectruma "RealSpec", który działa dobrze tylko w oknie (używa bibliotek Allegro), zaś na pełnym ekranie bez ubijania explorer.exe kolorystyka się kaszani tak, że wygląda jakby była wyświetlana przez jakąs stara kilku kolorową kartę typu CGA czy czymś w tym rodzaju (nie pamiętam danych starych ukłądów, bo mój pierwszy komp miał VGA :)). Chodzi mi o to jak można spróbować to spatchować żeby i pod XP, ale i pod wyższymi systemami działalo ok. Dodam, że nie zawsze zabawy ze zgodnością czy uruchamianie w niższych rozdzielczościach pomaga. Wiadomo, że tak kombinowac najłatwiej, ale może jednak da się poprawić jakoś sam kod. Z góry dziękuję za wszelkie podpowiedzi i przepraszam za rospianie się :)


edytowany 5x, ostatnio: olesio, 2011-07-24 17:24

Pozostało 580 znaków

2011-07-25 00:55
Rev
0

W sumie ciekawy temat. Faktycznie na nowszych systemach starsze gry mają artefakty w grafice. Poszukałem trochę i znalazłem podobny wątek na jednym z zagranicznych for: http://www.gamedev.net/topic/[...]ying-old-games-directx-calls/
Tam co prawda chodzi o grę już wykorzystującą Direct3d i sprawy mogą być bardziej skomplikowane, ale jak widać, są podstawy, by sądzić, że może pomóc uruchomienie kontekstu grafiki w trybie 24- albo 32-bitowym. Być może byłoby też trzeba popoprawiać wszystkie wywołania tworzące tekstury, a i z tym tekstury też. Jeżeli wystarczy to zrobić tylko tą pierwszą rzecz, to faktycznie jest to kwestia zmiany jednej stałej (4 bajty :)?). Można się pobawić IDĄ i jakimś heksedytorem.


Pozostało 580 znaków

2011-07-25 01:13
O_o
0

To kolory będę miał normalne jak włączę z ubitym explorerem o_O ?
Wraagh :D Zaraz sprawdzę bo jak na razie to się męczę z XP na wirtualce ;p

Pozostało 580 znaków

2011-07-25 19:23
0

@Rev: dziękuję za odpowiedź. Niestety http://www.reverse-engineering.net podana w tym wątku już nie istnieje. Jeżeli chodzi na przykład o "Księcia i Tchórza" to "stary ale jary" W32Dasm pokazuje nam tylko takie funkcje związane z DirectX'em:

   Import Module 003: DDRAW.dll

 Addr:000374E0 hint(0000) Name: DirectDrawCreate

   Import Module 004: DSOUND.dll

 Addr:000374F4 hint(0000) Name: DirectSoundCreate
   Import Module 006: WINMM.dll

Inne to MCI albo systemowe WIndowsa. A kod w okolicach DirectDrawCreate wygląda w przypadku Księcia i Tchórza tak jak poniżej:

* Possible StringData Ref from Data Obj ->"UWAGA!"
                                  |
:00401179 6889E04000              push 0040E089

* Possible StringData Ref from Data Obj ->"DirectSound: Niekompatybilny sterownik."
                                  |
:0040117E 688FE14000              push 0040E18F
:00401183 FF35D0E44000            push dword ptr [0040E4D0]

* Reference To: USER32.MessageBoxA, Ord:0000h
                                  |
:00401189 E845C70000              Call 0040D8D3
:0040118E 83F802                  cmp eax, 00000002
:00401191 75CA                    jne 0040115D
:00401193 C60580E5400001          mov byte ptr [0040E580], 01

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040115B(U), :00401172(C)
|
:0040119A 6A00                    push 00000000
:0040119C 6850E54000              push 0040E550
:004011A1 6A00                    push 00000000

* Reference To: DDRAW.DirectDrawCreate, Ord:0000h
                                  |
:004011A3 E89DC70000              Call 0040D945

* Possible StringData Ref from Data Obj ->"DirectX: Brak sterownik"
                                  |
:004011A8 BEA6E04000              mov esi, 0040E0A6
:004011AD 85C0                    test eax, eax
:004011AF 0F8538020000            jne 004013ED
:004011B5 6A11                    push 00000011
:004011B7 A150E54000              mov eax, dword ptr [0040E550]
:004011BC FF35D0E44000            push dword ptr [0040E4D0]
:004011C2 8B18                    mov ebx, dword ptr [eax]
:004011C4 50                      push eax
:004011C5 FF5350                  call [ebx+50]

* Possible StringData Ref from Data Obj ->"DirectX: Nie moge uruchomic trybu "
                                        ->"640x480x256 kolorow."
                                  |
:004011C8 BE01E14000              mov esi, 0040E101
:004011CD 85C0                    test eax, eax
:004011CF 0F8518020000            jne 004013ED

Dla próby dalem pod 4011CF skok na bezwarunkowy i pokazuje się błąd oczywiście, ale teraz pytanie gdzie szukać tej stałej z ilością kolorów. Czytałem opis DirectDrawCreate na MSDNie, ale nie jest on tak szczegółowy i bogaty, abym się w nim połapał. Brak też przykładów. Liczę, że może ktoś jeszcze spojrzy na ten temat i będzie w stanie coś więcej doradzić, a może Ty Rev robiłeś kiedyś taki reverse enginering dla jakiejś starszej gierki i wiesz jak poprawić DirectDrawCreate o ile poprawienie wywołania ów funkcji w ogóle będzie "lekarstwem" na działąnie gry pod Win 7.

@O_o: taK, dla Windows 7 to wystarczy, ja na przykład dla Księcia i Tchórza napisałem taki loader, którego kod wklejam poniżej, bo wprawdzie można ustawić w zgodności rozdzielczość 640x480 i uruchomienie w 256 kolorach, ale nie na każdą grę to zadziała. Poza tym fajnie by było by uruchomić grę bez kombinowania w zgodnościach itp.

program kit_loader;
 
{$APPTYPE GUI}
 
{$R *.res}
 
uses
  Windows, TlHelp32;
 
const
  Game_Exec = 'code.exe';
 
function AddBackSlash(Path : string) : string;
begin
  Result := '';
  if Path = '' then
  begin
    Exit;
  end;
  if Path[Length(Path)] <> '\' then
  begin
    Result := Path + '\'
  end
  else
  begin
    Result := Path;
  end;
end;
 
function StrLCopy(Dest : PChar; const Source : PChar; MaxLen : Cardinal) : PChar; assembler;
asm
        PUSH    EDI
        PUSH    ESI
        PUSH    EBX
        MOV     ESI,EAX
        MOV     EDI,EDX
        MOV     EBX,ECX
        XOR     AL,AL
        TEST    ECX,ECX
        JZ      @@1
        REPNE   SCASB
        JNE     @@1
        INC     ECX
@@1:    SUB     EBX,ECX
        MOV     EDI,ESI
        MOV     ESI,EDX
        MOV     EDX,EDI
        MOV     ECX,EBX
        SHR     ECX,2
        REP     MOVSD
        MOV     ECX,EBX
        AND     ECX,3
        REP     MOVSB
        STOSB
        MOV     EAX,EDX
        POP     EBX
        POP     ESI
        POP     EDI
end;
 
function StrPCopy(Dest : PChar; const Source : string) : PChar;
begin
  Result := StrLCopy(Dest, PChar(Source), Length(Source));
end;
 
function StrPas(const Str : PChar) : string;
begin
  Result := Str;
end;
 
function AnsiUpperCase(const S : string) : string;
var
  Len : Integer;
begin
  Len := Length(S);
  SetString(Result, PChar(S), Len);
  if Len > 0 then
  begin
    CharUpperBuff(Pointer(Result), Len);
  end;
end;
 
function GetWinDir : string;
var
  Dir : array[0..MAX_PATH] of Char;
begin
  GetWindowsDirectory(Dir, MAX_PATH);
  Result := AddBackSlash(StrPas(Dir));
end;
 
function FileExists(FileName : string) : boolean;
var
  Find : THandle;
  WFD : TWin32FindData;
begin
  Find := Windows.FindFirstFile(PChar(FileName), WFD);
  Result := Find <> INVALID_HANDLE_VALUE;
  Windows.FindClose(Find);
end;
 
function ExtractFileName(FileName : string) : string;
var
  I : integer;
begin
  ExtractFileName := FileName;
  for I := Length(FileName) downto 1 do
  begin
    if (FileName[I] = '\') then
    begin
      ExtractFileName := Copy(FileName, I + 1, MaxInt);
      Break;
    end;
  end;
end;
 
function ExtractFilePath(const FileName : string) : string;
var
  I : integer;
begin
  ExtractFilePath := '';
  for I := Length(FileName) downto 1 do
  begin
    if FileName[I] = '\' then
    begin
      ExtractFilePath := Copy(FileName, 1, I);
      Break;
    end;
  end;
end;
 
function ProcessExists(ExeFileName : string; var PIDResult : Cardinal) : boolean;
var
  ContinueLoop : BOOL;
  FSnapshotHandle : THandle;
  FProcessEntry32 : TProcessEntry32;
begin
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  Result := False;
  while Integer(ContinueLoop) <> 0 do
  begin
    if ((AnsiUpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      AnsiUpperCase(ExeFileName)) or (AnsiUpperCase(FProcessEntry32.szExeFile) =
      AnsiUpperCase(ExeFileName))) then
    begin
      Result := True;
      PIDResult := FProcessEntry32.th32ProcessID;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;
 
procedure KillTask(ExeFileName : string);
var
  CPid : Cardinal;
begin
  ProcessExists(ExeFileName, CPid);
  if CPid <> 0 then
  begin
    TerminateProcess(OpenProcess(PROCESS_TERMINATE, False, CPid), 1);
  end;
end;
 
procedure WinExecAndWait32(FileName : string; Visibility : Integer);
var
  WorkDir : string;
  StartupInfo : TStartupInfo;
  AppName : array[0..512] of Char;
  CurrDir : array[0..255] of Char;
  ProcessInfo : TProcessInformation;
begin
  StrPCopy(AppName, FileName);
  GetDir(0, WorkDir);
  StrPCopy(CurrDir, WorkDir);
  FillChar(StartupInfo, Sizeof(StartupInfo), #0);
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;
  if CreateProcess(nil, AppName, nil, nil, False,
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil,
    StartupInfo, ProcessInfo) then
  begin
    WaitforSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end;
end;
 
const
  Explorer_Exec = 'explorer.exe';
var
  TmpC : Cardinal;
  App_Path : string;
begin
  App_Path := ExtractFilePath(ParamStr(0));
  if FileExists(App_Path + Game_Exec) then
  begin
    KillTask(Explorer_Exec);
    WinExecAndWait32(App_Path + Game_Exec, SW_SHOW);
    if not ProcessExists(Explorer_Exec, TmpC) then
    begin
      WinExec(PChar(GetWinDir + Explorer_Exec), SW_HIDE);
    end;
  end;
end.

EDIT: pozmieniałem 08 na 10 i 20, tak samo rozdzielczośc na większą, no i niestety w przypadku "Księcia i Tchórza" gra na chwile miga czarnym ekranem i się nie uruchamia. Natomiast zmiany w podobnym miejscu w "Eackach" powodują że gra się uruchamia ale okno samej gry jest na czarnym tle w rogu, a poza tym kolory są gorzej pomieszane niż z explorer.exe działającym w tle. Podejrzewam więc, że musiała by zostać chyba przekonwertowana cała grafika i ewentualne inne opcje. Jakby ktoś miał jeszcze jakiś pomysł to proszę pisać.

:004011D5 6A08                    push 00000008
:004011D7 68E0010000              push 000001E0
:004011DC A150E54000              mov eax, dword ptr [0040E550]
:004011E1 6880020000              push 00000280
:004011E6 8B18                    mov ebx, dword ptr [eax]
:004011E8 50                      push eax
:004011E9 FF5354                  call [ebx+54]

edytowany 2x, ostatnio: olesio, 2011-07-25 21:16

Pozostało 580 znaków

2011-07-26 07:29
Rev
0

Wygląda na to, że Microsoft sam wie o problemie z kolorami pod DirectDraw w Windows 7 i nawet zaimplementował opcję wstecznej kompatybilności. Lista aplikacji jest w rejestrze. Wygugluj pod "Microsoft\DirectDraw\Compatibility", znajdziesz więcej info. Są nawet gotowe narzędzia, które mogą dodać daną aplikację.
Problem rozwiązuje też bezpośrednia translacja wywołań DirectDraw na np. DirectX 10, są też takie aplikacje i ponoć też działają.

A co do tego RE, zdaje się, że gdy zmienimy 8 bitów na 16, jedna z późniejszych funkcji DirectDraw zwraca błąd. Nie chciało mi się już szukać która to i co zwróciła, ale to ta funkcja, do której skaczemy pod adres ecx+7C.


Pozostało 580 znaków

2011-07-26 21:44
0
Rev napisał(a)

Wygląda na to, że Microsoft sam wie o problemie z kolorami pod DirectDraw w Windows 7 i nawet zaimplementował opcję wstecznej kompatybilności. Lista aplikacji jest w rejestrze. Wygugluj pod "Microsoft\DirectDraw\Compatibility", znajdziesz więcej info. Są nawet gotowe narzędzia, które mogą dodać daną aplikację.
Dziękuję za odpowiedź. Sprawdziłem i faktycznie można modyfikować rejestr, ale są pewne "ale". Mianowicie na przykład w przypadku gry Wacki, intro uruchamiane przed grą nadal jest w złych kolorach, pewnie trzeba by dodać program wywołujący kodeki, ale jaki to jest nie wiem, bo wszystko jest raczej pod procesem wacki.exe i jeżeli zastosujemy zmiany kompatybilności to zadziała ok. Jest także jeden niestety poważny minus, który niweluje jedynie ubicie explorer.exe - mianowicie czy przez ustawienaia w zakładce zgodnośc czy przez rejestr dla kompatybilności DirectDraw, po przełaczeniu Alt+Tab z powrotem na pulpit i powrocie do gry, kolory znowu są namieszane. Dodałem dla testów rownież explorer.exe do tych kluczy w Rejestrze, ale nic to nie pomogło.
Problem rozwiązuje też bezpośrednia translacja wywołań DirectDraw na np. DirectX 10, są też takie aplikacje i ponoć też działają.
To brzmi ciekawie, ale jak wygooglować takie programy, nie wiem za bardzo co wpisać. Wyskoczyły mi linki do artkułów o translacji textur, a jak wpisywałem changing directx to wyskakiwały artykuły jak zrobić downgrade z DX 10 na DX 9 albo w ogołe pozbywać się DX'a z nowszych systemów.

A co do tego RE, zdaje się, że gdy zmienimy 8 bitów na 16, jedna z późniejszych funkcji DirectDraw zwraca błąd. Nie chciało mi się już szukać która to i co zwróciła, ale to ta funkcja, do której skaczemy pod adres ecx+7C.
Zanopowałem skoki sprawdzające w kodzie exeka do "Księcia i Tchórza", zmieniłem rozdzielczość oraz paletę na 1440x900x32 w tej instrukcji po DirectDrawCreate, jednak gra odapala się jakby w kolorach czarno-białych, a do tego w malutkim okienku w lewym górnym rogu, a reszta ekranu jest czarna. Podobnie na zmiany reagują "Wacki". Masz może jeszcze jakiś pomysł co poprawić aby gra jednak miała prawidłowy wygląd pod Windows 7, bez cudowania z ubijaniem explorera, wpisach w rejestrze i innych? Czy w ogóle da się jeszcze coś pozmieniać? Bo gdyby nie problem taki, że czasami trzeba się przełaczyć na ekran Windows'a i wtedy znowu jest "sieczka z kolorami" to myk z Rejestrami byłby ok. Z góry dziękuję za dalsze podpowiedzi.


edytowany 2x, ostatnio: olesio, 2011-07-26 21:46

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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