Wie funktionieren Patches in Spielen?

37

Konsolen- und PC-Spiele haben manchmal Patches, um Fehler zu beheben, die die Entwickler verpasst haben / für die sie keine Zeit hatten.

Meine Frage ist, wie funktionieren diese?

Manchmal sind die Patch-Dateien einige Megabyte groß. Ich verstehe nicht, wie eine kleine Datei ein konformes Programm verändern kann.

MulletDevil
quelle
Sie möchten ein kompiliertes Spiel ändern, das Sie mit einem kleinen Patch erstellt haben?
Wolfdawn
Nein, ich interessiere mich nur für die Theorie dahinter. Meine Spiele sind klein genug, um sie einfach neu zu kompilieren und das ganze Spiel erneut zu verbreiten :)
MulletDevil
4
Das ist eine interessante Frage. Es basiert nicht auf einem Problem, mit dem Sie beim Spieldesign konfrontiert sind. Es gibt auch viele Möglichkeiten, mit Patches von der einfachsten Seite aus umzugehen, indem alle Dateien ersetzt werden, die auf die komplexesten geändert wurden, und Anweisungen zum Ändern bestimmter Dinge in vorhandenen Dateien abgerufen werden. Ich bin nicht sicher, ob diese Frage für diese Site geeignet ist.
Wolfdawn
3
Ein paar Megabyte sind nicht "klein". Angenommen, wir haben eine drei Megabyte große Datei, die aus sechs Megabyte komprimiertem ausführbarem Code besteht. Angenommen, die Anweisungen sind im Durchschnitt sechs Byte lang, so dass es sich um eine Million Anweisungen handelt. (Ignorieren wir statische Daten wie String-Literale und so weiter.) Wenn eine Zeile C ungefähr zehn Maschinenanweisungen entspricht, sind das 100.000 Codezeilen. Das scheint für die Kern-Engine eines Spiels ausreichend zu sein. Der größte Teil der Installationsgröße wird aus Texture Maps, Bildschirmen und Videosequenzen bestehen.
2
Einige Megabyte sind möglicherweise klein, alles hängt davon ab, was darin enthalten ist und wie viel Prozent der gesamten Codebasis enthalten sind. Wenn beispielsweise aufgrund der gewählten Dateiformate usw. eine komplette 3D-Karte ersetzt werden muss, einschließlich aller Texturen und was nicht, können einige Megabyte tatsächlich sehr klein sein.
Jwenting

Antworten:

30

Es gibt mehrere Möglichkeiten, dies zu tun. Am einfachsten wäre es, die beiden Dateien per XOR zu verknüpfen und zu komprimieren (GZIP oder so weiter). Die Theorie dahinter ist, dass man hoffentlich eine große Folge von Nullen bekommen kann (lange Folgen gleicher Werte lassen sich gut komprimieren).

Sie können dieses Konzept weiterentwickeln und versuchen, Bereiche der beiden Dateien zu finden, in denen die Daten identisch sind, und sie vollständig weglassen.

Schließlich können Sie die Struktur jedes Dateityps zu Ihrem Vorteil nutzen. In einer EXE-Datei können Sie beispielsweise jede Methode einzeln packen (nur die, die geändert wurden) und die EXE-Datei während der Patch-Anwendung selbst wiederherstellen. Bedenken Sie jedoch, dass dies im Bereich des Overkills sehr wahrscheinlich ist und sich möglicherweise nicht lohnt (der Gewinn gegenüber einem einfachen Bdiff rechtfertigt möglicherweise nicht die zusätzliche Komplexität, die in der freien Wildbahn brechen könnte). Als weiteres Beispiel könnten Sie Diff-Dateien für Skripte verwenden.

