なでしこを明後日の方向に

日本語プログラム言語なでしこを応援しています

なでしこ1でバイナリデータを扱う

なでしこ1には「バイナリ取得」「バイナリ設定」「バイナリダンプ」の命令があります
その他に、通常は文字列に使用する命令がいくつか使用できます(主に「バイト」がつく命令)

バイナリデータを用意するには

ファイルを「開く」「ファイルストリーム読む」命令で返ってくる値がバイナリデータです。 変数に入れて使います。 また「確保」命令では00で初期化されたデータを用意できます

以後、バイナリデータはサンプルでは変数名を「bin」にしておきます。

「開く」命令

//なでしこ1 サンプル
bin=「{ランタイムパス}nadesiko.png」開く
binバイナリダンプ
それ言う  //→89,50,4E,47,0D,0A,1A,0A,00,00,00,0D,49,48,44,52…

「確保」命令

//サンプル
bin8確保
binバイナリダンプ
それ言う  //→00,00,00,00,00,00,00,00

「バイナリ取得」「バイナリ設定」命令

【名前】バイナリ取得 (ばいなりしゅとく)
【引数】{参照渡し}SのIをFで
【説明】バイナリデータSのIバイト目をFの形式(CHAR|CHAR*|INT|BYTE|WORD|DWORD)で取得する。

//サンプル
bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
bin1「INT」バイナリ取得
それ言う //→1196314761
HEX(それ)言う //→474E5089

バイナリ取得で最初のデータを取得する場合、1を指定します。0ではないです。

形式「INT」を指定すると4バイト分を数値にして取り出します。
バイナリの最初 89,50,4E,471196314761という数値になります。
16進数表記に直すHEX命令を使うと 474E5089 になります。 89,50,4E,47474E5089 のように逆になるのはリトルエンディアンというやつです。

Fの形式(CHAR|CHAR*|INT|BYTE|WORD|DWORD)

bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
bin1「INT」バイナリ取得。HEX(それ)表示 //→474E5089
bin1「DWORD」バイナリ取得。HEX(それ)表示 //→474E5089
bin1「WORD」バイナリ取得。HEX(それ)表示 //→5089
bin1「BYTE」バイナリ取得。HEX(それ)表示 //→89

INTは4バイト(符号あり)、DWORDも4バイト(符号なし)、WORDは2バイト、BYTEは1バイト分を数値として読み取って返します。

マイナスの数値を扱えるかどうか

//マイナスの数値をバイナリ設定し、すぐバイナリ取得する例
bin8確保
bin1-1「INT」バイナリ設定
binバイナリダンプして表示 //→FF,FF,FF,FF,00,00,00,00
bin1「INT」バイナリ取得。それ表示 //→-1
bin1「DWORD」バイナリ取得。それ表示 //→4294967295
bin1「WORD」バイナリ取得。それ表示 //→65535
bin1「BYTE」バイナリ取得。それ表示 //→255

マイナスの数値を「INT」で設定するとFF,FF,FF,FFのようになります。(詳しくは「補数」で検索)
マイナスを扱える型は「INT」のみのようです。

その他の型

ヘルプによると形式(CHAR|CHAR*|INT|BYTE|WORD|DWORD)以外にも対応しているようです
INTでマイナスの数値になるのがイヤならばUINT(符号なし4バイト)も使えます。

なお4バイトより大きい数値を取ってきた場合、いくつかの命令に対応していません。

bin8確保
bin1$77777777「UINT」バイナリ設定
bin5$77777777「UINT」バイナリ設定
binバイナリダンプして表示 //→77,77,77,77,77,77,77,77

bin1「INT64」バイナリ取得。それ表示 //→8.60848056773112E18
bin1「INT64」バイナリ取得。HEX(それ)表示 //→77777777 (4バイト分だけ)

INT64は8バイト整数です。 整数で16桁くらいになると「表示」命令は指数になります。
HEXは下4バイトしか変換しません。AND、OR、XORなんかも下4バイトのみ。

バイナリ設定

1バイトだけ書き換えるときは「BYTE」か「CHAR」でバイナリ設定します。

bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
$FFbin1「BYTE」バイナリ設定。
$FFbin2「CHAR」バイナリ設定。
binバイナリダンプして表示 //→FF,FF,4E,47,0D,0A,1A,0A,…

サンプルでは変数の内容が書き換わるだけなので元のファイルには影響ありません。
保存すると変更したファイルを保存できます。

INTで書き込みした場合の注意点

INTでバイナリ設定した場合、必ず4バイト分上書きになります。
たとえば$FFを「INT」でバイナリ設定すると、$000000FFを書き込みします。

bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
$FFbin1「INT」バイナリ設定。 //$000000FFを書き込み
binバイナリダンプして表示 //→FF,00,00,00,0D,0A,1A,0A,

$AABBCCをINTで設定した場合、CC BB AA 00 で上書きになります。 リトルエンディアンというやつです。

bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
$AABBCCbin1「INT」バイナリ設定。 //$00AABBCCを書き込み
binバイナリダンプして表示 //→CC,BB,AA,00,0D,0A,1A,0A,…

任意の16進数で書き換える

最初の3バイト分を AA BB CCで上書きしたい場合の書き方は以下のような感じです。

bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
「{\$AA,$BB,$CC}」bin1「CHAR*」バイナリ設定
binバイナリダンプして表示//→AA,BB,CC,47,0D,0A,1A,0A…

「{\$AA}」はなでしこのマニュアル「アスキーコードの直接埋め込み」の記法です
以下の書き方は同じ結果が得られます

「{\$AA,$BB,$CC}」bin1「CHAR*」バイナリ設定
「{\$AA}{\$BB}{\$CC}」bin1「CHAR*」バイナリ設定
CHR($AA) & CHR($BB) & CHR($CC)bin1「CHAR*」バイナリ設定

文字列処理命令も使える

バイナリデータには「バイト検索」や「区切る」など文字列処理命令の多くが使えます。

bin=「{ランタイムパス}nadesiko.png」開く //89,50,4E,47,0D,0A,1A,0A,…
binバイト数言う //→9865
bin「{\$0A}」何バイト目。それ言う //→6
bin7から「{\$0A}」バイト検索。それ言う //→8
LEFTB(bin,5)バイナリダンプして言う //→89,50,4E,47,0D
bin5「{\$AA,$BB,$CC}」バイト挿入 //→89,50,4E,47,AA,BB,CC,0D,0A,1A,0A,…

bin「{\$0D}」区切る
反復
  対象バイナリダンプして表示
//→89,50,4E,47
//→0A,1A,0A,00,00,00
//→49,48,44,52,00,00,00,8A,00,00,00,64,08,02,00,00

区切るはゲームのシナリオデータなんかを取り出すときに使えるかも。