基本的には、データ列を順に見て行って、以前と同じパターンが現れたらその部分をコピーする、というやり方です。たとえば、
番地 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
データ |
A |
B |
C |
D |
E |
F |
G |
A |
B |
C |
D |
E |
H |
I |
ABCDEFG[copy-7,5]HI
のように表現できます。また、
番地 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
データ |
A |
B |
C |
D |
E |
D |
E |
D |
E |
D |
E |
F |
G |
ABCDE[copy-2,6]FG
と表現できます。この [copy-x,y] というのをうまい具合に短いコードで表現すればデータを圧縮することができます。
データは、基本的にバイナリデータをそのまま書いていくのですが、データ中に以前のデータからコピー可能なパターンがあった場合、以下のようなコードに変換されます。
ショートコピーコード |
0E7H xx |
ロングコピーコード |
0F7H yy zz |
(コピーするバイト数−1)*32+戻るバイト数−1
です。この形式では最大32バイト戻ることができ、最大8バイトコピー可能です。
ロングコピーコードは3バイトです。まず16進数の 0F7H があり、そのあとの2バイト値 yy zz の値は、
(コピーするバイト数−1)*1024+戻るバイト数−1
です。この形式では最大1024バイト戻ることができ、最大64バイトコピーできます。なお、この yy zz のバイト順は「モトローラ方式」で、yy が上位です。
ところで、データ列中に始めから 0E7H とか 0F7H とかいったデータが含まれる場合も当然あり得ます。それをコピーコードと誤認してはいけないので、データ列中に 0E7H、0F7H が含まれている場合、
0E7H → 0E7H 000H 0F7H → 0F7H 000H
と変換します。圧縮データの展開時には、0E7H または 0F7H に続く1バイトが0だった場合、それはコピーコードではなく 0E7H、0F7H そのものを表すと解釈します。
データ中に 0E7H、0F7H が多く含まれている場合、かえってデータが大きくなる可能性もあるわけですが、一応出現頻度の低い値、ということでこの値を選びました。実際今まで私が作ったH8用プログラムで調べた限りでは出現頻度はかなり低いです。
H8の命令コードとしてみると 0E7H は AND.B #xx,R7H、0F7H は MOV.B #xx,R7H です。R7はスタックポインタですから、普通のプログラムではこんな命令を実行することはまずありえません。純粋なデータとしてみた場合にはなんともいえませんが、経験的にあまり出てこないデータだと思います。
圧縮を行うには H8COMP.COM というプログラムをMSX−DOS上で実行します。H8COMP.COM は以下のような形式のファイルを出力します。なお、H8COMP.COM が出力するファイルの拡張子は .H8C です。
オフセット |
意味 |
内容 |
0〜3 |
ファイルID |
文字列"H8C\0" |
4〜7 |
展開後のデータのサイズ |
4バイト整数(下位バイトが先の、インテル方式) |
8以降 |
データ本体 |
圧縮されたデータ本体 |