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ę :)
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/562103-advice-on-modifying-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.
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
@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]
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
.
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.