スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

10月24日 Lord of the MSX-BASIC / 割り込みの帰還


またベーマガのゲームをMSXに移植してるんですか。相変わらず後ろ向きな……




いいじゃん別に。ところで、移植してたら以前に感じた疑問が少し解決した、というお話をしたいと思いまして。あと、いつものことながら、わたしはプロでもないし、技術もないへたれアマチュアプログラマーという前提でひとつ。




はいはい。




少し前のこと、ベーマガでこんな記述を見つけました。「移植について:RETURN [行番号]の構文を使っているので、この機能がない機種は気をつけて下さい。」




ふむふむ。X1用のゲームですか。




で、「 RETURN [行番号] ??そんな使い方あったのか?」と思ったわけです。




RETURN文というと、GOSUBとセットで使うやつですね。




そう。サブルーチンを呼び出すGOSUB、そのサブルーチンから戻るRETURN、というものです。例えば、


100 一時間目の授業
110 二時間目の授業
120 三時間目の授業
130 四時間目の授業
140 GOSUB *お昼休み
150 五時間目の授業
160 六時間目の授業
170 クラブ活動
180 帰宅
……
……
500 *お昼休み
510 弁当を食べる
520 体育館で遊ぶ
530 RETURN


……てな感じに使います。この例だとわざわざサブルーチンにする必要はないんですけどね。




140行で[お昼休み]処理へ飛んで、530行の RETURN で戻ってきて次の150行の処理へ、という流れですよね。




うん。GOSUB は、他の場所へジャンプして処理を移しますが、必ず戻って来るので、プログラムの流れを乱さない、というものです。




ただ単に「ジャンプしろ」という GOTO との違いですね。片道切符と往復切符というか。片道切符だと、目的地に着いた後どこへ行くのかがわからないけど、往復切符なら必ず戻ってきますから。




戻って来るのが GOSUB~RETURN の最大の利点、というか存在意義なのに、 RETURN [行番号] とかぶっちゃけありえない、と。




先に挙げたプログラムの例でいくと、530行を RETURN 160 にすれば、五時間目をフケることが可能、ということで、先生は困ってしまうでしょう。




まあ、先生にしてみれば予想外、ですよね。




なのでこの機能、どうせ蛇足的なもだろう、できるからといってなんでもやっていいもんじゃないのに、と思っていたんですけど……




冒頭でも話した移植で、MSXだからスプライトを使おう、スプライトを使えば、プレイヤーと敵の衝突判定には ON SPRITE GOSUB が使えて便利だな、よし使おう、ということでその機能を使って移植を進めたら……あれ、RETURN [行番号]ってアリだな、って結論に。




MSX-BASICにもあるんですね、RETURN [行番号]。N88-BASICにも。




そう、で、共通しているのが、BASICによる割り込み処理がある、という点ではないかと。




割り込み処理って?




例えば、宿題している時に電話がかかってくる。当然、宿題を一時中断して、電話に出るよね。そして話し終わればまた宿題に戻る。この、今していることを中断してでも優先される処理が割り込み処理なわけです。




MSXでは、SPRITE ON としておくと、スプライトとスプライトが衝突した時、先ほどの「電話のベルが鳴る」状態になり、ON SPRITE GOSUB [行番号] で設定された行番号以下の処理が、今している処理を中断して実行されます。




GOSUB なので、処理が終わればまた元の場所へ戻ってきて処理を続けます。




やっぱり元の場所へ戻って来るのが重要なんじゃないの?




もちろんそうなんだけど、割り込み処理で使われるGOSUBが通常のものと違うのは、「プログラムのどの位置で呼び出されるのか分からない」というところ。電話がいつかかってくるのかわからないのと同じです。




先ほどの学校プログラムで考えてみましょう。プログラムの冒頭にこんな追加をしてみます。


20 ON 体調悪化 GOSUB *保健室
40 体調悪化 ON


あと、話を簡単にする為に、お昼休みサブルーチンは無いことにします。


140 お昼休み


ということで、食事したり遊んだりは「お昼休み処理」でひとくくりにします。





なんか不吉な割り込みですね。




確かに考えたくないですけど、これで、もし体の調子が悪くなったら保健室へ、という処理をしてくれます。授業中でもお昼休みでも、体調が悪化すれば中断して保健室へ行けます。




さて、保健室へ行ったら、体調が思ったより悪いので早退していいことになりました。




GOSUB は元の場所へ戻る、ということですから、例えば二時間目の授業中に体調悪化した場合、保健室処理が終わればここに戻ることになります。でも、普通に戻るとこのままプログラムが続行され、体調が悪いにもかかわらず授業を続けさせられることになります。




困った時はフラグですよ!早退フラグを作って、保健室処理でフラグを立てればいいのでは?




そうなんだけど、そうすると、いちいち処理の度にフラグ確認をしなきゃ、ということになります。


100 一時間目の授業
105 IF 早退? THEN 180
110 二時間目の授業
115 IF 早退? THEN 180
120 三時間目の授業
125 IF 早退? THEN 180
130 四時間目の授業
135 IF 早退? THEN 180
……
180 帰宅


