超暇人MSX

実戦BASICファイター?

8ビットパソコンの限界

80年代当時は、プログラミングと言えばBASICの事を指すというくらい、名前にVisual等の付かない “素の” BASICが流行っていました。主な8ビットパソコンに搭載されたBASICでは、書いたプログラムをEXEファイルやCOMファイル等の実行ファイルに変換(コンパイル)せずに、そのまま使用します。まずBASIC本体を立ち上げて (大抵の機種では、システムの入ったフロッピーを入れずに電源を入れれば立ち上がる)、保存しておいたプログラムを読み込んで走らせれば、そこで1行ずつコンピュータが理解できる機械語に翻訳して実行するのです(インタプリタ方式)。
 BASIC本体がOSとして起動している上でプログラムを実行するので、プログラムに間違いが有っても殆どフリーズしたりせずにエラーを出して中断しますし、プログラムは書いたときのままですから、その場で簡単に修正も改造もできます。その半面、常に翻訳しながら実行するので動作速度は遅めです。

80年代インタプリタ方式の利点  ・手入れが簡単・・・エディタが常駐し、その場でプログラムを作成・修正できる  ・コンパイルの必要がない・・・書いたままのプログラムを読み込んで、実行するだけ  ・暴走しにくい・・・プログラムに間違いがあっても、インタプリタ本体にもどる

さて、Z80をはじめとする80年代の8ビットCPUが一度に使えるメモリは64キロバイト (65536バイト) です。それ以上メモリを載せていても、8ビットCPUは一度に64キロしか把握できないので、スロット切り替えの(例えば16kずつメモリを入れ替えて使う)ような機械的な仕組みが必要です。BASICを使う場合はその64kの中にBASICソフト本体が入るので、機種によって違いますが、プログラムに使えるのは40〜20k程度になります (いわゆる裏RAMを入れず、64k内で)
 また、PC−8801mkIISRやMSX2など後期の8ビット機になるほど機能が増える分、大きくて重い(遅い)BASICが搭載されました注1。ちょうど、Windowsのバージョンが上がるほど高機能化して、大きく重くなるのと同じ理屈です。例えばMSXでは、8ビット機用『Microsoft Business BASIC』の当時の最新版 (Ver.3(Microsoft社の標準BASIC第4.5版)に、MSX仕様の改造を加えたもの) を搭載している為、 「内部十進演算・有効数字14桁(倍精度8バイト)」 という、8ビット機には重い設定が標準の状態となっています注2

80年代インタプリタ方式の欠点  ・処理が遅い・・・1行ずつ機械語に翻訳しながら実行するので遅くなる  ・書式は固定・・・フリーフォーマットはエディタだけでメモリを食ってしまうので  ・オンメモリ・・・プログラミング言語本体が、常にメモリにデンと居座っている

というわけで、メモリが限られスピードの遅い8ビット機搭載BASIC用プログラム必須事項

 1.できるだけ小さくする  2.できるだけ速くする

となります。BASICプログラミングの教本で説かれるような、見た目が綺麗で分かりやすくて、構造化されていて・・・というプログラムは、メモリやスピードの都合で16ビット機以上でないと、(当時のパソコンに対する要求レベルに対してすら) あまり実用的ではありませんでした。

なお、C言語等と違って(Visual等の付かない素の)「BASICは構造化できない」 とか 「オブジェクト指向にならない」 と一般に思われているようですが、それは多くのパソコンに採用された 『マイクロソフトBASIC』 系がそうなのであって、ANSI規格に沿った 『TrueBASIC』注3や、JISに沿った 『十進BASIC』注4は、初めからANSIのC言語同等の構造化機能を備えています。
 『マイクロソフトBASIC』 は、プログラミングに於ける根本的かつ重要な一部の機能を端折って、70年代後半の8ビットパソコン上でも、インタプリタ方式で走るように軽量化し、大手メーカー各社に採用されて普及しましたが、それを引きずったままバージョンアップしていったため、BASICという言語に汚名を着せてしまったのです。

N88−BASIC系やMSXBASICといった、マイクロソフト系を祖とする “素の” BASICは、変数が全てグローバルであり、且つ、制御関連命令で引数が使えない (つまり、サブルーチンでも関数でも、すべてグローバル変数で受け渡しする) のが、実際、一番の問題点だったりします (=オブジェクト化不可能?)
 『TrueBASIC』『十進BASIC』等、ちゃんと規格に沿った「素の」BASICでは、この問題は有りません。

