カテゴリー
IchigoJam

IchigoJamのメモリ内のバイナリデータをテキスト・プログラム化するツール

IchigoJamのBASICプログラム上のバイナリデータが占有するプログラム容量を低減するためのツールを作成しました。本ツールによるプログラム書式を「B15形式」として提案したいと思います。
現状、81バイト以上のバイナリやマシン語を含むプログラムの配布などに適していると思います。
なお、まだテストが不十分につき不具合があるかもしれません。

開発の背景:C言語をIchigoJam用にコンパイルする
10月10日の朝、C言語で書いたプログラムをコンパイルして IchigoJam に転送可能な形式に変換するプログラムがFacebookのIchigoJam FANグループに投稿されました。
C言語で書いたプログラムをIchigoJamに転送可能な形式に変換:
(Kunihiro AiharaさんによるFacebookのIchigoJam FANグループへの投稿)
これを触っていて気づいたことがあります。それは、POKEで書かれたマシン語のプログラムの方が、同じ機能を持つBASICプログラムよりもプログラム用メモリーを多く消費してしまう場合があることです。
そこで、マシン語のサイズが大きくなってしまった場合のPOKE書式プログラムや自作文字フォントデータなどのバイナリデータを効率よくプログラムに埋め込むツールが必要と考え、その暫定版を作成しました。
C言語開発環境の続き:Windows での利用方法
上記で投稿されたC言語からのマシン語変換(poke文への変換)ツールはMac用でした。私も同じコンパイラを使用することでWindowsのCygwin環境でも動作することを確認しました。その手順の概要を以下に記しておきます。
  1. Cygwinのインストール(既にインストールされている方はモジュールの追加)
    下記にアクセスし、お使いのOS(32ビットか64ビット)に合わせてsetup-x86.exe(32ビット)もしくはsetup-x86_64.exe(64ビット)を実行します。またインストール時の「Select Packeges」にて「Devel内のmake」と「Devel内のgit」、そして「Python内のPython」を選択します。
    http://cygwin.com/install.html

  2. GNU Tools for ARM Embedded Processorsのインストール
    下記からダウンロードしてインストールします。
    https://launchpad.net/gcc-arm-embedded/4.9

  3. CygwinのPATHにBINを追加する
    以下のコマンドでパスを追加します。Windowsのディレクトリに「スペース文字」が含まれています。なぜか「\(スペース)」ではうまく動かなかったので「"」で囲いました。

    $ cat >> ~/.bashrc
    PATH="$PATH":"/cygdrive/c/Program Files/GNU Tools ARM Embedded/4.9 2015q3/bin"
    (Ctrl+Dで終了)

  4. Gitからダウンロードする

    $ git clone https://github.com/rohiniku/IchigoJam_bin2poke.git

  5. テストプログラムをコンパイルする

    $ cd IchigoJam_bin2poke
    $ cp usr_sample.c test.c
    $ make test.bas
    $ cat test.bas

  6. 表示された「test.bas」をIchigoJamへ転送し、usr関数で実行する
    100 poke #700,#40,#00,#40,#42,#00,#04,#00,#14
    110 poke #708,#70,#47
    ?usr(#700,15)
なお、Pythonの部分(オブジェクトをpoke形式に変換するプログラム)については、プラットフォームにほとんど依存しませんが、使用するコンパイラによって生成されるバイナリデータが異なりますのでご注意ください。
今日の本題:メモリ内のデータをテキスト化する
前置きが長くなりましたが、このように転送したプログラムは、すぐに長くなってしまいます。16進数を文字として表示するのが無駄だからです。そこで、16進数では無くテキスト形式で記憶するようにしてみました。この方法でプログラム部分の容量を3分の一に低減することが出来ます(16バイトを1行に記録する条件・デコーダ含まず・従来78バイト⇒本方式26バイト)。
以下が実行画面です。

実行して、「3」を入力するとダンプリストが表示されます。「1」を押すとプログラムに変換します。ここでは画面に表示するだけです。図中の行番号11~14が出力されたテキスト形式のプログラムですので、シリアル出力された内容を保存しておきます。ここではB15形式と呼ぶことにします。
次に、このB15形式プログラムに行番号96~99の「B15 Decoder」を追加します。この形で保存しておけば、プログラム形式なので配布が簡単です。プログラムに要するメモリ容量も減らすことが出来ます。(ただし、行番号96~99の追加による増加があるので、短いバイナリプログラムには適しません。)
エンコーダ/デコーダのプログラム
rem メモリ内バイナリデータのプログラム出力(Enc)/書込み(Dec)ツール
rem     Enc:シリアルで転送可能なテキスト文字列(B15形式)に変換
rem     Dec:テキスト文字列(B15形式)をメモリーに展開
rem             Copyright (c) 2015 Wataru KUNINO
rem             https://bokunimo.net/ichigojam/
1 ?"B15 Enc/Decoder"
100 'INIT
110 A=#700:'ADR FROM
120 E=#73F:'ADR TO
130 S=11:'P NUM
140 D=1:'P STEP
150 ?"1=enc 2=dec 3=dump 4=uDec 5=end>";:input I:goto 100*I+100
200 'Enc
210 C=0:F=0:forI=0to15:[I]=peek(A+I):M=[I]>>7<<I:C=C|M:[I]=[I]&127:next:?S;" '";chr$((C&15)+48);chr$(((C>>4)&15)+48);chr$(((C>>8)&15)+48);chr$(((C>>12)&15)+48);
220 forI=0to15:if[I]>79let[I],[I]+96elselet[I],[I]+48
230 if[I]=127let[I],162
240 F=F+[I]:letF,F&15:?chr$([I]);:next:A=A+16:S=S+D:?chr$(F+48):ifA<Egoto200elseend
300 'Dec
310 P=#C08:'Pnt
320 ifpeek(P)<>39letP,P+1:ifP<#C7Fgoto3
20elseend
330 forI=0to3:P=P+1:[I]=peek(P)-48:next:F=0:forI=0to15:P=P+1:C=peek(P):F=F+C:letF,F&15
340 ifC>175letC,C-96elseifC=162letC,127elseletC,C-48
350 M=([I/4]>>(I%4))&1:C=C|(M<<7):?hex$(C,2);:pokeA,C:A=A+1:next:?" ";F-peek(P+1)-48:P=P+2:ifA<Egoto320elseend
400 'Dump
410 forI=0to15:?hex$(peek(A),2);:A=A+1:next:?:ifA<Egoto410:else:end
500 end
デコーダのみのプログラム
rem プログラムをメモリへ書込む(Dec)ツール
rem     Dec:テキスト文字列(B15形式)をメモリーに展開
rem             Copyright (c) 2015 Wataru KUNINO
rem             https://bokunimo.net/ichigojam/
1 ?"B15 Decoder"
96 A=#700:E=#73F:P=#C08
97 ifpeek(P)<>39letP,P+1:goto97
98 forI=0to3:P=P+1:[I]=peek(P)-48:next:forI=0to15:P=P+1:C=peek(P):ifC>175letC,C-96elseifC=162letC,127elseletC,C-48
99 M=[I/4]>>I%4&1:C=C|M<<7:pokeA,C:A=A+1:next:P=P+2:ifA<Egoto97elseend
今後の課題と標準化
今回のエンコーダ(プログラム出力)はBASICで書きました。エンコーダ、デコーダの両方を作るのに一つのプラットフォームの方がスムーズだからと、どちらにしてもIchigoJam BASIC用のツールが必要と思ったからです。
まだデコーダのプログラムが長いです。もう少しフォーマットを見直して短くする必要があるでしょう。また、テストも不十分です。BASICの容量の都合上、各種のチェックを省いているので、色んな問題があるかもしれません。
順番としては、フォーマットが決まってからPythonで書いて、利便性が向上させるようなステップになります。
ところで、IchigoJam用のこういったフォーマットって、すでにあるのでしょうか。なければ、このB15形式を中心に改良したものをIchigoJam標準として貢献できれば幸いです。
プログラム用メモリ占有量の性能比較
本プログラムによるプログラム用メモリの低減効果は以下の通りです。従来方法はPOKEで16進数を使用した場合です。最新版の IchigoJam_bin2pokeでは10進数出力にも対応しており、もう少し容量削減することが可能です。
16バイトのバイナリデータを保持した場合の容量
従来方法(poke・#16進数書式)
データ容量:78バイト 展開用プログラム容量:0バイト(データに含まれる)
提案方法(B15 Decoder・B15形式)
データ容量:26バイト 展開用プログラム容量:262バイト
以上の結果から、81バイト以上のバイナリデータについては、本手法を用いることで小容量化が図れます。(80バイト以下の場合はpoke書式の方が小容量。)
補足(C言語float)

この方法ではC言語コンパイラでfloatやdoubleが使えないようです。実機で動かすと暴走してしまいます。浮動小数演算部は各オブジェクトのリンク時に生成されるらしく、オブジェクト単体で使う場合は未実装のままだそうです。(Kunihiro Aiharaさんによる情報)
補足(IchigoJam相対アドレスをC言語側で受け取る) [10/12 追加]
当ページを下記で紹介していただきました。
また、IchigoJam BASIC に相対アドレスをC言語側で受けれる仕組みが加わり、用途が大幅に拡大しました。(Version 1.1以降)
相対アドレスの割り当ては下記の情報も参照ください。
ライセンスについて
当ブログ上の情報およびプログラムはCC BYライセンスとします。自由に複製と改変が可能ですが、プログラムの再配布時は著作権表示が必要です。書式についてもCC BYといたします。権利表示は合理的であれば簡略化してもかまいません。(一例として「(C)2015 国野亘」や「(C)WataruKUNINO」といった表示と補足説明書やREADME、ウェブサイトなどの併用)。なお、Kunihiro Aiharaさんのプログラム IchigoJam_bin2pokeは2015/10/11現在Apache License Ver 2.0です。再使用時は最新のライセンス情報を確認してください。


ボクにもわかるIchigoJam用マイコンボード
 - 
Chinese (Simplified)
 - 
zh-CN
Chinese (Traditional)
 - 
zh-TW
English
 - 
en
French
 - 
fr
German
 - 
de
Italian
 - 
it
Japanese
 - 
ja
Korean
 - 
ko
Russian
 - 
ru
Spanish
 - 
es