ゲームのパッチはどのように機能しますか?


37

コンソールとPCゲームには、開発者が見逃した/修正する時間がなかったバグを修正するためのパッチが時々あります。

私の質問は、これらがどのように機能するのですか?

場合によっては、パッチファイルのサイズは数メガバイトです。小さなファイルがコンパイルされたプログラムをどのように変更できるか理解していません。


小さなパッチを使用して作成したコンパイル済みゲームを変更したいですか?
wolfdawn

いいえ、私はその背後にある理論に興味があります。私のゲームは、それらを再コンパイルしてゲーム全体を再配布するのに十分なほど小さいです:)
MulletDevil

4
これは興味深い質問です。ゲームデザインで直面している問題に基づいているわけではありません。また、修正されたすべてのファイルを最も複雑なものに置き換え、既存のファイル内の特定のものを変更する指示を取得し、最も単純な方法からパッチを適用する多くの方法があります。この質問がこのサイトに適しているかどうかはわかりません。
wolfdawn

3
数メガバイトは「小さく」ありません。圧縮された6メガバイトの実行可能コードである3メガバイトのファイルがあるとします。命令の平均長が6バイトであると仮定すると、約100万命令になります。(文字列リテラルやその他のような静的データを無視しましょう。)Cの行が約10の機械語命令に対応する場合、100,000行のコードになります。ゲームのコアエンジンにはこれで十分のようです。インストールサイズのほとんどは、テクスチャマップ、画面、ビデオシーケンスなどです。

2
数メガバイトはおそらく小さいかもしれませんが、すべてはその中にあるものとコードベース全体の何パーセントに依存します。すべてのテクスチャなどを含む、選択したファイル形式などのために3Dレベルマップ全体を置き換える必要がある場合、数メガバイトは実際には非常に小さくなります。
12

回答:


30

これを行う方法は複数ありますが、最も簡単なのは、2つのファイルをXORして圧縮することです(GZIPなど)。この背後にある理論は、願わくばゼロの大きなシーケンスを取得できることです(同じ値の長いシーケンスがうまく圧縮されます)。

その概念をさらに理解して、データが同一で​​ある2つのファイルの領域を見つけて、それを完全に省略することができます。

最後に、各タイプのファイルの構造を有利に使用できます。たとえば、EXEでは、各メソッドを個別にパッケージ化し(変更されたメソッドのみ)、パッチの適用中に自分でEXEを再構成できます。ただし、これはやり過ぎの領域である可能性が高く、努力する価値がない可能性があることに留意してください(単純なbdiffを超える利得は、野生で壊れる可能性のある余分な複雑さを正当化できない場合があります)。別の例として、スクリプトにdiffファイルを使用できます。

しかし、野生の中で最もパッチシステムは、最も簡単なルートを取る:彼らはちょうど変更されたファイルをパッケージ化-彼らはおそらく正当な理由のために、ほとんどのゲームコンテンツが既に圧縮されたファイル内のみのパッケージの変更(にしようとしていない高に対するパッチを作成しますエントロピーまたは圧縮データはまったく機能しません)。


exeの各メソッドを個別にパッケージ化するとはどういう意味ですか。それは実用的ですか?
wolfdawn

@ArthurWulfWhiteはい。おそらく非常に多くの時間と労力を要するため、時間の価値のないインディーハウスの場合(本質的に独自のリンカーを作成する必要があります)-「パッチングテクノロジー」のみを扱う会社としては、努力するだけの価値があります。それはすべて、実行可能コードの大きさに依存します-Sacred 2をざっと見てみると、26mb(メインEXEの場合は8mb)でした。ただし、バイナリdiffはそれに近いものになる可能性があります-それでも、それをそこに置く価値があるという考えです(EXEは構造を利用するため、CABはEXEで適切に圧縮されることを知っています)。
ジョナサンディキンソン

それはとても興味深いです。私は帯域幅が今日のものであると思うので、ゲームのパッチサイズを最小化することは大きな問題ではありません。よく考え抜かれた興味深い答えに+1。
wolfdawn

ほとんどのゲームでは、個別の方法でパッチを当てることはそれほど実現できません。コンパイラーは、単純なコード変更でさえ、かなり劇的に異なる出力を持つことができます。自動インライン化の決定、シンボルテーブルのレイアウトの変更などが可能です。コードの変更により、内部API構造もしばしば変更されます。最適化により、コードエディタで表示されるものと比較して、関数の境界線がすでに曖昧になります。DRMシステムも水を大きく濁らせます。パッチシステムは、大規模な置換またはバイナリdiffを使用し、それらを圧縮します。あなたが提案するものはどれも、実世界で出荷するにはもろくて単純すぎます。
ショーンミドルディッチ

2
@SeanMiddleditch私はそれが可能であることを証明するためだけにそれをするつもりです:)。
ジョナサンディキンソン

15

ゲームの実行可能コードは常に実行可能ファイルだけに存在するわけではなく、多くの場合、いくつかの動的ライブラリ(ゲーム、グラフィックス、サウンドエンジンなど)、実際の実行可能ファイル、およびさまざまな目的のスクリプトに分割されます。

パッチは、これらのすべての変更を保証することなく、これらのパーツのいずれか1つの問題を修正できます。

すべての変更されたファイルを置き換えることとは異なるアプローチは、単にそれらに対してバイナリ差分を行い、再配布される実際の差分のみをパックすることです。

(もちろん、ユーザーが変更しないことを保証できるファイルでのみ機能します。)


2
これを例として挙げることができます:daemonology.net/bsdiff
wolfdawn

2
良い実用的な答え。+1
wolfdawn

2

通常、サードパーティのバイナリdiffシステムを使用して、ゲームデータにパッチを配布します。実行可能ファイルは通常、十分に小さく、完全に分散されます。

最近のほとんどのゲームには、数百メガのゲームデータ(主にテクスチャ、モデル、レベルデータなど)があります。これらには頻繁にパッチを適用する必要があります。私の知る限り、出版社は通常これを行うための標準的な独自の方法を持っています。

言うまでもなく、オープンソースの例があります。一部のLinuxディストリビューション(Fedora?)は、パッチにバイナリdiffを使用しています。それらを調査し、ソースコードまたはドキュメントを読むことができます。


-1

最新のdiffアルゴリズムでは、2つのバイナリに共通するバイトシーケンスを効率的に見つけることができます。驚くことではありませんが、考えてみてください。ファイル圧縮も、同一のバイトシーケンスを見つけることに依存しています。

同一のバイトシーケンスのリストを取得したら、古いオフセットと新しいオフセット、長さ、そしてもちろんまったく新しいものを送信するだけです。受信側では、簡単なアセンブリになります。古いファイルから保持する必要があるビットをコピーし、新しいビットを入力します。

リンカがファイル内のすべての関数のオフセットをリストするMAPファイルを吐き出すことができる場合、パッチの作成はさらに簡単になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.