OSECPU-ASKA入門 #0005
(0) はじめに
- 以下の記事はver.0.49のWindows版を前提にしています。他の版を使っている場合は適宜読み替えてください。
- たとえば osecpu049d.zip とかのことです
(1) drawString
- junkApi_drawString(mode, xsiz, ysiz, x0, y0, color, string); :
- グラフィクス描画用のウィンドウの中に文字を書きます。modeは毎度の数値で、drawPointなどと同じです。
- xsizやysizは1以上の整数を指定します。両方が1のとき、1文字は8x16ピクセルです。
- x0とy0は1文字目の左上の座標を指定します。
- (例)
#include "osecpu_ask.h"
junkApi_drawString(4, 1, 1, 0, 0, 7, 'abcd');
junkApi_drawString(4, 8, 8, 0, 20, 7, 'abcd');
- 現状で表示できるのはASCIIキャラクタだけです。'\n'や'\t'などの制御文字は指定できません。
- 拡大するとぎざぎざが非常に目立ちますが、それは仕様です。美しいフォントなどを提供する予定は今のところありません。
- どうしてもきれいに描きたい場合は、アプリが自前で描画すればよい、というスタンスです。
(2) リリースモード
- OSECPUアプリは小ささが自慢と言うか取り柄なのですが、ここまではそのための話をほとんどしてきませんでした。
- 最初のpage0036の(1)で紹介したアプリのビルド方法は、実はデバッグモードで、全然小さくならない、つまらないものでした。・・・まあでもそれが一番簡単なビルド方法なのでありますが。
- しかしもうデバッグも終了して、リリースするだけとなれば、過剰なデバッグ情報はただの無駄です。必要最低限にさせましょう。
- 註:すべてのデバッグ情報を簡単に取り除く手段は用意していません。ある程度の規模になれば、絶対にバグがないプログラムなんて、そうそう作れないと思うのです。だから保険のためにも、最低限度のデバッグ情報は残しています。
- さらに小さくしたい場合は、OSECPU標準のパッカーを使います。
prompt>osectols tool:appack flags:2 in:app0038.ose out:app0038.tk5
- ただしこれをやる場合は、ext_tolsにあるbim2binとt5lzmaをosectolsと同じフォルダにコピーしておく必要があります。
- そうすると例えばこういう表示が出ます。
org:34 tk5:48
- これはパッキングしたほうが大きくなってしまったことを意味してます。もともとのオリジナルは34バイトで、パック版は48バイトですよ、と。この場合はパックなんてしないほうがいいので、このtk5ファイルは捨てて、app0038.oseをそのままリリースします。
- しかしアプリによっては、tk5のほうが小さくなることがあります。そんなときは、oseのほうを捨てて、.tk5を.oseにリネームしちゃってください。
(3) 複数の関数を作る例
(4) sleepのmodeについて
- page0039の(1)でsleepを紹介しましたが、その際にmodeの使い方を説明しませんでした。今回はそれを説明します。
- modeはビットごとに意味を持っています。したがって以下を加算して組み合わせることができます。
- 1: グラフィックス画面の自動全画面flushを抑制する。
- これを指定しなければ、sleepが呼ばれるたびに全画面flushが行われるので、アプリがflush処理を意識する必要はほとんどなくなります。その代わり負荷は増えます。
- とはいえ、現状ではまだ説明してないのでflushって何?状態ですよね。そうです、分からなくても構わないので、この1を指定しないようにしてください。それで万事解決です。
- しいて言えば、前回のsleepから一切画面を書き換えていないときには、この指定をしてもいいです。そうすればCPU負荷が下がってCPUにやさしいアプリになれます。まあでもこれを気にして処理が複雑になるくらいなら、何も考えずに0をしてしておく方がずっといいです。
- 2: sleepし終わった時にinkeyバッファをチェックし、もし空であればもう一度指定された時間のsleepを実行する。
- つまりこれを指定すれば、inkeyバッファが空の状態で戻ってくることはありません。
(5) inkeyのmodeについて
- page0039の(5)でinkeyを紹介しましたが、その際にmodeの使い方を説明しませんでした。今回はそれを説明します。
- modeはビットごとに意味を持っています。したがって以下を加算して組み合わせることができます。
- とはいえ、現状では1しかないので組み合わせようがないですが。
- 1: peekモードにする。
- これを指定すると、inkeyバッファの先頭のものを取ってはきますが、バッファから削除しません。たぶんあまり使わない機能だとは思います。
(6) グラフィックスでpage0044の(4)をやってみよう!
#include "osecpu_ask.h"
#define L_drawDec LOCAL(0)
LOCALLABELS(1);
#define drawDec(mode, xsiz, ysiz, x1, y0, col, i) R30=mode; R31=xsiz; R32=ysiz; R33=x1; R34=y0; R35=col; R36=i; CALL(L_drawDec)
#define XSIZ 16
#define YSIZ 16
// main
do {
SInt32 i:R00;
for (i = 111; i != -100; i--) {
junkApi_fillRect(0, 8*XSIZ*3, 16*YSIZ, 0, 0, 0x000000);
drawDec(4, XSIZ, YSIZ, 8*XSIZ*3, 0, 7, i); // (x, y)の指定が左上ではなくて右上なところに注意.
junkApi_sleep(0, 1000);
}
}
junkApi_sleep(0, -1);
beginFunc(L_drawDec);
do {
SInt32 mode:R08, xsiz:R02, ysiz:R09, x1:R01, y0:R0A, col:R0B, i:R00, flag:R03, ii:R04;
mode = R30; xsiz = R31; ysiz = R32; x1 = R33; y0 = R34; col = R35; i = R36;
flag = 0;
if (i < 0) {
flag = -1;
i *= -1;
}
do {
ii = (i % 10) + '0';
i /= 10;
x1 -= xsiz * 8;
junkApi_drawChar(mode, xsiz, ysiz, x1, y0, col, ii);
if (i > 0) continue;
}
if (flag != 0) {
x1 -= xsiz * 8;
junkApi_drawChar(mode, xsiz, ysiz, x1, y0, col, '-');
}
}
endFunc();
(7) for構文 #1
- まず、 for (;;) { ... } という構文があります。これは無限ループで、breakかgotoでなければ抜け出せません。
- 次に for (;0;) { ... } という構文があります。これは1回しか実行しないループ(?)で、主に関数などの変数スコープを限定するために使われます。・・・ for (;0;) と書くのはみっともないしよく忘れるので、 do で代用できるようになっています。
- do は1回しか実行しない、スコープ制限くらいにしか役に立たないと書きましたが、少々裏技も可能で、まずbreakすることができます。breakすればdoの中かっこ閉じのところまで処理を飛ばすことができます。
- do の裏技その2。continueができるのです。上記の(6)でもやっています。continueすれば、もちろん do のところに戻るのでループができます。(6)の使い方はまさにdo-whileですね。
こめんと欄