BASICの規格  1964 BASIC言語誕生  1978 ANSI MinimalBASIC 規格化(最低限必須のBASIC規格)  1982 MinimalBASICをJIS基本BASICとして日本規格化  1984 ISO系が ANSI MinimalBASIC 採用  1987 ANSI Full BASIC 規格化(標準のBASIC規格)  1991 ISO系が Full BASIC 採用  1993 Full BASICをJIS Full BASICとして日本規格化

超偉大なるマイクロソフト系BASICは、この規格を無視しています(^^;)

1985年にマイクロソフトが発売し、アメリカではかなり使用された『QUICK BASIC』は、91年の『Visual BASIC』に繋がるものですが、「C言語をBASICっぽくしたという方が適切」(マイコンBASICマガジン1992年1月号付録より) という感じです。当時のユーザーを惹きつけるためにBASICを名乗りましたが、BASICの規格を全く無視しているので、BASIC一族か?というと、ちょっと違う気がします。「85年度マイクロソフト製の新言語、内緒だけど当時流行のIDE付C言語のパクリ仕様で、コマンド名がBASIC風味」 という感じで、血の繋がってない遠縁の者くらいでしょう。(はぁ?)
 ビルゲイツ氏は自分を世に出したBASIC(という名?)にとてもこだわりが有って、91年の『Visual BASIC』発売の際には「これはBASICじゃないから名前を変えましょう」 という案を蹴ったそうです。

 注1.ただし、MSX1に搭載されたBASICのグラフィック関連命令は、全く機種への     最適化がされておらず、MSX2以降に搭載されたものと比較して、とても遅かった。      今で言う「GPU」搭載は、当時最新の考え方だったので、作り手も慣れておらず、     旧来の方法そのままで、グラフィック関連命令を実装したのである

注2.倍精度(8バイト)と整数(2バイト)の比較例     アスキー出版の本、『とにかく速いマシン語ゲーム集』1984年8月初版90ページの     コラム2に、MSXの「これがBASICによるスクロールの速さの限界だ」として     短いプログラムが有る。このプログラムの変数を全て整数指定すると100回ループ     が(時間の単位は60分の1秒で)            時間 → 速度比率      元は倍精度 673  100%      整数に変更 393  171%     7割も速度アップする。全然限界じゃなかったのだイッヒッヒ。次の章に書く2と     3の方法を使えば、アルゴリズムをいじらなくとも更に2%速くなる

   おまけ MSXBASICの演算精度(ネットで見つけた97年頃の比較に付け足し)           1 PRINT USING "+#.###############^^^^": EXP(LOG(7))      2 END     というプログラム(相当)の実行結果比較         組み合わせ           結果        7との誤差     *TrueBASIC6 & Windows +7.000000000000000e+00 0     *TrueBASIC6 & Ubuntu+Wine +7.000000000000000e+00 0     *TrueBASIC5 & Windows +7.000000000000000e+00 0      TrueBASIC & Mac Quadra +7.000000000000000e+00 0      TrueBASIC2 & MS-DOS +7.000000000000000e+00 0     *十進BASIC & Windows +7.000000000000001E+00 0.000000000000001     *十進BASIC & Ubuntu +7.000000000000001E+00 0.000000000000001     *十進BASIC2進 & Windows +6.999999999999999E+00 0.000000000000001      QuickBASIC & Mac Classic II +7.000000000000200D+00 0.0000000000002      MSX-BASIC & MSX2+ +6.999999999999500E+00 0.0000000000005      MSX-BASIC & MSX1 +6.999999999999500E+00 0.0000000000005      HP-BASIC & HP-85 +7.000000000030000E+00 0.00000000003      TrueBASIC & Power Macintosh +6.999999999864670e+00 0.0000000001533      TrueBASIC & Mac Classic II +6.999999999864670e+00 0.0000000001533     *を点けたのが現行のものなので、当然に上位に来るが、その他の16ビットの     90年代モノと比較して、80年代8ビットのMSXも精度は負けていない     参考:MSXの方がPC-9801より正確?

