HSPでバイナリを扱うときの注意点

Hot Soup Processor(HSP)上でバイナリデータを扱うときは注意を要する。基本的にバイナリデータは文字列型の変数に格納するのだが、文字列操作命令や関数ではヌル文字(0x00)を文字列の最後として処理を停止してしまうからだ。

ここでは、私が中学生のときによくハマったHSPの落とし穴、バイナリの扱い方について個人の体験をもとに具体的に項目を挙げる。(公式リファレンスには特にこのことに関する注意書きがないため)

なお、この記事ではHot Soup Processor 3.5をもとに説明する。

具体的に言うと、


バイナリに対してstrmidstrlenを使わない。ノートパッド命令も使わない。

先程言ったように0x00がデータに出現すると文字列の終わりをそこだと勝手に認識する。普通の文字列だと都合がいいがバイナリでは(恐らく)0x00が頻発するためよろしくない。それぞれ別の方法を使う必要がある。


strmid(データ一部切り取り)したいとき

repeatloop内でpokepeekを組み合わせるのが最も簡単だろう。

//binsrcが元のバイナリ列、

//bincutが一部取り出ししたデータの格納先、
//cutsizeが取り出すサイズ、
//offsetが取り出し開始位置とする。

repeat cutsize
poke bincut , cnt , peek(binsrc , offset + cnt)
loop

また、上級者向けだがdupptrでポインタにオフセットを付けて変数を作成するという方法もある。この場合、もとの作成した変数を書き換えると元の変数も書き換わるので扱い方には気をつけなければならず、ポインタを扱うのでアクセス違反を起こす危険もあるが、先はどの方法よりもずっと高速だ。

//binsrcが元のバイナリ列、

//bincutが一部取り出ししたデータの格納先、
//cutsizeが取り出すサイズ、
//offsetが取り出し開始位置とする。

dupptr bincut , varptr(binsrc) + offset , cutsize , 2

...これはおすすめはしない。


strlen(データの全長を測る)したいとき

strlenも、0x00を文字列の最後だと認識するので、この関数ではバイナリの長さを正しく測ることができない。

この記事を読んでいるあなたはどのような場面でバイナリを使いたいのだろうか?外部のバイナリデータを読み取りたいのだろうか、それとも変数のデータとかからバイナリを生成したいのだろうか?

外部ファイルのバイナリデータの大きさを読むのであれば、exist命令の機能でファイルサイズを取得できる。それを使えばよい。

exist "binary file name"

binsize = strsize

変数のデータからバイナリを作成してそのサイズを知りたい?????? は????????

サイズの分かっている変数から生成したならそこからサイズを測ればいいのでは????????????

わからないひとへ : int型は4バイト、double型は8バイト、ラベル型は4バイトだからそこから計算できるよ。


データをセーブしたりしたいとき

まさかnotesaveは使わないよね??? bsavebloadを使えばいいことは分かるのだが、このうちbsave命令は気をつけなければならないことがある。公式リファレンスを見てみよう。


p2のバッファサイズを省略するかマイナス値を指定すると、自動的に変数バッファのサイズが設定されます。


おわかりいただけただろうか。この仕様だと、変数のサイズが100バイトで、バイナリの長さが50バイトだった場合、末尾には自動的に0x00で埋められる可能性があるのだ。(多分バージョンによって挙動が違うのでなんともいえない。)

この場合は、別の変数を使って把握しておいたバイナリの全長をbsaveのパラメータに指定。

bsave "binary file name" , binary , binary_size , 0 


けつろん

文字列操作命令・関数とバイナリ操作命令・関数をごっちゃにするな。リファレンス見ろ。