Die meisten Patch-Systeme in freier Wildbahn gehen jedoch den einfachsten Weg: Sie packen nur Dateien, die sich geändert haben - sie versuchen nicht, Änderungen nur innerhalb dieser Dateien zu packen (wahrscheinlich aus gutem Grund sind die meisten Spielinhalte bereits komprimiert und erstellen Patches gegen Hoch Entropie oder komprimierte Daten funktionieren überhaupt nicht .

Jonathan Dickinson
quelle
Was bedeutet es, jede Methode einzeln in eine exe zu packen? Ist das praktisch
Wolfdawn
@ArthurWulfWhite ja. Für ein Indie-House ist es wahrscheinlich nicht die Zeit wert, da es extrem viel Zeit und Mühe kosten würde (Sie müssen im Wesentlichen Ihren eigenen Linker schreiben) - als Unternehmen, das sich ausschließlich mit Patching-Technologie befasst, wäre es die Mühe wert. Es hängt alles davon ab, wie groß der ausführbare Code ist - ich habe mir Sacred 2 angesehen und es war 26 MB (8 MB für die Haupt-EXE). Ein binäres Diff könnte sich dem allerdings annähern - es lohnt sich jedoch, es herauszubringen (ich weiß, dass CABs eine gute Komprimierung für EXEs erhalten, weil sie die Struktur ausnutzen).
Jonathan Dickinson
Das ist sehr interessant. Ich nehme an, dass die Minimierung der Patch-Größe bei der heutigen Bandbreite kein großes Problem darstellt. +1 eine interessante durchdachte Antwort.
Wolfdawn
Es ist nicht so einfach, einzelne Methoden in den meisten Spielen zu patchen. Der Compiler kann mit einfachen Codeänderungen eine drastisch andere Ausgabe haben. Automatische Inlining-Entscheidungen können sich ändern, das Layout der Symboltabelle kann sich ändern usw. Codeänderungen ändern häufig auch die interne API-Struktur. Optimierungen verwischen bereits die Grenze zwischen Funktionsgrenzen im Vergleich zu dem, was Sie in Ihrem Code-Editor sehen. DRM-Systeme trüben das Wasser ebenfalls stark. Patch-Systeme verwenden Wholesale-Ersatz oder Binär-Diffs und komprimieren diese. Alles, was Sie vorschlagen, ist einfach zu zerbrechlich, um in der realen Welt versendet zu werden, imo.
Sean Middleditch
2
@ SeanMiddleditch Ich werde es nur tun, um zu beweisen, dass es möglich ist :).
Jonathan Dickinson
15

Der ausführbare Code eines Spiels befindet sich nicht immer nur in der ausführbaren Datei, sondern ist häufig in mehrere dynamische Bibliotheken (z. B. das Spiel, Grafik- und Sound-Engines), die eigentliche ausführbare Datei und möglicherweise viele Skripts für verschiedene Zwecke unterteilt.

Ein Patch kann Probleme in einem dieser Teile beheben, ohne dass eine Änderung in allen Teilen erforderlich ist.

Ein anderer Ansatz als das Ersetzen aller geänderten Dateien könnte darin bestehen, einfach ein binäres Diff auf sie anzuwenden und nur die tatsächlichen Unterschiede zu packen, die neu verteilt werden sollen.

(Das funktioniert natürlich nur für Dateien, von denen Sie garantieren können, dass sie nicht vom Benutzer geändert werden.)


quelle
2
Sie können dies als Beispiel nennen: daemonology.net/bsdiff
wolfdawn
2
Gute praktische Antwort. +1
wolfdawn
2

Normalerweise verwenden sie ein binäres Diff-System eines Drittanbieters, um Patches auf die Spieldaten zu verteilen. Die ausführbaren Dateien sind in der Regel klein genug, um vollständig trivial verteilt zu werden.

Die meisten modernen Spiele verfügen über Hunderte von Megadaten (hauptsächlich Texturen, Modelle, Level-Daten usw.). Diese müssen ziemlich oft gepatcht werden. Soweit ich weiß, haben die Verlage normalerweise eine proprietäre Standardmethode, um dies zu tun.

Natürlich gibt es Open-Source-Beispiele. Einige Linux-Distributionen (Fedora?) Verwenden binäre Diffs für ihre Patches. Sie können diese untersuchen und deren Quellcode oder Dokumentation lesen.

MarkR
quelle
-1

Moderne diffAlgorithmen können Byte-Sequenzen, die zwei Binärdateien gemeinsam haben, effizient finden. Kein Wunder, wenn Sie darüber nachdenken. Bei der Dateikomprimierung müssen auch identische Bytefolgen gefunden werden.

Sobald Sie die Liste identischer Bytesequenzen haben, müssen Sie nur den alten und den neuen Versatz, die Länge und natürlich alles, was völlig neu ist, senden. Empfangsseitig handelt es sich dann um eine unkomplizierte Montage. Kopieren Sie die Bits, die Sie aus der alten Datei behalten möchten, und füllen Sie die neuen Bits aus.

Das Erstellen des Patches wird noch einfacher, wenn Ihr Linker eine MAP-Datei ausspucken kann, in der die Offsets aller Funktionen in der Datei aufgelistet sind.

MSalters
quelle