エピ23 MZ80のカーソル制御の文字はどうやって入力するの?
***
エピ23 MZ80のカーソル制御の文字はどうやって入力するの?
***
MZ80のキー入力はキーマトリクスをスキャンしてロウとカラムを得て、これをディスプレイコードに変換していることが分かりました。そして得られるディスプレイコードの一覧を確認したらキー入力可能なコードを確かめることができました。
ですがキー入力できても画面表示できないコードがあるのです。ですが。ですが、画面表示できる場合もあるようです。
不明確なことですね。これが気になって調べてみた、という話です。
***
ディスプレイコードの C1h〜C6h はキーボードから入力できて画面表示できると思っていたのです。だってパソコン雑誌のプログラムリストにカーソル制御の文字が載っているからです。
でも。このカーソル制御の文字はキーボードからどうやって入力するのでしょう? カーソルキーを押下したら画面上でカーソルが動くのですよね。
考えてみたら分らなくて夜になっても眠れなくて。ヒントを求めて1行入力用ルーチン GETL を解読することにしました。
***
**
*
GETL はコールされると 07E6h 番地にジャンプします。
07E6h 番地のルーチンはこんな感じです。簡略化して(ほぼ書き直して)いますがロジックは同じはずです。...、同じハズですがバグがあったり;汗;
push AF; push BC; push HL; push DE; [1193h] = 00h
while(1):
A=_09B3h() # キー入力
if [119Dh]==00h: _02E5h() # ベル
if A==CDh: jp _085Bh # リターン
elif A==CBh: jp _08B3h # ブレーク
elif A in [C7h,C9h,CAh]: _0DDCh(A) # 制御
elif A==C8h: inc [1193h]; _0DDCh(A) # 制御
elif A in [C0h〜CFh] and [1193h]==0: _0DDCh(A) # 制御
else:
_0DA6h(); _0DB5h(A) # 表示
if [1193h]>0: dec [1193h]
if A==62h: [1193h]=([1193h]&80h)^80h
登場するルーチンの説明です。細かいことは省略ね。
・09B3h はカーソル表示と文字入力を待機するルーチンです。カーソル(EFh)を点滅させてカーソルを表示する処理をします。文字入力は GETKY の本体である 08CAh のルーチンを利用します。
・02E5h は BELL です。ROM 003Eh のジャンプ先です。ラ(440Hz)を一瞬鳴らします。119Dh 番地はROMワークエリアでキー入力時のベル音を制御します。0=オン,-1=オフです。
・085Bh はリターンキー押下時の処理です。入力した文字を DE の指す番地に転送して RET します。
・08B3h はブレーク押下時の処理です。ブレークを意味する 1Bh, 0Dh を転送して RET します。
・0DA6h は垂直ブランクを検出したらリターンします。画面にノイズが出ないタイミングを計るために使います。
・0DDCh はカーソル制御のルーチンです。コードと制御内容は次の通り。
C0h:スクローリング
C1h:[↓] C2h:[↑] C3h:[→] C4h:[←]
C5h:[H] C6h:[C] C7h:[DEL] C8h:[INS]
C9h:[英数] CAh:[カナ] CDh:[CR]
・0DB5h はカーソル位置にディスプレイコードを表示します。
*
さて。キー入力された値 A の処理に注目します。0DB5h のルーチンによって画面表示される条件を確認しましょう。
C0h〜CFh 以外は画面表示のみです。当然ですね。
CDh (CR) と CBh (Break) は各キーに応じた処理となり画面表示しません。
C7h (DEL), C8h (INS), C9h (Eisu), CAh (Kana) はカーソル制御のみ。
C0h〜C6h, CCh, CEh, CFh は [1193h] の値によって、カーソル制御になる場合と画面表示になる場合があります!
[1193h] の初期値は 00h です。そして 00h ならカーソル制御で、00h 以外なら画面表示です。
*
[1193h] を更新しているのは次の3箇所です。
1)C8h (INS) なら1増加
2)C7h〜CBh, CDh 以外の場合に [1193h]>0 なら1減少
3)62h なら [1193h]=([1193h]&80h)^80h
うーむ。1)と2)だけなら単純ですね。
INS キーを押下した数だけカーソル位置の後方に空きができて、その数だけ入力キーをディスプレイコードで画面表示するのです。[1193h] は 00h から INS 数だけ増加して、画面表示したら減少して 00h で止まる。
ただね。INS を押し続けて 127 を超えるとオーバーフローしてマイナスになるため、その後の入力は全てディスプレイコード表示になる。更に INS を押し続けて 255 を超えると 00h に戻るけど。GETL では最大 80 文字しか扱わないから大丈夫?
3)は、まず 62h は「"」です。そして
[1193h]=([1193h]&80h)^80h
により [1193h] を 00h あるいは 80h にしているのですが。
初期値 00h なら、あるいは 0〜127 なら 80h にする。もう一度 62h を入力すると 00h に戻す。80h の間はディスプレイコード表示にする。
つまり、「"」で挟まれた文字列の入力時に C1h〜C6h のカーソル制御をオフにして、文字として入力できるのですね。
*
文字列の入力中にカーソルを移動したくて「←」キーを叩くと、文字として入力されてしまってあわてて見たいかな。あわわ。
***
今日の結論です。
カーソル制御の文字は、INS キーで隙間を空けた直後か、「"」の後に文字列を入力する際に文字として入力できる。
です。
***
スッキリとしたところでSP5030の解説書をパラパラめくっていたら、カーソル制御文字の入力方法を記載しているのを発見しました。IF-THEN のページでね。なんで〜 そこに〜 書くの〜
***
**
*
リターンとブレークの押下時の処理です。
リターンは 085Bh です。
if [1173h+[1172h]]!=00h:
BC=0050h; H=[1172h]-1; L=00h
elif [1173h+[1172h]+1]!=00h:
BC=0050h; H=[1172h]; L=00h
else:
BC=0028h; H=[1172h]; L=00h
HL = _0FB4h(HL)
pop DE; push DE; push BC; _0DA6h(); LDIR;
pop BC; pop HL; push HL
B=C
_088E: [HL]=_0BCEh([HL]); inc HL; djnz _088Eh
_0896: [HL]=0Dh; dec HL; if [HL]==20h: jr _0896h
_089E: _0006h(); pop DE; pop HL; pop BC; pop AF; ret
ブレークは 08B3h です。
pop HL; push HL; [HL]=1Bh; inc HL; [HL]=0Dh; jp _089Eh
どちらも予想通りの処理ですが。1173h 番地によるの行の連結の処置が明確になったのが嬉しいです。
リターン・キーを押下したときのカーソル位置 [1172h] がポイントです。
カーソル位置の行が前後の行と連結してなければカーソル位置の行だけが入力(BC=40)になる。
前の行と連結していると前の行との2行が入力(BC=80)になる。
後の行と連結していると後の行との2行が入力(BC=80)となる。
...、と処置されるのですよ。
*
**
***
取説には。GETL の入力文字数は 0Dh を含めて最大80文字との記載があるけど。81文字な感じがしないかな? 何か間違えたか。...?
***
間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!
***
2026.4.17 デバック。トホホ
2026.4.18 微推敲
2026.4.19 微推敲
2026.5.8 エピタイ修正




