Jak działają łatki w grach?

37

Gry na konsole i komputery PC mają czasami łatki do naprawiania błędów, których twórcy nie zauważyli / nie mieli czasu naprawić.

Moje pytanie brzmi: jak to działa?

Czasami pliki łatek mają kilka megabajtów. Nie rozumiem, jak mały plik może zmienić zgodny program.

MulletDevil
źródło
Chcesz zmienić skompilowane gry stworzone przy użyciu małej łatki?
wolfdawn
Nie, interesuje mnie tylko teoria. Moje gry są wystarczająco małe, aby je ponownie skompilować i ponownie rozprowadzić całą grę :)
MulletDevil
4
To interesujące pytanie. Nie jest oparty na problemie, z jakim masz do czynienia przy projektowaniu gry. Istnieje również wiele sposobów radzenia sobie z łatkami w najbardziej naiwny sposób, zastępując wszystkie pliki, które zostały zmodyfikowane, najbardziej złożonymi, otrzymując instrukcje zmiany określonych rzeczy w istniejących plikach. Nie jestem pewien, czy to pytanie jest odpowiednie dla tej witryny.
wolfdawn
3
Kilka megabajtów nie jest „małe”. Załóżmy, że mamy plik o rozmiarze trzech megabajtów, który jest skompresowany o rozmiarze 6 megabajtów wykonywalnego kodu. Załóżmy, że instrukcje mają średnio sześć bajtów, więc około miliona instrukcji. (Zignorujmy dane statyczne, takie jak literały łańcuchowe i tak dalej.) Jeśli wiersz C odpowiada około dziesięciu instrukcjom maszynowym, to 100 000 wierszy kodu. To wydaje się wystarczające dla podstawowego silnika gry. Większość rozmiaru instalacji to rzeczy takie jak mapy tekstur, ekrany, sekwencje wideo.
2
kilka megabajtów może być małe, wszystko zależy od tego, co w nim jest i jaki procent całkowitej bazy kodu. Jeśli powiedzmy, że należy wymienić całą mapę 3D z powodu wybranych formatów plików itp., W tym wszystkich tekstur, a co nie, kilka megabajtów może być naprawdę bardzo małych.
jwenting

Odpowiedzi:

30

Można to zrobić na wiele sposobów, najprościej byłoby XOR obu plików i skompresować je (GZIP itp.). Teoria tego polega na tym, że mam nadzieję, że można uzyskać dużą sekwencję zer (długie sekwencje tych samych wartości dobrze się kompresują).

Możesz rozwinąć tę koncepcję i znaleźć obszary dwóch plików, w których dane są identyczne, i całkowicie je pominąć.

Wreszcie możesz wykorzystać strukturę każdego typu pliku na swoją korzyść. Na przykład w EXE można spakować każdą metodę osobno (tylko te, które uległy zmianie) i samodzielnie odtworzyć EXE podczas aplikacji łatki; należy jednak pamiętać, że jest to bardzo prawdopodobne w dziedzinie przesady i może nie być warte wysiłku (zysk nad prostym bdiffem może nie uzasadniać dodatkowej złożoności, która mogłaby się złamać na wolności). Jako kolejny przykład możesz użyć plików diff do skryptów.

Jednak większość systemów łatających na wolności podąża najprostszą drogą: po prostu pakuje zmienione pliki - nie próbuje jedynie pakować zmian w tych plikach (prawdopodobnie z dobrego powodu większość zawartości gry jest już skompresowana i tworzy łatki przeciwko wysokim entropia lub skompresowane dane w ogóle nie będą działać ).