注3.本家本元BASIC。パクリ且つ変則的なMSの方が普及した為、1984年の     バージョン8相当からTrue(本物)と改名した。1964年にダートマス大     学で、ホストと端末の通信OS開発用として(!)、責任者ケメニー、現場監督     カーツ、建築作業員10名の数学科学生という体制で原型を開発。インタプリタ     ではなくコンパイル方式であり、現行バージョンではWindowsプログラム     も作成できる。有料ソフトであり、残念ながら現行の日本語版は無い。     ●C同等(以上?)の1979年、米国標準規格草案の頃の流れ制御関連命令      FOR文、GOTO、IF文、GOSUB文 ←これらは1964年の初版からある      DO〜LOOP、DO UNTIL〜LOOP、DO WHILE〜LOOP      EXIT、SELECT、CALL SUB      条件判定には論理式の他、論理句(KEY IN等の決まり文句)が使える      外部ファイル参照用LIBRARY宣言、EXTURNAL宣言      引数の使える関数宣言のDECLARE DEF命令もある     余談であるが、後にケメニーとカーツは仲違いした。カーツ「作ったのは私だ」     ケメニー「責任者は私だ」がもとで、カーツ「有料だ」ケメニー「本体無料でI     DEで稼ぐ」と対立して仲違い。商売としては「無料でバラ撒いてIDEで稼ぐ     」方が良かったかも? ちなみにケメニーはユダヤ系、やっぱり商売上手?

注4.フリー且つ国産で現役。現在最強の「素」BASICだと思われる

ページのTOPへもどる

実戦的8ビットBASIC

ファミコン用のファミリーベーシックは、用意された16種類のキャラ(スプライト)、8×8ドットの104種類の背景パーツ、カタカナとアルファベットと数字、を組み合わせてゲーム (とは限らないけれど、2バイト整数型しか数値を扱えないし、文字列は最大31文字だし、ゲーム以外の用途には・・・) を作る、機能限定なBASICシステムです。BASIC本体の名称は 『NS−HuBASIC』 で、ハドソンがパソコン用に作った 『HuBASIC』 の改造サブセットです。名称の頭のNSは、任天堂とシャープの頭文字らしいです。でも、別売りのデータレコーダは、松下製品の一つと同じ形状 (で機能省略?) の色・ロゴ違いだったと記憶しています(?)。

ファミリーベーシックは、カセット内蔵のSRAMにメモリの内容(打ち込んだBASICプログラム部と背景の並べ方)を1回分保存できるが、上書きすれば当然前回の記憶は消えるし、電源を入れたまま標準品より2倍の高さが有るカセットの上部前面に有るスイッチを操作して保存処理をするため、本体との接触不良でデータが飛んでしまう事故が頻繁に起こる。そのためマトモに使うには、データレコーダが必須であった。
 別の所にも書いたが、ファミコン+ファミベー+レコーダーを買うくらいなら、MSXを買った方がずっと実用的だったと、超暇人MSXとしては思う。ゲームで遊ぶならファミコン、プログラミングで遊ぶならMSXである

ファミリーベーシックでは、プロが作った背景パーツやキャラを組み合わせてゲームを作るので、パッと見にはMSX1のBASICで作ったゲームより良さそうに見える事も多いのですが、ファミコン最大の武器である 「背景スクロール」 は不可能ですし、プログラムに使えるメモリーが初代 (VER1.0、VER2.0、VER2.1) は2k弱、新型 (VER.3.0) は4kと超少なく、効率の良いメモリー使用は正に必須で、かなり工夫しても、とても単純なゲームしか作れません (単純なゲームがつまらないとは限りませんが)。

 そのファミリーベーシック用の 『オリジナルゲーム集25』(ナツメ社) という本によると

●メモリを上手く使う  1.REM文は、なるべく少なくします。  2.空白(スペース)を少なくします。  3.マルチステートメントをたくさん使う。  4.IF文をかんたんに・・・ ●スピードを速くする  A.掛け算・割り算は、なるべく使わないように  B.複雑な計算は、初めに計算しておきます  C.プログラムを圧縮します  D.変数名は、なるべく1文字にします  E.IF文では、ANDを使わないように

