* a23_useSelfMade #4
-(by [[K]], 2023.01.31)
--親ページ: [[a23_useSelfMade]]
** 2023.01.31 Tue #1
-自分で作ったものを今後も使っていけそうか?
--というのがこの一連の記事の趣旨なので、定期的に確認しようと思います。
-''[1ec, ecrun, ecc0]'' → 〇
-easy-Cを成り立たせているツール群。
-これはかなり便利なので(ほぼ常に立ち上げっぱなしになっている)、今後も使い続けるような気がします。
-ただ下請けになっているecrunやecc0を別々の実行ファイルにしておく必要はもはやありません(現在の構造は、試行錯誤の成り行きでそうなただけ)。だから全部1ecに統合するべきだとは思います。きっとそのほうが扱いやすそうです。
-''[HL-9b]'' → 〇
-たった740行で書かれたインタプリタ。だけどeasy-Cのプログラムが結構動く。
-プログラムの実行に際してgccとかを使うわけじゃないので、中間ファイルを生成することはなく、だからRAMディスクがなくてもHDDやSSDの寿命を削る心配はありません。
-最近は再起動後にRAMディスクを設定するのが面倒になってきて、簡単なことはこっちでやるようになってきました。
-このHL-9bと上記の1ecを統合する(コンパイル実行かインタプリタ実行かを簡単に選べる)といいのかもしれません。・・・うーん、欲が出てしまった。いやだって、2つを立ち上げっぱなしにするのはちょっと面倒ですし・・・。
(案)
>pr 1+2*3 → こんなふうに普通に書いたら、インタプリタ実行
7
>!pr 1+2*3 → こんなふうに!を頭に付けたらgccでコンパイルして実行
7
-後述のacl1ライブラリに、AEc_exec()っていう関数を作って、system()関数みたいに使えるようにしたら、実は便利かもしれない??
-あとHL-9bはCtrl-Cに対応してなくて、これやるとインタプリタごと強制終了してしまうので、そこも改善の余地があります。
-''[acl1]'' → 〇
-自分用のグラフィックライブラリ。最近はMML演奏もサポート。
-今のところこれを使わなくなる未来はちょっと考えられない・・・。非常に便利。特にeasy-Cと組み合わせると便利です。
-''[自作スタートアップ、自作リンカスクリプト]'' → 〇
-まだ落ち着いていなくて開発途上だけど、これがあれば簡単に極小サイズの実行ファイルが作れるので、もうずっと使い続けることになりそうです。
-''[雑多なミニアプリ]'' → △
-この中には使わなくなるものが結構ありそうだけど、デモとかには使うかもしれません。
-でもこういうのを作っていかないと、言語やツールの価値も限界もわからないので、作らないわけにはいかないです。
~
** 2023.02.01 Wed #1
-すごく小さな実行ファイルを作るための手順(Windows用):
-[1]まず適当なC言語のソースコードを用意します。これを hello.c とします。
#include <stdio.h>
int main()
{
puts("hello, wolrd");
return 0;
}
-[2]次に MinGW 5.1.6 を c:\mingw516 にインストールします。インストールした後にパスを通す作業は不要です。MinGW 5.1.6 のインストーラーはここにあります。
--https://essen.osask.jp/files/MinGW516.exe [理由はよくわからないのですが、新しいタブで開くにしないとダウンロードできない?]
--https://essen.osask.jp/files/MinGW516.exe
-[3]次にmstartup.cとして以下を用意します。
#include <stdlib.h>
int __getmainargs(int *argc, char ***argv, char ***env, int doWildCard, void *);
int mmain(int argc, char **argv);
void mainCRTStartup()
{
int argc, startupinfo[100/4 /* でもたぶん68バイトしか使ってない */];
char **argv, **env;
__getmainargs(&argc, &argv, &env, 0, startupinfo);
exit(mmain(argc, argv));
}
-[4]リンカスクリプトとして、以下をldscript.txtとして保存します。
OUTPUT_FORMAT(pei-i386)
SECTIONS
{
. = SIZEOF_HEADERS;
. = ALIGN(__section_alignment__);
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :
{
*(.text)
*(SORT(.text$*))
*(.rdata)
*(SORT(.rdata$*))
}
.idata BLOCK(__section_alignment__) :
{
SORT(*)(.idata$2)
SORT(*)(.idata$3)
/* These zeroes mark the end of the import list. */
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
SORT(*)(.idata$4)
SORT(*)(.idata$5)
SORT(*)(.idata$6)
SORT(*)(.idata$7)
__data_start__ = . ;
*(.data)
*(.data2)
*(SORT(.data$*))
}
.bss BLOCK(__section_alignment__) :
{
__bss_start__ = . ;
*(.bss)
*(COMMON)
__bss_end__ = . ;
}
}
-[5]最後に以下のバッチファイルを作ります。 mcc.bat ということにします(長い行があるので、行末に「^」をつけて行をつないでいます)。
c:\mingw516\bin\gcc -m32 -Os mstartup.c -c -o mstartup.obj
c:\mingw516\bin\gcc -m32 -Os %1.c -c -o %1.obj -Dmain=mmain
c:\mingw516\bin\ld -T ldscript.txt -o %1.exe -Bdynamic -s mstartup.obj %1.obj -Bdynamic -Lc:/mingw516/bin/../lib/gcc/mingw32/3.4.5 ^
-Lc:/mingw516/bin/../lib/gcc -Lc:/mingw516/bin/../lib/gcc/mingw32/3.4.5/../../../../mingw32/lib ^
-Lc:/mingw516/bin/../lib/gcc/mingw32/3.4.5/../../.. -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 ^
-lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt
-[6]これで、以下のようにすると、 hello.c から hello.exe が作られるはずです。
prompt>mcc hello
-このhello.exeは1.5KBで、その内訳はヘッダ512バイト、.textのイメージデータが512バイト、.idataのイメージが512バイトになっています。
~
-[Q]どうやってこの結論にたどり着いたのか?
-[A]なんか適当に調べてみたら mainCRTStartup が真のエントリポイントらしいことがわかりました。それでスタートアップ処理としてやらなければいけないことがいろいろあるんだろうなと思いましたが、C言語でよければ(つまりC++でなければ)、__getmainargs()を呼びさえすれば何とかなりそうだと分かりました。この謎の関数については、数年前に偶然に見つけていました。この関数は単にargcやargvのセットアップをしてくれるだけではなく、なんか必須の初期化処理か何かも一緒にやってくれているようです。だから引数を利用しないアプリでもやっておいた方がよさそうな感じです(たぶん)。
-[Q]mainをmmainに読み替えさせているようだけど、これは何のためにやっているのか?
-[A]gccはmainという関数を見つけると特別扱いするようで、なんか謎の初期化関数呼び出しを最初に勝手に挿入してきます。それがなくても動くみたいなので、そんなおせっかいを回避するために、mainをmmainに読み替えさせています。
-[Q]リンカスクリプトの書き方はどこで調べたの?
-[A]あーそれは調べていません。[[a23_usm003]]の「2023.01.29 Sun #1」の回に書いた通り、
prompt>gcc --verbose hello.c -O3 -o hello.exe
でデフォルトを出力させて、そこから「たぶんここはC言語では使わないだろう」と思うところを削っていって、それでちょっとだけ並べ替えて作りました(.rdataが.textの中に入るように、.dataが.idataの中に入るように)。
-[Q]ldのたくさんあるライブラリ指定リストはどうやって入手したの?
-[A]これも[[a23_usm003]]の「2023.01.29 Sun #1」の回に書いた通り、
prompt>gcc --verbose hello.c -O3 -o hello.exe
ってやって取得しました。collect2.exe(=ldの実体)への引数もこれで分かります。そのうちの.oファイルについては不要なもの(=消してみても動作に支障がなかったもの)は全部消してサイズを節約しています。
-[Q]なぜ.textの中に.rdataを入れるの?.dataをidataの中に入れる理由は?
-[A].exeファイルのヘッダサイズは512バイトでアラインされるので、ヘッダが513バイトになってしまえば、ヘッダだけで1024バイトが消費されることになります。そして合計3セクションに抑えることができれば、ヘッダは512バイト以下になるのです。そうすると標準的な.text, .rdata, .data, .bss, .idataの5セクション方式だと、多すぎることになってしまいます。それで、属性が似ているもの同士をまとめて、.text, .idata, .bssの3つに集約しています。
-[Q]なぜMinGWの最新版を使わずに、MinGW 5.1.6なんか使うの?
-[A]これは[[a23_usm003]]の「2023.01.29 Sun #2」の回に書いた通り、最近のバージョンでは-Osを付けてもあまり小さくならないと分かったためです。
-[Q]これ毎回やらないといけないの?
-[A]いえいえ。一度作ってしまえば、それ以降は、 prompt>mcc hl1 とかで、HL-1のコンパイルにも使えます。ちなみにHL-1は2.0KBになります(びっくり!)。
-[Q]これ本当に安全なの?削りすぎてうまく動かなくなる可能性は?
-[A]心配なら使わないのが一番です。普通にやりましょう。バグが出た時も、まずは問題を切り分けるために、普通にコンパイル&リンクして、そしてバグがなくなったのを確認してから mcc を使うようにします。うまくいかなくなったら、 mcc を使うのをやめましょう。
-[Q]ここまで攻めるのなら.textの中に.idataも入れたらいいんじゃないの?そしたらセクションイメージが1個になるから、1.0KBの.exeファイルが実現するよ!
-[A]なんと夢のあることを!うーん、writalbeの属性があっても実行権限をつけれるのかなあ。あとで試してみます。
--試しました。うーん、やはり.textはreadonlyじゃなきゃいけないし、そしたら.idataが書き込めなくなってしまうので、最小は1.5KBが限界のように思われます・・・。ひとまず諦めます。
~
** 2023.02.01 Wed #2
-osdev-jpでこんな話を教えてもらいました!
--デモシーンにようこそ!超低容量プログラミングで遊ぶカルチャー
--https://jp.ign.com/cedec-2016/6411/news/
-ここによると、「crinklerというPacker」がいいらしいです。UPXしか知らなかった私には、これはいい情報だ!
-キーワードが分かれば検索していけます。この記事も勉強になりそうです。
--crinklerとvisual studio 2017で400byteのexeを作る
--https://nanka.hateblo.jp/entry/2018/07/01/034341
-https://yosshin4004.github.io/ の中に「PC 4K Intro minify テクニック @ TDF2021(2021/12/12~)」がある。
~
** 2023.02.02 Thu #1
-小学生がMMLによる音楽再生に興味を持ったので、もっと簡単に音楽再生ができるように少し改造しました。
[改造前]
APlay *p = aOpenPlay(100000); // 適当な大きさのバッファ.
APlay_mml(p, 0, "CDEFEDCR EFGAGFER");
APlay_mml(p, 1, "R1R1 CDEFEDCR");
APlay_run(p);
[改造後]
PLAY "CDEFEDCR EFGAGFER"; PLAY1 "R1R1 CDEFEDCR"
→もはやワンライナーで十分。openもrunも自動でやる。
~
** 2023.02.02 Thu #2
-crinklerとvisual studio 2017で400byteのexeを作る
-https://nanka.hateblo.jp/entry/2018/07/01/034341
-これを見ても、Visual Studio のバージョンが違うせいなのか、全くわからず・・・。2022はアンインストールして、2017を探すべきなのか・・・。
-よしきめた。いったんこれはやめよう。ここから頑張ったとしてできるかどうかすらよくわからない。よくわからないものに時間をかけすぎるのはよくない。
~
** 2023.02.03 Fri #1
-以下は「ねこふんじゃった」を演奏するアプリです。
-nekofun.c[48行]
APlay *p = aOpenPlay16(100000);
// 1-
APlay_mml(p, 0, "T180 @1 r2.e-8d-8 r4g-4g-4e-8d-8 r4g-4g-4e-8d-8 r4g-4r4g-4");
APlay_mml(p, 1, "@1 r2.e-8d-8 r4<b-4b-4>e-8d-8 r4<b-4b-4>e-8d-8 r4<b-4r4b-4");
APlay_mml(p, 2, "@1 r2.r4 <g-4r4r2 g-4r4r2 g-4r4e-4r4");
// 5-
APlay_mml(p, 0, "r4f4f4e-8d-8 r4f4f4e-8d-8 r4f4f4e-8d-8 r4f4r4f4");
APlay_mml(p, 1, "r4>c-4c-4e-8d-8 r4c-4c-4e-8d-8 r4c-4c-4e-8d-8 r4c-4r4c-4");
APlay_mml(p, 2, "d-4r4r2 d-4r4r2 d-4r4r2 d-4r4e-4r4");
// 9-
APlay_mml(p, 0, "r4g-4g-4e-8d-8 r4g-4g-4e-8d-8 r4g-4g-4e-8d-8 r4g-4r4g-4");
APlay_mml(p, 1, "r4<b-4b-4>e-8d-8 r4<b-4b-4>e-8d-8 r4<b-4b-4>e-8d-8 r4<b-4r4b-4");
APlay_mml(p, 2, "g-4r4r2 >b-4r4r2 b-4r4r2 b-4r4>d-4r4");
// 13-
APlay_mml(p, 0, "r4f4f4e-8d-8 r4f4f4e-8d-8 r4f4f4e-8d-8 r4f4r4f4");
APlay_mml(p, 1, "r4>c-4c-4e-8d-8 r4c-4c-4e-8d-8 r4c-4c-4e-8d-8 r4c-4r4c-4");
APlay_mml(p, 2, "e-4r4r2 e-4r4r2 e-4r4r2 e-4r4d-4r4");
// 17-
APlay_mml(p, 0, "r4g-4g-4e-8d-8 r4g-4r4g-4 r4g-4r4g-4 r1");
APlay_mml(p, 1, "r4<b-4b-4>e-8d-8 r4<b-4r4b-4 r4b-4r4b-4 r1");
APlay_mml(p, 2, "<b-4r4r2 <g-4r4d-4r4 g-4r4d-4r4 g-4f4g-4g4");
// 21-
APlay_mml(p, 0, "r4f4f4e-8d-8 r4f4r4f4 r4f4r4f4 r1");
APlay_mml(p, 1, "r4>c-4c-4e-8d-8 r4c-4r4c-4 r4c-4r4c-4 r1");
APlay_mml(p, 2, "a-4r4r2 a-4r4d-4r4 a-4r4d-4r4 a-4g4a-4a4");
// 25-
APlay_mml(p, 0, "r4g-4g-4e-8d-8 r4g-4g-4e-8d-8 r4g-4g-4e-8d-8 r4g-4r4g-4");
APlay_mml(p, 1, "r4<b-4b-4>e-8d-8 r4<b-4b-4>e-8d-8 r4<b-4b-4>e-8d-8 r4<b-4r4b-4");
APlay_mml(p, 2, "b-4r4r2 g-4r4r2 g-4r4r2 g-4r4e-4r4");
// 29-
APlay_mml(p, 0, "r4f4f4e-8d-8 r4f4f4e-8d-8 r4f4f4e-8d-8 r4f4r4f4");
APlay_mml(p, 1, "r4>c-4c-4e-8d-8 r4c-4c-4e-8d-8 r4c-4c-4e-8d-8 r4c-4r4c-4");
APlay_mml(p, 2, "d-4r4r2 d-4r4r2 d-4r4r2 d-4r4e-4r4");
// 33-
APlay_mml(p, 0, "r4g-4g-4r4 g-4d-8d-8d4d-4 r4f4g-4r4");
APlay_mml(p, 1, "r4<b-4b-4r4 b-4>d-8d-8d4d-4 r4c-4<b-4r4");
APlay_mml(p, 2, "g-4r4r2 d-4r4r2 r4d-4<g-4r4");
APlay_run(p);
~
** 2023.02.03 Fri #2
-C言語入門としてprintf("hello, world\n");が定番ですが、これを小学生にやってもらうと「これの何が楽しいのか?」という顔をされます。画面に文字列を表示するだけなら、キータイプしたほうが早いので、それをわざわざプログラムでやってもちっとも面白くないためです。
-それならばと、aOpwnWin()して円や四角を書いて、グラフィックでお絵かきしてみます。これは楽しんでくれる場合が多いですが、しかしちょっとPCに詳しい小学生はこういいます。「これなら、ペイントで描いたほうが楽だよ。座標とか計算しなくていいし。」・・・うーん、くやしいけれど、これも彼らの言う通りなのです。
-変数を使わないくらい簡単で、だけど「わー、プログラミングってすごい、便利だー」思ってもらえるような、そんなプログラム例はないでしょうか。
-私は、それはPLAY文だと思います。MMLによる簡単な演奏なら、その気になればワンライナーで書けるくらいに簡単ですし、それでいて楽譜を入力して演奏するようなソフトウェアはそれほど一般的ではないので(少なくともペイントみたいにOSに標準インストールされてはいない)、それなりの目新しさがあるはずです。
-まあでも、やっぱり変数とかループとかを使うようにならないと、単機能ツールには勝てないかもなあという気はします。だからまあ五十歩百歩なのかもしれません。
~
** 2023.02.03 Fri #3
-小学生に教える案。CapsLockをONにしておく。
-PRとPRSPと変数演算とGOとIFが使えるようになればいい。それだけを目指す。
[1] 「1」を表示してみよう。
PR 1
[2] Iに1を入れてIを表示してみよう。
I = 1; PR I
[3] [2]の続きとして、Iを1ずつ増やして、3まで表示してみよう(ここでテキストエディタの使い方なども教える)。RUNで実行。
I = 1; PR I;
I = I + 1; PR I;
I = I + 1; PR I;
[4] GOを使って読み飛ばしてみるよ。どうなると思う?・・・もしGO命令がなかったらどうなると思う?
NO1: PR 1; GO NO3;
NO2: PR 2;
NO3: PR 3;
NO4: PR 4;
[5] GOで前に戻ることもできるよ。どうなると思う?
NO1: PR 1; GO NO1;
[6] じゃあこれはどうなるかな?
I = 1;
NO1:
PR I;
I = I + 1;
GO NO1;
数字がつながって見にくかったら、 PR I; の後に PRSP; を追加しよう。
[7] ずっと止まらないのは困るかな。じゃあ、100になったら止まるようにしよう。
I = 1;
NO1:
PR I; PRSP;
I = I + 1;
IF (I <= 100) GO NO1; // 101になったらgoしなくなるよ!
[8] 2から100までの偶数を表示するプログラムを書いてみよう!
[9] 1から99までの奇数を表示するプログラムを書いてみよう!
[10] 1, 2, 4, 8, 16, 32, ... で65536までを表示るプログラムを書いてみよう!
[11] 1から10までの和は55だけど、それを計算させてみよう。
PR 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
でも1から100までだったら、この調子では書けないね。どうしたらいいかな?
J = 0; I = 1;
NO1:
J = J + I;
I = I + 1;
IF (I <= 100) GO NO1;
PR J;
どうしてこれでうまくいくのか説明ができるかな?
~
** 2023.02.05 Sun #1
-もうずっとeasy-Cのプロンプト(といううかHL-9bのプロンプト)を出しっぱなしで、dirとかgccとかをやる時はshellコマンドを使ってばかりなのですが、だんだん「shell 」と6文字を入力するのが面倒になってきました。代案として「$」だけにしたらいいかもしれないと思っています。「$dir」「$gcc」。
-なぜ「$」にしたのかというと、shellのsに形が似ていることと、あと確かUNIXのbashのプロンプトが「$」だった気がするので、それにちなんで覚えやすいかなと思ってこれにしました。
-ということで整理すると、
--「$」で始まる命令はシェルコマンド
--「!」で始まる命令はgcc経由で実行(コンパイルは遅いけど、実行は速いし、C言語のすべての命令が使える)
--それ以外はHL-9bの中で普通に実行(実行はそれほど速くないけど、コンパイル時間がない。C言語のサブセット)
-になります。
~
** 2023.02.06 Mon #1
-どんどん便利になってきたeasy-Cですが、そろそろ先が見えてきたというか、アイデアが尽きてきました。ということはここから数週間頑張って今あるアイデアを実装し終わったら、終わりになっちゃうのかなあと心配になってきました(いやまあ、それでも「できたものを使いまくる」という一番楽しい段階は残っているのですが)。
-もうずっとeasy-Cのプロンプトは出しっぱなしで、もう何の違和感もなく当たり前にワンライナーして、dirやgccなどの起動も全部シェルコマンド($)を使って起動するのが当たり前になってしまっているのですが、そこで私はあることに気づきました。・・・あれ?私が作ったものはもはや言語ではなくてシェルなのではないか??
-シェルと言えば、私が20年前にOS自作をしていたころは、シェルとしてC++の文法が使えたらいいのにと思っていました。・・・なんでそんなことを考えたのかと言えば、私はまずいろんな文法が乱立するのが嫌いで、なぜプログラミングするときとシェルスクリプトを書くときとで違う言語を書かなきゃいけないんだ?って思っていたのです。C++の記述力は十分に高いから、シェルスクリプト用の構文なんかいらないと考えました。コマンドを入力するたびにコンパイルさせるのは遅そうで現実的ではないので、C++のインタプリタがあればいいと思っていました。
-・・・という昔の夢を急に思い出しました。そうか私はC++の構文が使えるシェルが欲しかったんだ!・・・あれ、このeasy-Cって、この構想にかなり近い感じがするぞ。C++じゃなくてCだけど。
-C言語がシェルになったら、どうあるべきでしょうか。私が真っ先に思うのは、変数が環境変数の代わりになることです。そうであるならば、変数はセーブしたりロードしたりできるべきです。・・・おお、これは前にやっていたpersistent-Cに近いなあ。
-シェルにはリダイレクトがありますが、C言語にはそんなものはありません。リダイレクトは標準出力や標準入力を切り替える機能ですが、似たようなことをC言語で自然にやるなら、関数の返値として結果を返すことでしょう。そうすればそれを適当な出力関数で画面に出すことができますし、ファイルに書きだすこともできますし、別の関数の引数にすることもできるでしょう。
-シェルにはシェルスクリプトがあります。シェルスクリプトを書けばコマンドを増やしていけます。easy-Cではどうしたらいいでしょうか。テキストファイルにC言語でちょろっと書いておけば、それがシェルスクリプトになるべきです。
-・・・と考え始めたらどんどんアイデアが出てきました。これなら当分開発のネタには困らなさそうです!
~
** 2023.02.06 Mon #2
-今日は、HL-9bと1ecとecrunとecc0をすべて統合して、HL-9cというのを作りました。
--[1]「インタプリタ実行」と「gccでコンパイルして実行」を自由に切り替えられる。
--[2]インタプリタ中でCtrl-Cしてもプロンプトに戻ってこられる。
--[3]gcc実行に限れば、適当にnewfunc()みたいな関数をテキストファイルに書いておくと、それを自由に呼び出せる。
-この[3]について追加で説明しておきます。たとえば、
char *myfunc(int a, int b)
{
char *s = malloc(100);
sprintf(s, "hello: a+b=%d\n", a + b);
return s;
}
-という関数を書いたとします。これをmyfunc.cという名前で保存しておくと、HL-9cのプロンプトで
>!prs myfunc(1, 2)
hello: a+b=3
>
-と実行できるのです。なかなかいいと思いませんか?・・・prsはputsみたいなものですが、カッコを省略できるのでよく使います。先頭の「!」は、この実行をインタプリタではなく、gccでコンパイルして実行せよいう意味になります。
~
** 2023.02.06 Mon #3
-もしかしたら、私の中では main関数を書く時代は終わったかもしれない・・・!!
~
** 2023.02.07 Tue #1
-[自分への戒め]
-改造は小さくなければいけない。大きな改造は開発の停滞を招きやすい。
-なぜ大きな開発がダメかというと、大きな開発の場合、「作ってみたけど思ったほどにはよくありませんでした」になってしまったら、それまでの開発時間が無駄になってしまう。それを避けることが何よりも大切。小さな開発を積み重ねる方法だと、遠回りだったり、後になって無駄になるなどの非効率が発生するけど、その損失は大規模改造が失敗するときよりもはるかに小さい。
-作ってみないと分からないことがある。使ってみないと分からないこともある。だから汚くてもいいし、実行速度が遅くてもいいから、「とりあえず」で作るのが一番いい。改良は後からいくらでもできる。最初から最適解なんてわからない。ちゃんと作るのは役に立つことがわかっていて、使うことが確定してからで十分だ。
~
** 2023.02.07 Tue #2
-昨日は相当に頑張って頭が疲れているので、今日はeasy-Cはお休み。
~
** 2023.02.08 Wed #1
-自分用のメモ:PLAY命令の音量指定は1~127。最大値は255ではない。間違って覚えていた。
~
** 2023.02.08 Wed #2
-PLAY文がHL-9cで未サポートだったので、動くように改造しました。
-prやprsもPRやPRSのように大文字で書いてもOKにしました。これは主に小学生向けの対応です。小学生はアルファベットがよくわからなくて、キーの刻印通りの大文字しか扱えないという想定です(常にCapsLockがON)。
-小学1年生がeasy-Cを徐々に習得していて自分でプログラムを書けるようになってきたので(まあPLAY文しかないプログラムではありますが)、ファイルの新規作成コマンド( NEW ABC.C みたいなやつ)を付けました。
-またシェルコマンドを拡張して$$というのも作りました。これは別プロセスで立ち上げるというものです。これがあるとアプリが終了しなくてもプロンプトに戻ってきます。これがあれば、「$$ABC.C」ってやるだけでテキストエディタが起動します。
-これらの拡張は大人の私にとってもかなり便利で、さらに快適になりました!
-こんな感じのことができます。
HL9>NEW TULIP.C
HL9>$$TULIP.C ← $$は別のプロセスで立ち上げるシェルコマンド。Windowsではテキストファイルを実行するとテキストエディタが開きます。それで以下の3行を入力して保存。
HL9>RUN TULIP.C ← これで演奏されます。
-ちなみに TULIP.C の中身はこんな感じです。
PLAY "CDERCDERGEDCDEDR";
PLAY "CDERCDERGEDCDECR";
PLAY "GGEGAAGREEDDC2R";
~
// persistent-C
//startupのasm化
//nekofun. invader.pr.prs.prlf.prsp
//winのクローズ
* こめんと欄
#comment