みたいに。




う~ん。




ここで、保健室処理をこんな感じにしてみると、スマートなんじゃないかと。


1000 *保健室
1010 ちょっと横になって休息
1020 IF 状態=悪い THEN RETURN 180
1030 RETURN




なるほど、こっち側で直接帰宅へ飛ぶんですね。悪くなければそのまま戻る、と。でも、なんかちょっと行儀が悪い気も……




どこから呼ばれるか分からないなら、呼ばれた場所に戻ることにこだわらなくてもいいのでは?、という解釈もあるなと。




でも、「どこから呼ばれるかわからない」っていうことは、通常サブルーチンの処理中にも呼ばれるってことじゃない?そこではちゃんとRETURNで戻らなきゃいろいろ不都合がおきるんですよね。




今の説明で、お昼休み処理をサブルーチンコールから通常処理に変えたのはそのためで。




最初のリスト通り、お昼休みサブルーチンがある場合、その処理中に体調悪化した場合、お昼休み処理のRETURNが実行されないまま帰宅処理に移ってしまうということですから、すぐエラーが出るわけではないですけどあとあと問題が起きますよね。GOSUBとRETURNは必ずセットですから。




うん。そもそも、機能的にいえば RETURN [行番号] じゃなくて GOTO [行番号] でもいいのにわざわざ作っているって事は、そういうことだからねえ。




ただ、始めに戻るけど、今移植しているゲームに関していえば、スプライトが衝突するっていうのはキャラクタを動かした直後しか発生しないわけで、その動かすプログラムがサブルーチン内でないなら、元に戻らない割り込み処理でもいいのかなと。




そこまで割り込みの発生タイミングが限定しているなら、そもそも割り込み処理でなくても、という気もしますが……




まあそうだよね。スプライトの当たり判定を勝手にやってくれるんで、その点は楽になるんだけど……。とにかく、RETURN [行番号] には意味があった、のだろう、ということで。




そもそもN88-BASICにもあった機能なのに、何で今更そんなことに気がついたのかと……




だって当時は割り込み処理なんて使おうとすら思わなかったんだもん。




あおいちゃん

コメントの投稿

非公開コメント

記憶が甦る~みたいな・・・(^^;

なんかここへ来ると忘れていたBASICプログラミングが甦ってきますねぇ(^^;;

RETURN[行番号] 確かにありました。
あれって、割り込み以外でも使い道あったように思います。
単純なところではサブルーチンの処理結果によって戻る場所を
変える時とか・・・

100 帰宅
110 GOSUB *宿題する?
120 テレビ見る
130 風呂入る
130 夕食を摂る
140 ゲームする
150 寝る

1000 *宿題する?
1010 IF 宿題しない THEN RETURN
1020 IF 宿題する THEN RETURN 130
1030 IF 部屋を片付けてから宿題する THEN RETURN 140
1040 IF 部屋を片付けてたらついマンガを読んでしまう THEN RETURN 150

みたいな?

あとは、サブルーチンの処理を終えた後、別のGOSUBに戻る(?)
なんて時に使ったような気がします。

100 *メニュー
110 INPUT A
120 ON A GOSUB *データ入力、*トータル出力、*検索、*印刷
130 GOTO *メニュー

1000 *データ入力
1010 GOSUB *キースキャン

いろいろ処理

1100 GOTO *データ入力


10000 *キースキャン
10010 A=0:AA$=""
10020 A$=INKEY$
10030 IF A$="" THEN 10020
10040 IF A$=CHR$(13) THEN *後処理
10050 FOR I=1 TO 10
10060 IF A$=MID$("0123456789",I,1) THEN AA$=AA$+A$
10070 NEXT
10080 GOTO 10020
11000 *後処理
11010 A=VAL(AA$)
11020 IF A=88 THEN RETURN *印刷
11030 IF A=99 THEN RETURN *終了
11040 RETURN

ちょっと良い例が思いつかなかったので、こんなんで勘弁して下さいm(_ _)m
当時、素人がPC操作をするのに変な文字を打ち込んでエラーを出さない為の
処理でこんな感じのキースキャンを組んだよーな・・・
なんせ、あの頃はPCを操作する人は特別な人種と思われてた時代ですから
ねぇ~
それを素人に操作させようとしたら、プログラムの方でがんじがらめにして、限ら
れたキー操作しかできないようにするしかなかったわけで・・・

って、長文失礼しました~m(_ _)m

向月さん江

>なんかここへ来ると忘れていたBASICプログラミングが
>甦ってきますねぇ(^^;;

時間が逆行しているサイトです。(^^;

う~ん、RETURN [行番号]はいろいろ用途が
ありそうですねえ。まだまだBASICも奥が深い……


> *宿題する?サブルーチン

必要のないコードがありすぎる気が(^^;
カレンダー
05 | 2017/06 | 07
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
twitterでひとこと
最新記事
リンク
カテゴリ
最新コメント
最新トラックバック
検索フォーム
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
来訪者数
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。