Jonathan Dickinson
źródło
Co rozumiesz przez pakowanie każdej metody indywidualnie w pliku exe. Czy to jest praktyczne?
wolfdawn
@ArthurWulfWhite tak. Dla indie house prawdopodobnie nie byłby warty tego czasu, ponieważ zajęłoby to niezwykle dużo czasu i wysiłku (w zasadzie musisz napisać własny linker) - jako firma zajmująca się wyłącznie „technologią łatania” byłaby warta wysiłku. Wszystko zależy od tego, jak duży jest kod wykonywalny - rzuciłem okiem na Sacred 2 i wynosił on 26 MB (8 MB dla głównego EXE). Binarny diff może być jednak w stanie się do niego zbliżyć - nadal warto go tam wypróbować (wiem, że CAB mają dobrą kompresję w plikach EXE, ponieważ korzystają ze struktury).
Jonathan Dickinson
To jest bardzo interesujące. Podejrzewam, że przepustowość jest taka, jaka jest dzisiaj, minimalizacja rozmiaru łatki gry nie jest poważnym problemem. +1 ciekawą, dobrze przemyślaną odpowiedź.
wolfdawn
W niektórych grach łatanie pojedynczymi metodami w większości gier jest niewykonalne. Kompilator może mieć drastycznie różne dane wyjściowe nawet przy prostych zmianach kodu. Automatyczne decyzje dotyczące wstawiania mogą ulec zmianie, układ tabeli symboli może ulec zmianie itp. Zmiany kodu często zmieniają również wewnętrzną strukturę API. Optymalizacje już zacierają granicę między granicami funkcji w porównaniu do tego, co widać w edytorze kodu. Systemy DRM również znacznie zabrudzają wodę. Systemy łatek używają hurtowych zamienników lub różnic binarnych i kompresują je. Wszystko, co sugerujesz, jest po prostu zbyt kruche, aby wysyłać je w prawdziwym świecie, imo.
Sean Middleditch
2
@SeanMiddleditch Zrobię to, aby udowodnić, że to możliwe :).
Jonathan Dickinson
15

Kod wykonywalny gry nie zawsze znajduje się tylko w pliku wykonywalnym, często jest podzielony na kilka bibliotek dynamicznych (na przykład gry, silników graficznych i dźwiękowych), rzeczywisty plik wykonywalny i być może wiele skryptów do różnych celów.

Łatka może naprawiać problemy w dowolnej z tych części bez uzasadnienia zmiany we wszystkich z nich.

Inne podejście niż zastąpienie wszystkich zmienionych plików może być po prostu zrobić binarne diff na nich, a tylko packackge rzeczywiste różnice mają być rozdzielone.

(To oczywiście działa tylko na pliki, które możesz zagwarantować, że nie zostaną zmienione przez użytkownika).


źródło
2
Możesz podać to jako przykład: daemonology.net/bsdiff
wolfdawn
2
Dobra praktyczna odpowiedź. +1
wolfdawn
2

Zwykle używają zewnętrznego systemu różnic binarnych do dystrybucji poprawek do danych gry. Pliki wykonywalne są zwykle wystarczająco małe, aby można je było całkowicie trywialnie dystrybuować.

Większość współczesnych gier ma setki megabajtów danych gry (głównie tekstury, modele, dane poziomów itp.). Wymagają one łatania dość często. O ile mi wiadomo, wydawcy zwykle mają standardowy, zastrzeżony sposób na zrobienie tego.

Nie trzeba dodawać, że istnieją przykłady typu open source. Niektóre dystrybucje Linuksa (Fedora?) Używają binarnych różnic w swoich łatkach. Możesz je zbadać i przeczytać ich kod źródłowy lub dokumentację.

MarkR
źródło
-1

Nowoczesne diffalgorytmy mogą efektywnie znajdować sekwencje bajtów wspólne dla dwóch plików binarnych. Nic dziwnego, jeśli się nad tym zastanowić. Kompresja plików polega również na znalezieniu identycznych sekwencji bajtów.

Gdy masz już listę identycznych sekwencji bajtów, wystarczy wysłać stare i nowe przesunięcia, długość i oczywiście wszystko, co jest zupełnie nowe. Po stronie odbiorczej jest to zatem prosty montaż. Skopiuj bity, które musisz zachować ze starego pliku, wypełnij nowe bity.

Tworzenie łatki staje się jeszcze łatwiejsze, jeśli twój linker może wypluć plik MAP, który zawiera listę przesunięć każdej funkcji w pliku.

MSalters
źródło