UPSフォーマット仕様書
現在は、UPSを設計したbyuu氏による新しいパッチフォーマット「BPS」が提案されており、新たにUPSに対応する必要性は低いです。
UPSはIPSに代わって提案されたパッチファイル形式です*1。tsukuyomiを用いることでパッチの作成と適用がおこなえます。ソースコード中の nall/ups.hpp がUPSパッチの核のようですが、そのフォーマットは実際のところどうなっているのでしょうか。
なお、IPSフォーマット仕様書も別に用意してあります。参考までに。
ファイル構造
フォーラムの書き込みを示します。
/***** * file format: ***** * [4] signature ("UPS1") * [V] X file size * [V] Y file size * [?] { * [V] relative difference offset * [?] X ^ Y * [1] 0x00 terminator * } * [4] X file crc32 * [4] Y file crc32 * [4] Z file crc32 *****/
ファイルサイズとそのフィールドの説明が書かれています。数値表現はリトルエンディアンです。
Vは標準MIDIファイルにあるような可変長データであることを意味していて、最上位ビットに0が現れるまではデータが続きます。いくつか例を示します。
.db $00 = $00 .db $7f = $7f .db $80 $01 = $80 .db $ff $01 = $ff .db $80 $02 = $100 .db $80 $80 $01 = $4000
ヘッダ以降は、ファイル先頭から順に差分データが並べられます。IPSと違って、前のパッチ位置から相対的に位置を求めることに注意してください。
基本的にはXが差分適用前ファイル、Yが差分適用後ファイルを意味します。しかし、XとYの排他的論理和で差分を表すというアルゴリズムの性質上、同一のパッチをYに適用してXを作成することもできます。なお、XとYのサイズが異なり、一方にしかデータが現れない場合、他方は0であるものとします。言い換えれば、一方にあるデータがそのまま記録されるということです。
Z fileというのは、最後のZ file crc32を除いたupsファイル全体を意味します。これにより、パッチファイルそのものの破損も検出できます。
UPSの利点(と欠点)
以下、フォーラムからテキトーに抜粋した長所です。
- ファイル構造が単純で、誰でも簡単にパッチ処理が実装できる。
- 双方向にパッチ適用が可能。同一のパッチファイルがパッチ解除にも利用できる。
- 改変前ファイルと改変後ファイル、パッチのCRC32を記録するため、間違ったゲームへのパッチ適用を未然に防止可能。
- ファイルサイズにフォーマット上の制約はない。IPSの16MB上限を突破できる。
- Windows/Linux用のpatcherが存在、コアはISO C++9xで書かれている(移植性が高い)。
- 仕様、コード、あらゆるものはパブリックドメインで配布されている。
IPSにできてUPSにできないこととして、所定の領域を特定のバイトで埋めること(RLE)があります。IPSでは「ファイル先頭から1MBの領域をすべて00にする」というようなパッチも数バイトで表現できますが、UPSはこのような場合でも差分の大きさだけ容量を必要とします。考案者であるbyuu氏はこういった実装をしなかった理由を「ZIP、7-Zip等々のプログラムはよりよくファイルを圧縮するだろうから」と説明します。
如何に圧縮プログラムが利口でも、巨大な領域に対してはRLEの方がサイズを縮めるのではないかとも思います。しかし、上記の理由に加え、UPSの利点とされるパッチの双方向性を維持するためには、こうした実装をしなかったのは理にかなった判断だったのではないかと思います。UPSで扱われるであろう主なファイルのサイズを考えれば、多少容量が多かろうが少なかろうが大して問題にはならないでしょう。
UPSは差分表現の形式上、生成前と生成後のファイルが持つべきをデータ列を明確に決め打ちします。ハッシュを用いて間違いがないか検査できることもあり、そういう用途には非常に有効なのですが、逆に言えばIPSに比べて汎用性のあるパッチファイルを作るのが苦手とも言えるでしょう。