表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
34/37

エピ25 MZ80のカーソル制御のこと


 ***


 エピ25 MZ80のカーソル制御のこと


 ***


 さて。


   0DB5h: ディスプレイ表示

   0DDCh: カーソル制御


 について調べてみます。


 ***


 ディスプレイ表示のルーチン 0DB5h です。


  def _0DB5(A):

    push AF; push BC; push DE; push HL

    HL=_0FB1h(); [HL]=A

    if [1171h]==27h and [1173h+[1172h]]==00h:

      [1173h+[1172h]+1]=01h # 次行と接続

      [1173h+[1172h]+2]=00h # 次行の次は切断

    jp _0E90h # [→] カーソル移動


 引数の A をカーソル位置に表示します。

 カーソル位置のX座標は 1171h 番地、Y座標は 1172h 番地にあります。0FB1h のルーチンは(X,Y)から D000h 以降の対応する番地を計算します。つまり、


   HL = D000h+X+Y*40


 です。ここに A を転送します。これで画面に反映されます。


 次には、1173h 番地が登場します。

 X==39, [1173h+Y]==00h なら、[1173h+Y+1]=01h にするのです。

 [1173h+Y] は 00h なら次行と未接続で、00h 以外なら接続中、...だと思っているのですが。


   Y=0, [1173h+0] = ?

   Y=1, [1173h+1] = ?

   Y=2, [1173h+2] = 0 # Now here

   Y=3, [1173h+3] = ? <-- set 1

   Y=4, [1173h+4] = ? <-- set 0

   :

 X=39, Y=2 のとき、[1173h+2]==00h なら [1173h+3] を 01h にする。ちょっと不思議ですね。調査必要な感じですが。1173h のことはカーソル制御を見ないと分らないかもですね。


 あとは、カーソル位置を右に移動します。0E90h はカーソル制御の [→] を処理するルーチンです。要は [1171h] を +1 するのですが、後述します。POP は 0E90h の方で行います。


 ***

 **

 *


 カーソル制御のルーチン 0DDCh です。


  def _0DDCh(A):

    push AF; push BC; push DE; push HL

    if (A&F0h)!=C0h: jp _0FDEh

    jp (0DF3h+(A&0Fh)*4)


  _0FDE: pop HL

  _0FDF: pop DE; pop BC; pop AF; ret


 引数 A が C0h〜CFh 以外なら 0FDEh にジャンプして POPs & RET で、C0h〜CFh ならテーブルジャンプ、...ではなくて、...算術型のジャンプですよ。


 A の値が 0〜(N-1) のとき、算術型なら


  1, 4: rlca

  1, 4: rlca

  1, 4: ld C,A

  2, 7: ld B,00h

  3, 10: ld HL,0DF3h

  1, 11: add HL,BC

  1, 4: jp (HL)


  4, 10: jp 0E32; nop <-- 分岐先


 なので、10+(4*N-1) バイトと 54 ステートです。分岐先が4つなら 10+4*4-1 = 25 バイト、54 ステート。

 テーブルジャンプなら、SP5030の 19FEh のルーチンを参考に条件を同じにして整理すると、13+2*N バイト、77 ステート。分岐先4なら 13+2*4 = 21 バイト、77 ステート。

 算術型の方が速いから。N=16 だけど速度優先で採用したのか。


 *


 カーソル制御の分岐先を見ましょう。


  _0DF3: jp 0E32; nop # C0h [UP]

  _0DF7: jp 0E74; nop # C1h [↓]

  _0DFB: jp 0E84; nop # C2h [↑]

  _0DFF: jp 0E90; nop # C3h [→]

  _0E03: jp 0EAE; nop # C4h [←]

  _0E07: jp 0EBF; nop # C5h [H]

  _0E0B: jp 0EC5; nop # C6h [C]

  _0E0F: jp 0EF8; nop # C7h [DEL]

  _0E13: jp 0F49; nop # C8h [INS]

  _0E17: jp 0EE1; nop # C9h [英数]

  _0E1B: jp 0EEE; nop # CAh [カナ]

  _0E1F: jp 0FDE; nop # CBh []

  _0E23: jp 0FDE; nop # CCh []

  _0E27: jp 0F8B; nop # CDh [CR]

  _0E2B: jp 0FDE; nop # CEh []

  _0E2F: jp 0FDE; # CFh []


 分かり易いところからね。


 *


 C9h [英数] と CAh [カナ] です。カナ/英数の状態を切り替えます。


  _0EE1: #C9 [英数]

    [E003h]=05h; [1170h]=00h; jp _0FDEh


  _0EEE: #CA [カナ]

    [E003h]=04h; [1170h]=01h; jp _0FDEh


 E003h 番地はメモリマップドIOで、04h/05h を転送するとLEDを赤色/緑色にできます。

 1170h はカナ/英数の状態を管理するワークエリアです。

 0FDEh 番地のルーチンは POPs&RET する共通のルーチンです。

 簡単ですね。


 *


 機械語なら少しでも同じコードがあれば共有するので、0EEEh の後半は 0EE1h にジャンプしますが、分かり易さを優先した整理をしてます。


 *


 次は C5h [H] と C6h [C] です。[H] はカーソル位置を(0,0)にします。[C] は画面をクリヤしてカーソル位置を(0,0)します。


  _0EBF: #C5h [H]

    [1171h]=0000h; jp _0FDEh # POPs&RET


  _0EC5: #C6h [C]

    _0DA6h(); C=19h; HL=D000h

    while(C>0):

      HL=_0FD8h(HL,B=28h); dec C

    HL=1173h; HL=_0FD8h(HL,B=1Bh) # 1Bh=27 ?

    jp _0EBFh # [H]へ


  _0FD8: A=00h

  _0FD9: [HL]=A; inc HL; djnz _0FD9h; ret


 [H] はそのままですね。

 [C] では 0DA6h のルーチンで垂直ブランク検出して、0FD8h のルーチンで D000h〜 と 1173h〜 をゼロクリアします。

 D000h〜 は 28h = 40 バイトのクリアを 19h = 25 回行いますが、200 バイトのクリアを5回行った方が良くないかな? 

 あとは [H] にジャンプです。


 *


 次は C0h [UP] です。画面を1行分スクロールアップします。


  _0E32: #C0 SCR-UP

    _0DA6h(); [E003h]=00h

  _0E39:

    BC=03C0h;DE=D000h;HL=D028h;LDIR;ex DE,HL;HL=_0FD8h(HL,B=28h)

    BC=001Ah;DE=1173h;HL=1173h;inc HL;LDIR;[HL]=00h

    if [1173h]!=00h: [1172h]-=1; jp _0E39h #

    _0DA6h(); [E003h]=01h; jp _0FDEh # POPs&RET


 最初に垂直ブランク検出して、[E003h] に 00h を転送します。すると画面オフします。

 D000h と 1173h を1行分移動します。

 D000h+40 から D000h へ 40*24 バイト転送して、0FD8h のルーチンで最後の行をゼロクリアします。

 次は 1174h から 1173h へ 26 バイト転送して、[1174h+26] に 00h を転送します。...。でもね。何故そこをゼロクリアするのかな。ex DE,HL か dec HL が抜けてない? そも 「HL=1173h; inc HL」って変だよ。もしかしてバG、...。

 [1173h]!=00h の場合、カーソル位置のY座標を -1 して、もう一度スクロールアップ。...、だけどY座標が0だったらバグらない?

 最後に垂直ブランク検出して [E003h] に 01h を転送して画面オンします。


 *


 謎が蓄積していますが解けるのでしょうか


 *


 次は C1h [↓] と C2h [↑] です。


  _0E74: #C1h [↓]

    if [1172h]==18h: jp _0E32h # SCR-UPへ

    else: [1172h]+=1; jp _0FDEh # POPs&RET


  _0E84: #C2h [↑]

    if [1172h]==00h: jp _0FDEh # POPs&RET

    else: [1172h]-=1; jp _0FDEh # POPs&RET


 カーソル位置のY座標を増減するのですが。最初の行(Y=0)で [↑] なら移動なし。最後の行(Y=24)で [↓] ならスクロールアップです。


 *


 続いて C3h [→] と C4h [←] です。


  _0E90: #C3h [→]

    if [1171h]>=27h: #27h=39

      if [1172h]<18h: [1171h]=00h; [1172h]+=1

      else: [1171h]=00h; [1172h]=18h; jp _0E32h # SCR-UPへ

    else: [1171h]+=1

    jp _0FDEh


  _0EAE: #C4h [←]

    if [1171h]==00h

      if [1172h]>=01h: [1171h]=27h; [1172h]-=1

      else: [1171h]=00h; [1172h]=00h

    else: [1171h]-=1

    jp _0FDEh


 [←] は簡単ですね。カーソル位置のX座標を -1 するのですが、X=0 のときは上の行の末(X=39,Y-=1)に移動します。Y=0 だったらそれ以上は移動できないので(X=0,Y=0)にする。ってか、元から(0,0)なのでは。


 [→] も同様ですが。行末(X=39)にいたときに、最後の行(Y=24)の場合はスクロールアップするのです。


 *


 はい。CDh [CR] です。


  _0F8B: #CDh [CR]

    if [1173h+[1172h]+1]==00h: #次行未接続

      if [1172h]<18h: [1171h]=00h; [1172h]+=1

      else: [1171h]=00h; [1172h]=18h; jp _0E32h # SCR-UPへ

    elif [1172h]!=17h: #17h=23

      [1171h]=00h; [1172h]+=2

    else:

      [1171h]=00h; [1172h]+=1

      jp _0E32h # スクロールアップへ

    jp 0FDEh


 次行未接続の場合は 0E9Dh([→]の一部)にジャンプするのですがコピペしました。


 次行未接続なら次行の先頭(X=0,Y+=1)にカーソル位置を移動するのです。最後の行(Y=24)ならスクロールアップです。


 次行接続中なら2行下の先頭(X=0,Y+=2)に移動だけど、Y=23 のときは Y=24 にしてスクロールアップ。むむ。Y=24 のときは必ず次行未接続なのかな。Y=25 の行はないから良いのか。


 あれ? [1173h+[1172h]+1] の +1 って何? 次行が次行未接続? あれ、あれ? ッー


 *


 **


 ***


 ピポッ! 謎の蓄積によりヒープメモリがオーバーフローエラーしました。強制シャットダウンしました。


 ***


 C7h [DEL] と C8h [INS] が手付かずですが。少し休憩して。ここまでを見直します。


 次回、1173h は思うてたのと違うのか。巨大な不発弾。自爆と誘爆にご用心!


 ***


 間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!


 ***

2026.4.28 推敲

2026.5.8 エピタイ修正



評価をするにはログインしてください。
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

↑ページトップへ