とわ君に独り言2(痛)

MSXやエレキギターが好きなおっさんの戯言。妻が白血病で亡くなり、3人の子供達と暮らしてます。昔のブログ→id:TOWA0104

■MSX BASIC 高速化考察■MSX BASIC入門 ゲーム制作〜番外編〜

●2023/10/8※2つの数値の交互繰り返し追加●
MSXは電気羊の夢を見るのか?〜
本題(※たいした内容では無いよう)
■MSXBASIC速度アップの方法を探ります。■「TIME」変数で検証もしています。

●BASICの構造によるところ●
プログラムを1回実行すると分岐命令(GOTOなど)の飛び先行番号が実アドレスに変換されるので2回目以降は若干高速化する。(ごりぽんさんのツイートより引用)

●変数●
・変数に0代入が複数ある場合、「CLEAR」文を先に入れれば全ての変数を0に速く定義出来る。
 (※「CLEAR」文は変数の型宣言(DEFINT等)より前に置かなければいけない縛り有り)
・「DEFINTA-Z」等で変数の整数型宣言を行う(確保するメモリも削減)
 (※「RND」を使う場合は個別に「INT」を付けないと何故か遅くなる)
・よく使う変数は、早めに初期値定義(メモリ前方はアクセスが速い)
・無駄な変数を減らす
 「T=STRIG(■):IF T THEN 〜」なら、
 「IF STRIG(■) THEN 〜」に変更
 (変数Tを他で参照しない前提なら)

●計算式●0と1の繰返しは、
 A=0^A
 A=A XOR 1
 A=1-A
 A=-(A=0)
 IF A THEN A=0 ELSE A=1
の順に速い。(↑※b.p.sさんのツイートより引用)

・変数を使い違う数値を交互に繰り返す場合
 「SWAP A,B」のように予め用意しておいた数値を入れ替えた方が更に速い場合が多い。

●記述に関すること●
・「:」を使い1行により多く詰める。
・「REM」や「`」を使わない。
・変数名を短くする。(1文字が1番速い)
 例:それぞれXY値を示す変数名を、XY,EF,MN等雰囲気が似た物にしたり、方向ボタン検出の変数はSでトリガ検出の変数はTにしたり、自分で予想しやすい物にすると便利。
・扱う数値を極力速い物にする
 整数型の0〜9が1番、10〜255が2番目に使用メモリも少なく速度も速い。(※MSX-DatapackのP258参照)
 0〜9>10〜255>256〜32767の順に速い
・メインルーチンやサブルーチンをプログラム前方に置く。(メモリ前方はアクセスが速い)

●「LOCATE」や「PRINT」●
・「PRINT」文末尾に「;」を足す。
 (※文字列を接続し表示する場合「;」や「+」を使うと遅くなる。)
・「LOCATE0,0:PRINT"■";」より、カーソル位置を左上にする「PRINTCHR$(11)"■";」が速い。
・「LOCATE ■,■」のX座標が0なら「LOCATE,■」と省略。(状況によっては使えない場合あり)
・「LOCATE■,■:PRINT"■";」と「VPOKE■,■」では後者が速い。(※一文字限定)
・カーソル位置から改行を行う場合「PRINT」が速い

●アドレス指定●
※「PEEK」「POKE」「VPEEK」「VPOKE」等アドレス指定をする場合、10進数より&hで始まる16進数で指定した方が速い。
(中間コードの関係なのか?ちょっと驚き)

●スプライト●
・PUTSPRITEとVPOKEだと、VPOKE1つまでならPUTSPRITEより速い。

●IF文●
・空白を削減し詰めて記述
 「IF A>7 THEN A=0 」を「IFA>7THENA=0」に
・「IF〜THENGOTO■」(■は行番号) を「IF〜GOTO■」に省略。
・「IF〜THEN〜ELSEGOTO■」を「IF〜THEN〜ELSE■」に省略。
・変数と定数を比較する場合、定数を前にした方が速い!(2023/3/1追記※b.p.sさん検証ツイートより)
 「A<16」は「16>A」の方が速くなる。

●FOR〜TO〜NEXT●
・繰り返しの処理を展開し、「FOR〜NEXT」文を極力使わない。
・「TO」の前後の数値も、当然0〜9や10〜255の数値に収めると、僅かに速くなる
・「NEXT ■(変数名)」は、変数名を省略すると速くてメモリ節約
・「NEXT■:NEXT■」又は「NEXT■,■」は、
「NEXT:NEXT」の方が速い(■はFOR文で使われているそれぞれの変数名)2023/6/16訂正

●「GOSUB」●
・サブルーチンを極力展開
(当然サブルーチンへの往復分速くなる)
・GOSUB RETURNの行き帰りより、GOTO2回の方が速い。
・「GOSUB RETURN」で呼び出す良く使うサブルーチンは若い行に置くとアクセスがわずかに速い。

●ファイル関係●
・VRAMへのデータ書き込み
 BASIC上でVRAMデータを書き込むよりも、BSAVEされたVRAMデータファイルを読み込んだ方がデータ量が多い程速い。
・ファイルのセーブのロード時間は、ASCセーブよりBINセーブの方がかなり速い(b.p.sさんツイートより抜粋)

●一部の乗算式の展開●
 乗算より加算が速い場合がある。
 「A=A×2」は「A=A+A」とした方が速い(3倍以上は逆に遅くなる)

●各演算子等を置き換える●(※2023/4/6書きかけだった別記事より転載)
・S=STICK(0) OR STICK(1)や
 T=STRIG(0) OR STRIG(1)等の処理は、
 「OR」を「+」に置き換えると
 メモリ節約兼スピードアップ
(▲しかし両方押された時に挙動がおかしくなる)

●自キャラ8方向移動プログラムではどの方法が速いか?●
①「ON〜GOTO」を使う方法
②XYそれぞれの計算にMID$を使う方法
③IF文羅列
④1画面プログラムで多用された、論理演算子を使う方法
と、いう順に処理が速い。
(※使用状況に応じて変わる可能性有り)
※何処かのブログでON〜GOTOとMID$の比較再検証&再確認をして下さった方がいました。感謝🙏

●PLAY文●
・PLAY(0)より、PEEK(&HFB40)の方が速い。(※2023/10/18検証済)
MMLは音階指定する「O1C」や直接数値で指定する「N64」(Nコマンド)等は速度ほぼ同じ



●描画は、画面を非表示中にすると速い


★以下は全て未検証の課題★

▲割り算は「/」より「¥」が速いのは
変数の型宣言後でも意味があるのか?
▲「IF A=A<(定数や変数)AND A>(同じ定数や変数)THEN〜」を「<>」や「><」等に変更する。
例:「IF A<>(定数や変数) THEN〜」等に変更。
▲「LOCATE■,■:PRINT"■";」よりも、「PRINT"Y)●●■";」の方が速いのか?(XY座標が定数のみ)


■まとめ■
意外な結果も多く、色々検証した方が良さそうです。
検証をしていると、BASICインタープリタ内での挙動が何となく見えて来るような気がします。(えっ、しない?)
※一定条件下での検証ですが、1つの指針としての有用性はあるのではないかと思います。
(10代後半の時に、BASICで一画面シューティングゲーム作ろうとして調べた時の記憶頼りだったり、複数一度に検証しメモ取り忘れたりしたので、再検証しないといけない物もあるかも…)

※間違いがありましたらご指摘をお願い致します🙇

◆他にもあったら教えてエロい人◆

◆予告なくのんびり検証しつつ加筆修正整等します◆