が、良いプログラミング方法だそうです (激怒するプログラマーが居そう(^^;))。これを私なりに解説すると

 1.REM文とは、コメント文の事。コメントは1文字1バイト使うので、とても    メモリを食う。よって最低限の使用に止める。なお、大抵のBASICでは、    ’(アポストロフィ)とREMが使えるが、メモリ上ではREMの方が小さい    ので、REMを使う。    例、    「10 ’コメント」 → 「10 REMコメント」 →「10 REM」    右ほどメモリ使用量が少ない  2.例えば「FOR I=0 TO 10」という文を「FORI=0TO10」    とスペースを詰めて書くと、その分メモリを使わない  3.1行にX=10とだけ書くより、X=10:Y=20:Z=30というように    255字以内なら出来るだけ:で繋いで1行にすると、よりメモリを使わない  4.ファミリーベーシックではIF文のTHENを省略できる。他にもマルチステ    ートメントの:が省略できる。他のBASICでは両方とも省略不可  A.X*2をX+Xにする等。当時の8ビットCPUでは、機械語に翻訳すると    掛け算・割り算は長くて遅い  B.複雑な計算の答えをデータ文で表にして書いておき、実行時の計算をさける  C.インタプリタはプログラムを1行ずつ取り込むので、1行に書けるだけ詰め込    むと、取り込み回数が減って速くなる。また、1文字ずつ解析するので、文字    数が少ないほど速くなる  D.上の C.と同じく文字が少ないほど解析が速い  E.「IF X=0 AND Y=0・・・」と条件をANDで複数繋ぐより、    1行ずつ「IF X=0・・・」「IF Y=0・・・」と分ける方が速い

という感じです。このほかに私の知る高速化は 「複雑な数式をバラして単純な式の連続として書く事」 です。ただしその分メモリは消費します。また、ほかの私の知るメモリ効率化は 「同じ変数(名)を色々な所で使い回しにする」 「同じ作業をする部分をまとめてサブルーチンにしてしまう事を徹底する」 です。ただしサブルーチンを多用すれば速度は遅くなります。メモリ使用量を減らす事と高速化は、両立することも、トレードオフ関係となることもあります。
 ああ、まだありました。インタプリタが解析する際には1文字ずつ順にA、B、・・・と比較していくので、変数名をAにすると一番速いのです。X、Y、Zより、A、B、Cが速いのです。

参考
 下左はファミリーベーシックの『BGグラフィック』モード = マップデータを入れる画面。キー操作で下部に順繰りに表示されるパーツを見て探して、同じくキー操作で座標を表示して入れていくらしい。右はファミリーベーシックの全背景パーツ

ファミべーの「BGグラフィック」モード ファミベーの全背景パーツ

ページのTOPへもどる

出来ればアルゴリズムを見直せ

私の経験から言うと、80年代8ビット機に搭載のBASICでは、上記の高速化A〜Eと複雑な式のバラしを全て行えば、1.5倍程度速くなる事があります。上記メモリ使用の効率化1〜3とサブルーチン徹底化や変数の使い回しを全て行えば、2〜3割サイズが小さくなる事があります。その代わりこれらを行えば、可読性の低いとてもメンテナンスのし辛いプログラムになります注4。つまり、8ビット機のBASICでは、少しでもメモリの使用量を減らす/高速化するための苦肉の策として上記1〜3やA〜Eの様な方法をとりますが、難読化する副作用があるわけです。
 私の拙作 『マジンナースB』 のBASIC部分を覗いた方は 「なんと読み辛い分かり辛いプログラムだ!」 と思われたかもしれませんが、別にパクられないように難読化したワケではなく (パクる人も居ないでしょうし(^^;))、作っていく内にどうしてもメモリが足りなくなって、メモリの効率化をせっせと行った結果です。(ゲームの途中でディスクを読まないようにしたいと、なんとなく思ったので、詰めるだけ詰めたのです。)

では、そういう副作用の少ない 「メモリ使用の効率化」 や 「実効速度を高速化」 する手段はあるでしょうか? コンピュータサイエンスの本には 「アルゴリズムを見直せば100倍も速くなる、サイズも3分の1になる」 みたいな話がよく書いてあります。ですが自分で自分のプログラムを見直して、より効率的なアルゴリズムを編み出すというのは、根気と時間と数学っぽいセンスとオツム(と運)が必要で、なかなか大変なことなのです(いや、私には)。本来そうあるべきなのでしょうが。

注4.プログラムのメンテナンスというと、MSXでは別売りの『MSX−AID』    というROMを刺せば、BASICにデバッグ用の      1.使用した変数のリスト表示。3種類の表示方法を指定できる      2.プリンタにトレース(プリンタにTRONする)      3.参照された行番号と参照した行番号を2種類の方法を指定して表示      4.指定の命令や文字列の有る行を3種類の方法を指定して表示    という機能が増え、16ビット機BASIC並のデバッグが可能となる

ページのTOPへもどる

このページは、1024×768画面に合わせて作りました。ちゃんと見えなかったらスミマセン