ND8080 応用プログラム集(100ページ)

ND8080 応用プログラム集
(有)中日電工
目次
第1部 ゲームプログラム
ⅰ)はじめに
ⅱ)プログラムリストについて
ⅲ)附属CDROMのプログラム、データの扱い方
プログラム№1 おはよー(OHAYO8.BTK)
プログラム№2 CRAZY EIGHT(CRAZY88.BTK)
プログラム№3 Hi-Lo(HILO8.BTK)
プログラム№4 FLIPFLOP(FLIPFLP8.BTK)
プログラム№5 SWAP(SWAP8.BTK)
プログラム№6 CATCH(CATCH8.BTK)
プログラム№7 もぐらたたき(MOGURA8.BTK)
プログラム№8 神経衰弱(SINKSUI8.BTK)
プログラム№9 WANTED(WANTED8.BTK)
プログラム№10 すごろく迷路(SUGOROK8.BTK)
プログラム№11 REVERSE(REVERSE8.BTK)
プログラム№12 ROCK CLIMBING(ROCKCLM8.BTK)
プログラム№13 WILD SEVEN(WILD78.BTK)
プログラム№14 MOO(MOO8.BTK)
プログラム№15 SWAP2(SWAP28.BTK)
第2部 電子オルゴール
1.電子オルゴールプログラム
ⅰ)プログラムの使い方
ⅱ)曲データコード
ⅲ)曲の速さ
ⅳ)プログラムの説明
2.電子オルゴールデータ
1
1
2
2
3
6
12
17
21
26
33
39
44
50
57
64
70
76
83
89
89
89
89
90
90
95
〒463‐0067 名古屋市守山区守山2-8-14
パレス守山305
有限会社中日電工
℡052‐791‐6254 Fax052‐791‐1391
E‐mail [email protected]
Homepage http://www.tyunitidenko.x0.com/
2016.4.29 Rev. 1.0
2
第1部 ゲームプログラム
ⅰ)はじめに
本編はND8080のためのゲームプログラム集です。
2003年にND80K用の応用プログラム集として編集したものを、2010年にND80ZⅢのために書き直しました。
その後2012年にND80Z3.5用に、内容はそのまま語句のみND80ZⅢをND80Z3.5に書き換えました。
今回(2016年4月)、もとはZ80CPU用として作成したプログラムを8080CPU用に書き改めました。
数日間でZ80プログラムを8080用に書き直さなければならなかったため、Z80なればこそメリットがあったプログラム
をそのまま8080用に書き直すというかなり強引なプログラムになってしまいました。
結果としてプロが作ったと自慢できるほどのプログラムではなくなってしまいました。
ま、その辺はお許しいただくとしまして、序文にありますように、なにはともあれ、レトロな世界をお楽しみください。
2016年4月 (有)中日電工代表者 菱田照久 記
以下は2003年にND80K用として編集した応用プログラムの序文です。
本編はND80Kのためのゲームプログラム集です。
ND80Kは20年前にNECのTK80とソフトコンパチブルとして発売したND80の後継機種です。
発売当初はTK80と同じくCPUは8080でしたが、その後Z80を採用し(NECは8085を使ったTK85を発売した)、
マイコンがパソコンになって、Windows全盛の今日まで、当時に近い機能のまま今日に至っています。
その間参考プログラム集の作成も検討はしてきたのですが、世の動きに合わせて私の関心も機械語からアセンブラへ
移り(8080アセンブラを自作し、ついでに逆アセンブラも作りこれは後にZ80アセンブラ、逆アセンブラに発展します)、
さらにはBASICへと展開していきました。当然のことながらBASICも整数型のBASICからNECのPC8001に刺激さ
れて浮動小数点演算やカラーグラフィック機能をも搭載したBASICの製作とハードの製作という、およそ零細企業にあ
るまじき狂気のふるまいの中に埋没してしまい、ND80のZ80版であるND80Zも改良を続けながら販売しては来たの
ですがいつしか惰性に流され、ND80Z参考プログラム集の製作も着手しないまま今日まで来てしまいました。
ND80KはCPUをZ80から川崎製鉄のKL5C8012に強化するとともに、DOS/Vパソコンと接続してプログラム開
発ができる機能(オプション)をも付加して2000年に発売を開始しました。しかし過去からのいきさつからこのボードを作
ったものの、今更TK80コンパチでもあるまいし、ということで、勿論あらためて参考プログラムを作る気もありませんでし
た。
ところがつい先日(2003年4月)、当社のホームページを見た方から電話をいただき、TK80のシミュレーションソフト
が販売されていること、そしてそれを購入したけれども、やはりパソコン上での模擬体験ではなく実物がさわってみたい、
というお話しを聞きました。
さっそくネットで検索して、はじめてそういうものが売られていることを知りました(いかに自分がTK80から離れていた
かの証左です)。
しかし!これはなんなのだ!ふつうシミュレーションとは実物が容易に体験できないものが対象であるはず(たとえば
航空機の操縦とか、電車でGOとか)。しかるにたかがワンボードマイコンをバーチャルで体験するとは何たる世の中で
あるか!ここに実物が、ND80Kがあるではないか!
もーぜんと闘志がわいてきました。
参考プログラム集も作ってやろーではないか!と怒りにまかせてゴールデンウィークを棒に振って作成したのが本書で
す。
本書中のプログラムのほとんどは、当時出版されていた、岸田孝一著「マイコンゲーム21」(産報出版)からアイデアを
拝借しました。この本はいつか参考プログラム集を出すときに参考にしようと思い、本箱の隅に眠っていたものですが、
私自身はゲームには興味がなくまたそんなひまもなかったのでプログラムを打ち込んでみることもなくそのままになって
いました。
参考プログラム集を作成しようと思い立ったとき真っ先に頭に浮かんだのが「マイコンゲーム21」でした。
TK80ソフトコンパチを売り物にしてきたとはいえ、ND80KはTK80とはクロックもメモリ容量も比較にならぬほど速く、
そして大容量です。「マイコンゲーム21」のニーモニックは8080(インテル)であるのに対して、ND80KではZ80(ザイ
ログ)ニーモニックです。またZ80は8080に倍化する新しい命令が使えます。当然「マイコンゲーム21」のプログラムを
そのまま使うというわけにはいきません。
またどうせ作るなら、「マイコンゲーム21」で作者が述べているように、こちらもプロのプログラマが作ったらこうなると
いうところを見せようではないか、と思い至りました。そこでできるだけ「マイコンゲーム21」のゲームプログラムと同じ動
作をするプログラムを作ってみることにしました。しかしプロの意地でもあって、参考にしたのは各ゲームの説明部分の
みでプログラムリストそのものは読んでいません(説明のみを読んでこの程度のプログラムがすぐに書けないようではプ
ロにはなれません)。
この参考プログラム集は、そういうわけでプロの意地などという不純な動機でもって作成されたもので、良い教科書と
なりうるものではないかもしれません。かなりアクの強いテクニックを随所で用いています。このようなテクニックはプログ
ラマとして必ずしも必要なものではありませんから、敢えて学ぶ必要は無いとも思います。こういうクセは知らず知らずの
1
うちに身にしみついてきてしまいます。初心者にはわかりづらいところがあるかもしれません。そこは「意地」に免じてお
許しください。できるだけ説明を入れるようにしました。
もしも「マイコンゲーム21」をお持ちの方でしたら、両方のプログラムを比較することで、同じ動きをするプログラムでも
作者が違うこととCPUが8080に対してZ80であることで全く異なっている(多分そのはずです)ことに驚かれると思いま
す。
「マイコンゲーム21」にはその名の通り21本のゲームが紹介されています。しかしこの参考プログラム集ではそのうち
何本かは割愛しました。当時と違いパソコンやTVゲームがあるのですから、8ケタのLEDだけで2次元的なゲームを表
現するのは余りに無理があるように感じたからです。
ND80Kは最近のWindowsパソコンから見たらまるで新幹線と自転車のようですが、しかしながらWindowsパソコン
でC++やVisual Basicなどのプログラムを作るのは相当の知識を必要とするのに対し、かえってむずかしいはずの
機械語の方が簡単に扱えるように思えます。
なにはともあれ、レトロなマイコンの世界をじっくりお楽しみ下さい。
2003年5月
(有)中日電工代表者 菱田照久 記
ⅱ)プログラムリストについて
プログラムはWindowsパソコンを使い、当社オリジナルの8080アセンブラ(ASM80)で作成しました。
ND8080は機械語で入力しますから、リストのうち必要なのは左端の4桁のアドレスとその次の機械語コードのみで
す。
TK80は標準ではRAMが8200~83FFまでしか実装されていませんでした(たった512バイト!です)。そのためTK
80用に書かれたプログラムは大抵は8200番地から始っています。
ND8080は標準ではRAMとして32KB(キロバイト)の62256を実装していますから、TK80の64倍のメモリエリア
があることになります。したがってTK80と同じように8200番地からプログラムを書くこともできますが、ND8080はプ
ログラムの開始アドレスは8000番地からとなっているため、通常は8000番地から書くようにします。
プログラムによってはCPUレジスタだけでは不足することがあってRAM上にワークエリアを設けます。システムが使
わなくて、ユーザープログラムとも重ならないRAMアドレスならばどこでもよいのですが、このゲームプログラム集では8
200~に割り当てています。
実はこのゲーム集のプログラムは8080用に新規に作成したものではなくて、Z80用のソースプログラムを8080用に
コンバートして、それに加筆訂正したものです。
そのため8080にはない命令には”?”がついていて、その前後にそれに代わる8080の命令文が書かれています。
ⅲ)附属CDROMのプログラム、データの扱い方
ND8080組立キットの附属CDROMにはこの応用プログラム集に記載したゲームプログラム、電子オルゴールプロ
グラム、曲データが全て収録されています。
CDROM(nd8080フォルダ)にはプログラムがTK80形式のバイナリファイルで入っています(ソースプログラムはA
SM80フォルダにあります)。
nd8080フォルダごとハードディスクにコピーしてください。
プログラムのロードはコマンドプロンプトで操作します。詳細についてはND8080操作説明書、USB接続説明書を参
照してください。
1)TK80モードでの操作を前提にしていますから、ND8080はTK80モニタモードで使ってください。
2)USBケーブルでND8080とWindowsパソコンを接続します。
3)ND8080のキーボードの[REG]キー(TK80モードでは[LOAD]キーとして働きます)を押してください。受信スタン
バイになります。LED表示は変わりませんが[MON]キー([RESET]キー)以外は受け付けなくなります。
4)Windowsパソコンのコマンドプロンプト画面からHIDWR8コマンドを使って、ND8080で実行したいプログラム(拡
張子は.BTKです)を送信します。
>hidwr8 ohayo.btk[Enter]
[注記]プログラムは8000番地からLOADされます。
2
プログラム№1 おはよー(OHAYO8.BTK)
これはゲームではありません。「マイコンゲーム21」にもありません。雑誌だったのか、どういう本に載っていたのかも
思い出せません。実は私自身完全に忘れていました。覚えていたのはうちのカミさんでした。その昔に、私が何かの本を
見てこんな動作をするプログラムを入力して動かしてみせたのを覚えているというのです(げに世の女房族の記憶力に
は恐怖すべきものがあります)。
カミさんの記憶を頼りに作ったのがこのプログラムです。ゲームではありませんが、オープニングの肩ならしにはちょう
どよいと思います。
ではさっそくスタートです。
プログラムを入力して、[8][0][0][0][ADRSSET][RUN]とするとコンピュータが起きあがってのそりのそりと歩き
始めます(LEDに表示されるのは足跡のみ)。目をパチパチさせて、それからゆっくりと「おはよー」と声をかけます(言葉
は話せませんからLEDにそれもローマ字で表示します)。
このプログラムはこれでおしまいです。
プログラムの説明
(以下の説明文に出てくる命令やレジスタの機能などの基本的な内容や詳細は、ND8080に付属の8080命令説明
書を参照してください。またND8080のメモリアドレスやシステムサブルーチン、キーの操作などはND8080操作説明
書を参照してください)
LEDに0~F以外のパターンを表示するとか、表示を全部クリアして(0を表示するのではなくて)ブランクにしたいとき
などは、LED表示アドレス($83F8~$83FF)に直接書き込みます。各アドレスの8ビットのデータのうち1のビットに
対応するLEDのセグメントが点灯し0のビットに対応するセグメントは消灯します。以下のプログラムの中でLED1~LE
D8に対してデータを書き込んでいるところは全部この目的で使われています。
;EYE close/openやサブルーチンCLRがその例です。;ASIATO dispと;ohayo dispでは表示するデータを8
バイト分用意しておいて、全部の表示を順次置換えています。
サブルーチンCLRは$83F8~$83FFに00を書き込むことでLEDを全消灯しています。
;ASIATO dispと;ohayo dispで使っているLDIは8080には無い命令なのでサブルーチンとしました。
本当は機械的にサブルーチン化するのではなくて、目的に合わせて適切なプログラムを書くべきなのですが、時間が
無い中での作業のため、安易な方法になってしまいました。
2016/4/20
END=8087
8000 CD5180
8003 217280
8006 11F883
8009 0E08
800B CD5E80
800E CD8280
8011 C20B80
8014 CD5E80
8017 CD5180
7:39
ohayo8.txt
; OHAYO for NDZ
; 03/04/28 5/9
;10/6/1 for ND80Z3
;16/4/17 for nd8080
;
ORG $8000
LED1=$83F8;$FFF8
LED4=$83FB;$FFFB
START1=$0051;$080F
TM5M=$02DD
;
CALL CLR
;ASIATO disp
LXI H,ASIDT
LXI D,LED1
;
LXI B,$0008
MVI C,08
ASIDP2:CALL TM1S
;?
LDI
CALL LDI;
;
JPE ASIDP2
JNZ ASIDP2
CALL TM1S
CALL CLR
3
801A CD5E80
801D
801F
8022
8025
8028
0603
211C1C
113F3F
22FB83
CD6480
802B
802C
802F
8030
EB
22FB83
EB
CD6180
8033 05
8034 C22580
8037 CD5180
803A 217A80
803D 11F883
8040 0E08
8042 CD6180
8045 CD8280
8048 C24280
804B CD5E80
804E C35100
8051
8054
8057
8058
21F883
010008
71
23
8059 05
805A C25780
805D C9
805E
8061
8064
8065
8067
8068
806B
806C
806D
8070
8071
CD6180
CD6480
D5
1E32
D5
CDDD02
D1
1D
C26780
D1
C9
8072
8073
8074
8075
8076
8077
8078
8079
43
4C
43
4C
43
4C
43
4C
CALL TM1S
;EYE close/open
MVI B,03
LXI H,$1C1C
LXI D,$3F3F
EYE:SHLD LED4
CALL TM025
;?
LD (LED4),DE
XCHG;
SHLD LED4;
XCHG;
CALL TM05
;?
DJNZ *EYE
DCR B
JNZ EYE
CALL CLR
;ohayo disp
LXI H,OHAYODT
LXI D,LED1
;
LXI B,$0008
MVI C,08;
OHYDP2:CALL TM05
;?
LDI
CALL LDI;
;
JPE OHYDP2
JNZ OHYDP2;
CALL TM1S
JMP START1
;LED clear
CLR:LXI H,LED1
LXI B,$0800
CLR2:MOV M,C
INX H
;?
DJNZ *CLR2
DCR B;
JNZ CLR2;
RET
;1sec timer/0.5sec timer/0.25sec timer
TM1S:CALL TM05
TM05:CALL TM025
TM025:PUSH D
MVI E,32;=50
TM025_2:PUSH D
CALL TM5M;4.684ms
POP D
DCR E
JNZ TM025_2
POP D
RET
;asiato data
ASIDT:DB 43
DB 4C
DB 43
DB 4C
DB 43
DB 4C
DB 43
DB 4C
4
807A
807B
807C
807D
807E
807F
8080
8081
3F
76
77
6E
3F
40
40
40
8082
8083
8084
8085
8086
8087
7E
12
23
13
0D
C9
ASIDP2
CLR2
LED1
OHYDP2
TM025_2
TM5M
;"ohayo---"
OHAYODT:DB 3F;O
DB 76;H
DB 77;A
DB 6E;y
DB 3F;O
DB 40;DB,40;DB 40;;
LDI:MOV A,M
STAX D
INX H
INX D
DCR C
RET
;
=800B ASIDT
=8057 EYE
=83F8 LED4
=8042 START1
=8067 TM05
=02DD
=8072
=8025
=83FB
=0051
=8061
CLR
LDI
OHAYODT
TM025
TM1S
=8051
=8082
=807A
=8064
=805E
5
プログラム№2 CRAZY EIGHT(CRAZY88.BTK)
ゲームの説明
8000番地からRUNするとスピーカからピーと音が出て、LEDが全部消え、キー入力待ちになります。
ゲームはLED1~LED8のどこをコンピュータが選ぶか予測してその番号をキー入力するものです。
1~8のいずれかのキーを押すとその数に対応するLEDに”8”の下半分が表示されます。次の瞬間にコンピュータが
選んだ位置に”8”の上半分が表示されます。もし位置が一致すれば”8”の字が完成しピッピッという断続音とともにそ
の”8”が点滅したあと点灯して静止します。位置が異なれば下半分と上半分が離れて表示されるだけで何もおこりませ
ん。続いて残った消灯しているLEDから同じようにコンピュータの選択を予測して、その位置の数をキー入力します。こ
れを繰り返してブランクが全て無くなればゲーム終了です。約2秒後にLEDの右2桁に獲得した点数が表示されます。
点数は”8”ができるごとに加算されます。加算される点数はその”8”の表示直前のLEDが消灯している数になります。
ゲーム開始直後は全部消灯していますから、最初にうまくヒットして”8”ができれば8点ゲットです。失敗すると2ヶ所が
点灯しますから残りは6個で、6点が次の”8”完成によって加算される得点になります。
数を入力するときに間違えて1~8以外のキーを押したり、すでに表示済みのLEDを示す数を入力しても無視されま
す。
点数表示状態でどこかキーを押すと最初にもどって再びゲームが開始されます。このとき得点もゼロクリアされます。
プログラムの説明
CPUのレジスタだけでは足りないのでメモリ上にワークエリアを設けます。キー入力位置を記憶するYRADRS(your
addressのつもり。名前は自分がわかる適当な名前をつける。これはアセンブラに必要なもので機械語に直してしまえ
ば、ただのアドレスになってしまう。この場合は8003)、LEDの残り消灯数を格納するREST、乱数の作業用にRNDD
T、RNDDT2、獲得した点数をカウントするCNTRです。
CNTRは普通のRAMエリアではなくて、システムのデータエリアである83F7を指定しています。
このあたりが機械語プログラムを書くときにアクの強さが出てくるところです。83F7はLEDの表示用のデータエリアで、
このプログラムでは最後の点数表示以外では使用しないのではじめから表示用データエリアをカウンタとして使ってしま
おうというわけです。なおこのカウンタは点数を加算し、それを10進で表示するため、バイナリではなくて10進で演算し
ます。
さてキー入力ですが、1~8の入力のチェックにCPI 09はよいのですが、ORA A、JZとしないのはなぜでしょう?
そうする代わりにDCR A、JMとしています。
こういうところにプログラマの性格が現れます。なんともせっかちな…。
じつはここで入力した数は、そのあとで対応するLEDアドレスを計算するのに使いますが、そこでは1~8ではなくて0
~7でないと都合が悪いのです。どうせ後でDCRするなら、ここでDCRを実行して同時に0キー入力も除外してしまおう
というささやかなアイデアです。
なおLEDアドレスの算出は本来は、
LXI H,LED1
MOV E,A
MVI D,00
DAD D
とするべきです。ここでは、ADD Lとしています。わかっていてするのはテクニックですが初心者は誤解してしまいま
す(教科書としては不適切です)。こういうプログラムを書くと学校のテストなら×になるかもしれません。しかし私が先生
ならこの設定でこのプログラムは◎をあげます。
上で例示したプログラムはどんな場合でも通用するプログラムです。初心者はこう書けば間違いありません。しかし今
回はデータに一定範囲の条件があります。Aの値は0~7で、HL=83F8という条件です。この場合にはADD Lでも、
ORA Lでも構いません。
さてMYTURNでは乱数を使って、コンピュータ側の1~8を発生させています。実際には上と同じ理由で0~7を用い
ています。乱数については後で説明します。
とにかくサブルーチンRND3をCALLすると、00~07の範囲のランダムな数が得られます。プレーヤーが入力した数
(YRADRS)と一致すれば”8”になりますが、それ以外ですでに点灯済みのLEDを選択するのは無効ですから、それを
チェックして、点灯済みなら乱数発生からやりなおします。
結果が不一致の場合にはLEDの残りが2つ減りますから、(REST)に対して2回DECを実行します。その結果(RES
T)=0になったらゲーム終了です。
結果が一致したらヒットです。HIT:でその処理をします。サウンドの出力と、”8”の点滅表示のあと、点数を加算します。
(CNTR)に(REST)を加算します。10進数(BCD)として扱うため10進補正命令、DAAを使っています。
ではなぜ10進数なのか?なぜ10進補正が必要なのか?
それは(CNTR)の値を最後にLEDに表示させるためです。通常の2進演算の場合、09+01は0Aになります。これを
(CNTR)に入れてLEDにそのまま表示させると、0Aと表示されてしまいます。09+01の加算後にDAAを実行するとA
レジスタの値は、10になります。これをそのままLEDに表示すれば10進の計算結果として正しく点数が表示されること
6
になります。
結果が一致したときは、LEDの残りは1つしか減りません。(REST)に対してDCRを1回だけ実行します。その結果
(REST)が奇数の場合と偶数の場合が出てきます。その両方の場合でゲーム終了の判断が異なります。
END:がゲーム終了での処理です。ここでやっとCNTRとしてLEDの表示用データレジスタをそのまま使用したわけが
明らかになります(なんとずる賢い)。
データ表示ルーチン01C0をCALLすれば何もしなくても点数がLEDの右2桁に表示されます。残りの6桁には無関係
な値が表示されてしまいますからLEDレジスタに00を書き込んでLED1~LED6の表示を消してしまいます。
乱数について
ゲームではよくサイコロを使います。ところがコンピュータでサイコロを作るのはなかなか大変なのです。本格的な乱数
発生の計算方法もいろいろ考案されているらしいのですが、たかがワンボードのゲームのために複雑な計算をするのは
ちょっと考え物です。といっていいかげんではゲームになりません。一番よいのは乱数表をメモリに入れておくことなので
すが、仮にそうしたとしても、そのどこを読むかが問題です。毎回同じアドレスを選択したり、その選択する順序が毎回同
じであったりすれば乱数にはなりません。
ここでは擬似的な乱数表として、ROMに書かれたプログラムの命令コードを利用しています。コードの並びはプログラ
ムとしては意味がありますが、数としてみれば大小順序はばらばらで乱数的と言えます。しかし完全ではなくて、よく使
われる命令コードやアドレスは頻繁に現れます。
乱数発生サブルーチンRND3では連続して同じ数が出ないように工夫しています。また次のアドレスを算出するときも
毎回同じ流れにならないようにするため、キー入力のときにコールされるチャタリングタイマーに乱数用の初期値カウン
タR(=FFD2)を組み込んで、タイマーがコールされるたびに+1されるようにして、それを利用しています。
RNDの実行結果はまあまあですが、ときとしてちょっとできの悪いサイコロになることもあります。とりあえずは簡単な
ゲーム用ですから、こんなものでしょう。
2016/4/20
END=8136
8000
8003
8004
8005
8006
8007
8008
800B
800E
800F
8010
8011
C30880
00
00
00
00
00
3AD2FF
210580
77
23
77
CDD880
11:50
crazy88.txt
; CRAZY EIGHT for NDZ
; 03/05/07 5/9
;10/6/1 for ND80Z3
;16/4/16 for nd8080
;4/18 sound,timer
;4/19 rnd
;4/20
;
ORG $8000
;
YRADRS=$E800
;
REST=$E801
;
RNDDT=$E810;$E811
CNTR=$83F7;$FFF7;=DP4
LED1=$83F8;$FFF8
R=$FFD2
;
DTDPS=$01C0;$05C0;DATA DISP
KEYIN1=$0216;$0616
D1=$02DD;4.684msec
;
;data set
JMP START
YRADRS:NOP
REST:NOP
RNDDT:NOP
NOP
RNDDT2:NOP
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
CALL CLR
7
8014
8015
8018
801A
AF
32F783
3E08
320480
801D 3E10
801F 060A
8021 CDE580
8024
8025
8028
802B
802D
8030
8031
05
C22180
CD1602
FE09
D22880
3D
FA2880
8034
8037
803A
803B
803C
803D
803E
8041
320380
21F883
85
6F
7E
B7
C22880
365C
8043 CDBA80
8046
8047
804A
804B
804E
804F
8052
8053
8054
8055
8056
8059
805C
805E
8061
8064
8066
8069
806A
806B
806E
57
3A0380
BA
CA7180
7A
21F883
85
6F
7E
B7
CA6480
3A0480
FE01
CA9F80
C34380
3663
210480
35
35
C22880
C39F80
8071
8074
8075
8076
8078
807A
807C
807E
21F883
85
6F
0E05
367F
3E17
0603
CDE580
XRA A
STA CNTR;DECIMAL COUNTER clear
MVI A,08
STA REST
;GAME START
MVI A,10;puuuu
MVI B,0A
START1:CALL SOUND
;?
DJNZ START1
DCR B;
JNZ START1;
KEY:CALL KEYIN1
CPI 09
JNC KEY
DCR A
JM KEY
;keyin position check
STA YRADRS;position save
LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORA A
JNZ KEY;already used
MVI M,5C;"low" disp
;my turn
MYTURN:CALL RND3;0-7 select
;
ANI 07
MOV D,A
LDA YRADRS
CMP D
JZ HIT
MOV A,D
LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORA A
JZ MYTN2;not used
LDA REST
CPI 01
JZ END;no rest
JMP MYTURN
MYTN2:MVI M,63;"high" disp
LXI H,REST
DCR M
DCR M
JNZ KEY
JMP END
;
HIT:LXI H,LED1
ADD L
MOV L,A
MVI C,05
HIT1:MVI M,7F;"8" disp
MVI A,17;piii
MVI B,03
HIT2:CALL SOUND
8
;?
8081
8082
8085
8087
808A
808B
808E
8090
8093
8096
8097
8098
809B
809C
809F
80A1
05
C27E80
3600
CD2681
0D
C27880
367F
210480
3AF783
86
27
32F783
35
C22880
0614
CD2981
80A4
80A5
80A8
80AB
80AE
80B0
80B1
80B4
80B7
05
C2A180
CDC001
21F883
0606
AF
CDDE80
CD1602
C30880
80BA
80BB
80BC
80BF
80C0
80C1
80C3
80C4
80C7
80CA
80CB
80CC
80CE
80CF
80D2
80D5
80D6
80D7
E5
D5
2A0580
23
7C
E603
67
220580
3A0780
57
7E
E607
BA
CABC80
320780
D1
E1
C9
80D8
80DB
80DC
80DE
80DF
21F883
AF
0608
77
23
80E0 05
80E1 C2DE80
80E4 C9
DJNZ HIT2
DCR B;
JNZ HIT2;
MVI M,00
CALL TM02S
DCR C
JNZ HIT1
MVI M,7F
LXI H,REST
LDA CNTR;point up
ADD M
DAA
STA CNTR
DCR M
JNZ KEY
END:MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
CALL DTDPS
LXI H,LED1
MVI B,06
XRA A
END2:CALL CLR1
CALL KEYIN1
JMP START
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all clear
CLR:LXI H,LED1
XRA A
MVI B,08
CLR1:MOV M,A
INX H
;?
DJNZ *CLR1
DCR B;
JNZ CLR1;
RET
9
80E5
80E6
80E7
80E8
80E9
80EC
80ED
80EE
80EF
80F1
80F2
80F4
80F6
80F7
80F8
80FB
80FC
80FE
8100
8101
8102
8105
8106
8109
810A
810B
810C
810D
F5
E5
D5
C5
210E81
85
6F
46
1E1A
50
3EFF
D398
7F
15
C2F680
50
3EDF
D398
7F
15
C20081
1D
C2F180
C1
D1
E1
F1
C9
810E
810F
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
811A
811B
811C
811D
811E
811F
8120
8121
8122
8123
8124
8125
7F
77
71
6A
5F
59
54
4F
47
43
3F
3B
35
32
2F
2C
25
27
2A
4B
38
64
23
21
8126 CD2981
;
;
SOUND:PUSH PSW
PUSH H
PUSH D
PUSH B
LXI H,SNDTBL
ADD L
MOV L,A
MOV B,M
MVI E,1A
SNDS1:MOV D,B
MVI A,FF;SP OUT=H
OUT 98
SNDS2:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS2;10---MOV D,B
MVI A,DF;sp out=L
OUT 98
SNDS3:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS3;10---DCR E
JNZ SNDS1
POP B
POP D
POP H
POP PSW
RET
; SOUND TABLE
SNDTBL:DB 7F;so4
DB 77;so#4
DB 71;ra4
DB 6A;ra#4
DB 5F;do5
DB 59;do#5
DB 54;re5
DB 4F;re#
DB 47;fA5
DB 43;fa#5
DB 3F;so5
DB 3B;so5#
DB 35;ra#5
DB 32;si5
DB 2F;do6
DB 2C;do#6
DB 25;mi6
DB 27;re#6
DB 2A;re6
DB 4B;mi5
DB 38;ra5
DB 64;si4
DB 23;fa6
DB 21;fa#6
;
;0.2sec timer
TM02S:CALL TM01S
20/2=10microsec
20/2=10microsec
10
8129
812A
812C
812D
8130
8131
8132
8135
8136
D5
1E15
D5
CDDD02
D1
1D
C22C81
D1
C9
CLR
D1
END2
HIT2
LED1
R
RND3
SNDS1
SNDTBL
START1
TM02S
;0.1sec timer
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
=80D8 CLR1
=02DD DTDPS
=80B1 HIT
=807E KEY
=83F8 MYTN2
=FFD2 REST
=80BA RNDDT
=80F1 SNDS2
=810E SOUND
=8021 TM01S
=8126 WAIT
=80DE
=01C0
=8071
=8028
=8064
=8004
=8005
=80F6
=80E5
=8129
=80A1
CNTR
END
HIT1
KEYIN1
MYTURN
RND2
RNDDT2
SNDS3
START
TM01S2
YRADRS
=83F7
=809F
=8078
=0216
=8043
=80BC
=8007
=8100
=8008
=812C
=8003
11
プログラム№3 Hi-Lo(HILO8.BTK)
ゲームの説明
8000番地からRUNするとLEDの左2桁に、--が表示され、右4桁に0000が表示されます。このときコンピュータ
は乱数を利用して4桁の数0000~9999を算出して隠しています。それを当てるゲームです。
キーから適当な数、たとえば4567と入力してWRITE INCキーを押すと、コンピュータは入力された数と、自分が隠
している数とを比較して、入力された数が隠した数よりも大きければLEDの左2桁に、Hi と表示します。小さければ、L
o と表示します。この表示を参考にして、なるべく少ない回数で正解を得るのが目的です。
キーからの数値の入力はWRITE INCキーを押さない限りは何回でも入れなおしができます。
正解が出ると、LEDの左2桁にそれまでの入力回数が表示され、LED全体が約2秒間点滅したあと、最初に戻って新
しい数が選択されてゲームが再開されます。
プログラムの説明
最初にRND4サブルーチンを4回CALLして4桁のBCD数を求めて、HIDNDTに格納します(hidden dataのつもり)。
試行回数をカウントするCNTRは先回のCRAZY EIGHTと同じ手ですが、今回はLEDの左2桁に結果を表示するため、
アドレスは83EFに割り当てています。先回は表示用データレジスタ(83F4~83F7)をカウンタに利用したのですが、
今回はアドレス、データレジスタ(83EC~83EF)を利用しています。今回のプログラムではキー入力された数値をデー
タレジスタに一度格納してからそれを表示するので、カウンタもアドレスレジスタに置かなければなりません。キー入力さ
れた数値はLED表示用データレジスタに置くこともできるのですが、そうするとHとLの位置が逆になるので、プログラム
が少し面倒になります。
(参考)
HLの数値をデータレジスタに入れる場合
SHLD DTRG
HLの数値をLED表示用データレジスタに入れる場合
XCHG
LXI H,DP3;DP3=$83F6
MOV M,D
INX H
MOV M,E
;compare DATA でデータの比較を行っています。HL、DEともにBCD数なので、SBC HL,DE(この命令は80
80にはないのでサブルーチンSBCHLDEをコール)を行っても正しい結果は得られません。しかしここでは差を計算す
ることが目的ではなくて大小がわかればよいので、比較命令としてつかっているのでこれでよいのです。
ALBLNKサブルーチンではND8080のDMAによるLEDの表示機能を利用しています。
LEDの一部だけを点滅させる場合には、表示データを一定時間毎にブランクと入れ替えて表示します。
しかしここでは全部を点灯、消灯すればよいのですから、LED表示回路が行っているDMAによる表示を禁止したり、
許可したりすればよいことになります。LEDONはLED表示のDMA許可ルーチンでLEDOFFはDMA禁止ルーチンで
す。
2016/4/20
END=8102
11:49
hilo8.txt
; Hi-Lo for NDZ
; 03/04/29 4/30 5/1 5/3 5/5 5/9 5/10
;10/6/1 for ND80Z3
;16/4/16 for ND8080
;4/18
;4/19 rnd
;4/20
;
ORG $8000
;
HIDNDT=$E800;$E801
;
RNDDT=$E810;$E811
DTRG=$83EC;$FFEC
ADRG=$83EE;$FFEE
CNTR=$83EF;$FFEF;=ADRGH
LED1=$83F8;$FFF8
12
LED3=$83FA;$FFFA
R=$FFD2
;
ADDPS=$01A1;$05A1
KEYIN1=$0216;$0616
D1=$02DD;4.684msec
;
8000
8003
8004
8005
8006
8007
C30880
00
00
00
00
00
8008
800B
800E
800F
8010
8011
8013
3AD2FF
210580
77
23
77
0604
CD8480
8016
8018
801B
801C
801D
801E
801F
8020
FE0A
D21380
29
29
29
29
B5
6F
8021
8022
8025
8028
802B
802E
8031
8032
8035
8038
803B
05
C21380
220380
210000
22EE83
22EC83
E5
CDA101
21CF80
CDC580
E1
803C
803F
8041
8044
8046
8049
804A
804B
804C
804D
804E
804F
CD1602
FE15
CA5280
FE0A
D23C80
29
29
29
29
B5
6F
C32E80
8052 3AEF83
JMP START
HIDNDT:NOP
NOP
RNDDT:NOP
NOP
RNDDT2:NOP
;data(hidden) set
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
MVI B,04
DTST1:CALL RND4
;
ANI 0F
CPI 0A
JNC DTST1
DAD H
DAD H
DAD H
DAD H
ORA L
MOV L,A
;?
DJNZ *DTST1
DCR B;
JNZ DTST1;
SHLD HIDNDT
LXI H,$0000
SHLD ADRG;DECIMAL COUNTER clear
REENT:SHLD DTRG
PUSH H
CALL ADDPS
LXI H,STDT
REENT1:CALL H4DP
POP H
;key entry(0000-9999)
KEY:CALL KEYIN1
CPI 15;WRITE INC
JZ COMP
CPI 0A
JNC KEY
DAD H
DAD H
DAD H
DAD H
ORA L
MOV L,A
JMP REENT
;compare DATA
COMP:LDA CNTR;DECIMAL COUNTER up
13
8055
8057
8058
805B
C601
27
32EF83
B7
805C
805D
8060
8061
EB
2A0380
EB
E5
8062
8065
8068
806B
806E
8071
8074
8075
8078
807B
CDDB80
CA7480
21D780
DA3880
21D380
C33880
E1
CDA101
210000
22FA83
807E CDA280
8081 C30880
8084
8085
8086
8089
808A
808B
808D
808E
8091
8094
8095
8096
8098
8099
809C
809F
80A0
80A1
E5
D5
2A0580
23
7C
E603
67
220580
3A0780
57
7E
E60F
BA
CA8680
320780
D1
E1
C9
80A2
80A4
80A6
80A8
80AB
80AD
80AF
060A
3EEF
D398
CDB780
3EFF
D398
CDB780
80B2 05
80B3 C2A480
80B6 C9
ADI 01
DAA
STA CNTR
ORA A;clear CARRY
;?
LD DE,(HIDNDT)
XCHG;
LHLD HIDNDT;
XCHG;
PUSH H
;?
SBC HL,DE
CALL SBCHLDE;
JZ SAME
LXI H,LODT
JC REENT1
LXI H,HIDT
JMP REENT1
SAME:POP H
CALL ADDPS
LXI H,$0000
SHLD LED3
;OK! ALL LED blink
CALL ALBLNK
JMP START
;
;ransu
RND4:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 0F
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98;LED OFF
CALL TM01S
MVI A,FF
OUT 98;LED ON
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;0.1sec timer
14
80B7
80B8
80BA
80BB
80BE
80BF
80C0
80C3
80C4
D5
1E15
D5
CDDD02
D1
1D
C2BA80
D1
C9
80C5 11F883
80C8 010400
80CB CDF680
80CE C9
80CF
80D0
80D1
80D2
80D3
80D4
80D5
80D6
80D7
80D8
80D9
80DA
40
40
00
00
76
06
00
00
38
3F
00
00
80DB
80DC
80DD
80DE
80DF
80E0
80E1
80E2
80E3
80E6
80E9
80EA
80ED
80EE
80EF
80F0
80F2
80F3
80F4
80F5
C5
47
7D
9B
6F
7C
9A
67
DAED80
FAED80
B5
C2F080
78
C1
C9
3E01
B7
78
C1
C9
80F6
80F7
80F8
80F9
80FA
80FB
80FC
F5
7E
12
23
13
0B
78
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
;High 4 disp
H4DP:LXI D,LED1
LXI B,$0004
;?
LDIR
CALL LDIR;
RET
;
STDT:DB 40
DB 40
DB 00
DB 00
HIDT:DB 76;H
DB 06;i
DB 00
DB 00
LODT:DB 38;L
DB 3F;O
DB 00
DB 00
;
SBCHLDE:PUSH B
MOV B,A
MOV A,L
SBB E
MOV L,A
MOV A,H
SBB D
MOV H,A
JC SBCHLDE1
JM SBCHLDE1
ORA L
JNZ SBCHLDE2
SBCHLDE1:MOV A,B
POP B
RET
SBCHLDE2:MVI A,01
ORA A;clear sf
MOV A,B
POP B
RET
;
LDIR:PUSH PSW
LDIR2:MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
15
80FD
80FE
8101
8102
B1
C2F780
F1
C9
ADDPS
ALBLNK1
D1
H4DP
KEY
LDIR2
LODT
REENT1
RNDDT
SBCHLDE
START
TM01S2
ORA C
JNZ LDIR2
POP PSW
RET
;
=01A1
=80A4
=02DD
=80C5
=803C
=80F7
=80D7
=8038
=8005
=80DB
=8008
=80BA
ADRG
CNTR
DTRG
HIDNDT
KEYIN1
LED1
R
RND2
RNDDT2
SBCHLDE1
STDT
=83EE
=83EF
=83EC
=8003
=0216
=83F8
=FFD2
=8086
=8007
=80ED
=80CF
ALBLNK
COMP
DTST1
HIDT
LDIR
LED3
REENT
RND4
SAME
SBCHLDE2
TM01S
=80A2
=8052
=8013
=80D3
=80F6
=83FA
=802E
=8084
=8074
=80F0
=80B7
16
プログラム№4 FLIPFLOP(FLIPFLOP8.BTK)
ゲームの説明
8000番地からRUNするとLEDに”8”の上半分が8個表示されます。各桁を示す1~8の数をキーから入力すると、
その位置のLEDが点滅します。それでよければWRITE INCキーを押します。WRITE INCキーを押す前なら別の数
を入れなおして位置の指定を変更することができます。WRITE INCを押すと指定位置の今点滅しているLEDの表示
が上下反転します。上半分の表示は下半分の表示になり、下半分の表示は逆に上半分の表示になります。ゲーム開始
時点でコンピュータは乱数によって各LEDに別のLEDを結びつけています。そのため、指定位置のLEDが反転すると
ともに関係つけられた別のLEDも一緒に反転してしまいます。関係つけのリンクは1本のみで、自分自身を指定してい
るときもあります。この場合には他のLEDは反転しません。関係つけの方向は一方向のみです。たとえばLED1を指定
したときにLED3が同時に反転したとしても、次にLED3を指定したときにLED1も同時に反転するとは限りません。逆
にLED3はLED6からも関係つけられているかもしれません。その場合はLED1を指定しても、LED6を指定してもそれ
ぞれ同時にLED3が反転することになります。
首尾良く全部の表示が下半分になると、全部の表示が点滅し2秒後に、それまでの試行回数が表示されます。さらに
2秒たつと最初からゲームが再スタートします。関係つけによってはエンドレスになってしまってゲームが終了しない場
合もあります。そんなときはリセットしてもう一度8000番地からRUNしてください。
プログラムの説明
このプログラムでは各LEDにリンクされているLEDの番号を格納する場所としてLINKBF(8バイト)を用意しています。
はじめに各LED位置毎にRND3サブルーチンによって1~8(実際には0~7)を求めて対応するLINKBF以降の8バイ
トに順に数を割り当てて行きます。
KEY:ではLED表示静止の状態でキー入力を待つため、KEYIN1($0216)をCAllしていますが、BLNK0:以下の
部分では表示をブリンクさせながらキーの入力をチェックしなければならないため、KEYIN2($0223)をCALLしてい
ます。
2016/4/20
END=8104
8000
8003
8004
8005
8006
8007
8008
8009
C30E80
00
00
00
00
00
00
00
11:51
flipflp8.txt
; FLIP-FLOP for NDZ
; 03/04/29 4/30 5/1 5/3 5/5 5/10
;10/6/1 for ND80Z3
;16/4/16 for ND8080
;4/17
;4/19
;4/20
;
ORG $8000
;
LINKBF=$E800
;
RNDDT=$E810;$E811
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
KEYIN2=$0223;$0623
D1=$02DD;4.684msec
;
JMP START
LINKBF:NOP
NOP
NOP
NOP
NOP
NOP
NOP
17
800A
800B
800C
800D
00
00
00
00
800E
8011
8014
8015
8016
8017
8019
801B
801E
801F
3AD2FF
210B80
77
23
77
3E63
0608
21F883
77
23
8020
8021
8024
8027
802A
05
C21E80
210000
22F683
22F483
802D 0608
802F 210380
8032 CDC480
8035 77
8036 23
8037 05
8038 C23280
803B
803E
8040
8043
8044
CD1602
FE09
D23B80
3D
FA3B80
8047
804A
804B
804C
804D
804E
8050
8051
8054
8055
8056
8059
805A
805B
805D
8060
8061
8064
8065
8068
21F883
85
6F
56
42
0E00
71
CDF780
D5
C5
CD2302
C1
D1
FE09
D26880
3D
FA6D80
72
C34780
FE15
NOP
RNDDT:NOP
NOP
RNDDT2:NOP
;all"UP" disp
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
MVI A,63;"UP"
MVI B,08
LXI H,LED1
UPDP1:MOV M,A
INX H
;?
DJNZ UPDP1
DCR B;
JNZ UPDP1;
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
SHLD DP1
;LINK set
MVI B,08
LXI H,LINKBF
LNKST1:CALL RND3
;
ANI 07
MOV M,A
INX H
;?
DJNZ LNKST1
DCR B;
JNZ LNKST1;
;key entry
KEY:CALL KEYIN1
CPI 09
JNC KEY
DCR A
JM KEY
;LED blink and wait WINC in
BLNK0:LXI H,LED1
ADD L
MOV L,A
MOV D,M;LED data save
MOV B,D
MVI C,00
BLNK1:MOV M,C
CALL TM01S
PUSH D
PUSH B
CALL KEYIN2
POP B
POP D
CPI 09
JNC BLNK2
DCR A
JM BLNK3
MOV M,D
JMP BLNK0
BLNK2:CPI 15;WRITE INC
18
806A
806D
806E
806F
8070
CA7380
79
48
47
C35080
8073
8074
8076
8077
807A
807C
72
3E63
BE
C27C80
3E5C
77
807D
807E
8080
8081
8084
8085
8086
8087
8088
808B
808E
808F
8090
8092
8093
8096
8098
8099
809C
809E
809F
7D
E607
57
210380
85
6F
7E
BA
CA9980
21F883
85
6F
3E63
BE
C29880
3E5C
77
3AF783
C601
27
32F783
80A2
80A5
80A7
80A9
80AA
80AD
21F883
0608
3E5C
BE
C23B80
23
80AE 05
80AF C2A980
80B2
80B5
80B8
80BA
CDE280
CDC001
0614
CDF780
80BD 05
80BE C2BA80
80C1 C30E80
80C4 E5
80C5 D5
80C6 2A0B80
JZ REVRS
BLNK3:MOV A,C
MOV C,B
MOV B,A
JMP BLNK1
;LED reverse
REVRS:MOV M,D
MVI A,63;"UP"
CMP M
JNZ REVRS1
MVI A,5C;"DOWN"
REVRS1:MOV M,A
;link LED reverse
MOV A,L
ANI 07
MOV D,A; No. save
LXI H,LINKBF
ADD L
MOV L,A
MOV A,M
CMP D
JZ REVRS3;same No.(no LINK)
LXI H,LED1
ADD L
MOV L,A
MVI A,63;"UP"
CMP M
JNZ REVRS2
MVI A,5C;"DOWN"
REVRS2:MOV M,A
REVRS3:LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
;check
LXI H,LED1
MVI B,08
MVI A,5C;"DOWN"
CK1:CMP M
JNZ KEY;not success
INX H
;?
DJNZ *CK1
DCR B;
JNZ CK1;
;OK! ALL LED blink and COUNTER disp
CALL ALBLNK
CALL DTDPS
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
19
80C9
80CA
80CB
80CD
80CE
80D1
80D4
80D5
80D6
80D8
80D9
80DC
80DF
80E0
80E1
80E2
80E4
80E6
80E8
80EB
80ED
80EF
23
7C
E603
67
220B80
3A0D80
57
7E
E607
BA
CAC680
320D80
D1
E1
C9
060A
3EEF
D398
CDF780
3EFF
D398
CDF780
80F2 05
80F3 C2E480
80F6 C9
80F7 D5
80F8 C5
80F9 0615
80FB CDDD02
80FE 05
80FF C2FB80
8102 C1
8103 D1
8104 C9
ALBLNK
BLNK1
CK1
DP1
KEY
LED1
R
REVRS2
RND3
START
UPDP1
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF;LED OFF
OUT 98
CALL TM01S
MVI A,FF;LED ON
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;0.1sec timer
TM01S:PUSH D
PUSH B
MVI B,15;=21
TM01S2:;CALL TM1M
CALL D1;4.684ms
DCR B
JNZ TM01S2
POP B
POP D
RET
=80E2 ALBLNK1
=80E4
=8050 BLNK2
=8068
=80A9 CNTR
=83F7
=83F4 DP3
=83F6
=803B KEYIN1
=0216
=83F8 LINKBF
=8003
=FFD2 REVRS
=8073
=8098 REVRS3
=8099
=80C4 RNDDT
=800B
=800E TM01S
=80F7
=801E WAIT
=80BA
BLNK0
BLNK3
D1
DTDPS
KEYIN2
LNKST1
REVRS1
RND2
RNDDT2
TM01S2
=8047
=806D
=02DD
=01C0
=0223
=8032
=807C
=80C6
=800D
=80FB
20
プログラム№5 SWAP(SWAP8.BTK)
ゲームの説明
8000番地からRUNするとLEDの左3桁に”8”の下半分が表示されその右に1桁のブランクがあってさらに右3桁に
は”8”の上半分が表示されます。右端の1桁はブランクでこの桁は使用しません。
ルールにしたがって表示を移動し、左3桁の表示と右3桁の表示を上下入れ替えるのがゲームの目的です。
ルールは次の通りです。
1)ブランクの隣の表示はブランクと位置を交代することができます。
2)隣に異なる表示があるとき、その表示をはさんでさらにその隣がブランクならば、間の表示を飛び越してブランクと表
示位置を交代することができます。たとえば表示が[下][上][ブランク]とならんでいる時、[下]のLED番号をKEY入力
すると、[ブランク][上][下]に表示が入れ替わります。ルールに合わない表示を指定しても無視されます。
入れ替えたいLED位置を示す数をKEY入力するとその位置のLEDが点滅します。それでよければWRITE INCキー
を押します。WRITE INCキーを押す前なら別の数を入れなおして位置の指定を変更することができます。WRITE IN
Cを押すとルールにしたがって表示とブランクが入れ替わります。ルールに合わない場合には点滅は続きますが入れ替
えは行われません。
うまく全部の入れ替えに成功すると2秒間表示が点滅し、さらに2秒間試行回数が表示されたあと、最初に戻って再び
ゲームが開始されます。
プログラムの説明
このプログラムではシステムのワークエリア以外は使用しません。LED表示はLED表示用のアドレスをそのまま使用
しています。また乱数も使いません。その割りには結構ややこしいプログラムです。こういうプログラムが得意な人と不
得意な人がでてきます。いかにもコンピュータ的なプログラムです。ややこしいのは、場合分けが何通りもあるからです。
こういう作業が苦手なプログラマは何か別のうまい方法を考えようとします。それはそれでよいので、こう書かなければ
ならないというきまりはありません。こういうところでプログラマの個性が出て来ます。
私はというと割りと得意というか、苦にならない方なので、こんな感じに書いてしまいます。
場合分けはまずキー入力されたLED位置の左の状態を確認して、それから右を確認します。右から見ていっても構い
ません(たまたま私は左利きなのでどうしても左が先になってしまいます)。
順に確認します。CHECK:のルーチンです。
①入力した番号のLEDは左端か?これはLEDアドレスの下位3ビットが0であることで確認できます(LED1=$FFF
8)。このときは右側のチェックに行きます。
②1 つ左はブランクか?左のLEDアドレスのデータが00ならブランクです。置換えルーチンへ行きます。
③1つ左は自分(KEY入力したLEDアドレス)と同じ表示データか?同じ場合は右側のチェックに行きます。
④1つ左のLEDは左端か?これは①と同じ方法でチェックできます。この場合は右側のチェックに行きます。
⑤もう 1 つ左はブランクか?この場合は置き換えルーチンへ行きます。ブランクでない場合は左側のチェックは終了です。
右側のチェックに行きます。
右側のチェックの説明は省略しますが、やっていることは同じことです。
2016/4/18
END=810D
8000 21F280
8003 11F883
14:8
swap8.txt
; SWAP for NDZ
; 03/04/29 4/30 5/2 5/3 5/5 5/10
;10/6/2 for ND80Z3
;16/4/18 for nd8080
;
ORG $8000
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
KEYIN2=$0223;$0623
D1=$02DD;4.684sec
;
;start data disp
START:LXI H,STDT
LXI D,LED1
21
8006 010800
LXI B,$0008
LDIR
CALL LDIR;
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
SHLD DP1
;key entry
KEY:CALL KEYIN1S;1-7 input
CPI 08
JNC KEY
DCR A
JM KEY
;LED blink and wait WINC in
BLNK0:LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORA A
JZ KEY;space position
MOV D,A;LED data save
MOV B,A
MVI C,00
BLNK1:MOV M,C
CALL TM01S
CALL KEYIN2S;1-7,15 input
CPI 08
JNC BLNK2
DCR A
JM BLNK3
MOV M,D
JMP BLNK0
BLNK2:CPI 15;WRITE INC
JZ CHECK
BLNK3:MOV A,C
MOV C,B
MOV B,A
JMP BLNK1
;check
CHECK:MOV A,L
PUSH H;save HL(current position)
ANI 07
JZ CHECKR;position=LED1
DCX H
MOV A,M
ORA A
JZ REP;left=space
CMP D
JZ CHECKR;left=same
MOV A,L
ANI 07
JZ CHECKR;left=LED1
DCX H
MOV A,M
ORA A
JZ REP;left of left=space
CHECKR:POP H
PUSH H
MOV A,L
;?
8009
800C
800F
8012
CD0181
210000
22F683
22F483
8015
8018
801A
801D
801E
CDBF80
FE08
D21580
3D
FA1580
8021
8024
8025
8026
8027
8028
802B
802C
802D
802F
8030
8033
8036
8038
803B
803C
803F
8040
8043
8045
8048
8049
804A
804B
21F883
85
6F
7E
B7
CA1580
57
47
0E00
71
CDE480
CDC780
FE08
D24380
3D
FA4880
72
C32180
FE15
CA4E80
79
48
47
C32F80
804E
804F
8050
8052
8055
8056
8057
8058
805B
805C
805F
8060
8062
8065
8066
8067
8068
806B
806C
806D
7D
E5
E607
CA6B80
2B
7E
B7
CA8980
BA
CA6B80
7D
E607
CA6B80
2B
7E
B7
CA8980
E1
E5
7D
22
806E
8070
8073
8074
8075
8076
8079
807A
807D
807E
8080
8083
8084
8085
8086
FEFE
CABB80
23
7E
B7
CA8980
BA
CABB80
7D
FEFE
CABB80
23
7E
B7
C2BB80
8089
808A
808B
808D
8090
8092
8093
72
E1
3600
3AF783
C601
27
32F783
8096
8099
809C
809E
809F
80A0
80A3
80A4
21F883
11FA80
0607
1A
BE
C21580
23
13
80A5 05
80A6 C29E80
80A9
80AC
80AF
80B1
CDCF80
CDC001
0614
CDE480
80B4 05
80B5 C2B180
80B8 C30080
80BB E1
80BC C34880
80BF
80C0
80C1
80C4
80C5
80C6
80C7
80C8
80C9
C5
D5
CD1602
D1
C1
C9
C5
D5
CD2302
CPI FE
JZ CANT;position=LED7,cannot replace
INX H
MOV A,M
ORA A
JZ REP;right=space
CMP D
JZ CANT;right=same,cannot replace
MOV A,L
CPI FE
JZ CANT;right=LED7,cannot replace
INX H
MOV A,M
ORA A
JNZ CANT;right of right is not space,cannot replace
;replace
REP:MOV M,D;set current DATA to space position
POP H
MVI M,00;set space to current position
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
;all check
LXI H,LED1
LXI D,ENDDT
MVI B,07
ALCHK1:LDAX D
CMP M
JNZ KEY;not success
INX H
INX D
;?
DJNZ *ALCHK1
DCR B;
JNZ ALCHK1;
;OK! ALL LED blink and COUNTER disp
CALL ALBLNK
CALL DTDPS
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;cannot replace
CANT:POP H
JMP BLNK3
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
23
80CC D1
80CD C1
80CE C9
80CF
80D1
80D3
80D5
80D8
80DA
80DC
060A
3EEF
D398
CDE480
3EFF
D398
CDE480
80DF 05
80E0 C2D180
80E3 C9
80E4
80E5
80E7
80E8
80EB
80EC
80ED
80F0
80F1
D5
1E15
D5
CDDD02
D1
1D
C2E780
D1
C9
80F2
80F3
80F4
80F5
80F6
80F7
80F8
80F9
5C
5C
5C
00
63
63
63
00
80FA
80FB
80FC
80FD
80FE
80FF
8100
63
63
63
00
5C
5C
5C
8101
8102
8103
8104
8105
8106
8107
8108
8109
810C
810D
F5
7E
12
23
13
0B
78
B1
C20281
F1
C9
ALBLNK
POP D
POP B
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
STDT:DB 5C
DB 5C
DB 5C
DB 00
DB 63
DB 63
DB 63
DB 00
;
ENDDT:DB 63
DB 63
DB 63
DB 00
DB 5C
DB 5C
DB 5C
;
LDIR:PUSH PSW
LDIR2:MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ LDIR2
POP PSW
RET
;
=80CF ALBLNK1
=80D1
ALCHK1
=809E
24
BLNK0
BLNK3
CHECKR
DP1
ENDDT
KEYIN1S
LDIR
REP
TM01S
=8021
=8048
=806B
=83F4
=80FA
=80BF
=8101
=8089
=80E4
BLNK1
CANT
CNTR
DP3
KEY
KEYIN2
LDIR2
START
TM01S2
=802F
=80BB
=83F7
=83F6
=8015
=0223
=8102
=8000
=80E7
BLNK2
CHECK
D1
DTDPS
KEYIN1
KEYIN2S
LED1
STDT
WAIT
=8043
=804E
=02DD
=01C0
=0216
=80C7
=83F8
=80F2
=80B1
25
プログラム№6 CATCH(CATCH8.BTK)
ゲームの説明
これはコンピュータ相手の鬼ごっこ(正確には追いかけっこ)です。
8000番地からRUNするとLEDのどこかに上向きのマーク(CUP)と下向きのマーク(CAP)がそれぞれ1個表示され
ます。CUPがプレーヤーでCAPがコンピュータです。最初の表示位置は乱数で決定します。CUPが点滅してKEY入力
待ちであることを示します。プレーヤーはCUPを右に動かすか、左に動かすかを決めてKEY入力します。左に移動する
なら[0]を、右に移動するなら[WRITE INC]を押します。移動量はコンピュータが乱数で求めます。CUPが移動して、
CAPと同じ位置で止まれば、プレーヤーの勝ちです。ピーと音がしてCAPが消滅します。CAPと同じ位置で止まらなか
ったときはCAPが移動する番です。コンピュータがCAPをどちらにいくつ移動するかを乱数で求めてそのとおりに移動し
ます。移動の結果CUPと同じ位置で止まるとコンピュータの勝ちです。ブーと音がしてCUPが消滅します。どちらかが消
滅するとゲームは終りです。2秒たつと始めに戻って再びゲームが開始されます。
なおゲーム開始時にCUPとCAPが同じ位置に表示されることがあります。この場合プレーヤーはまずCAPから逃げ
ることから開始することになります。またLEDの左端と右端はリング状につながっていることとしています。左端からさら
に左に移動したマークは右端から出現します。逆に右端からさらに右に移動したマークは左端から現れます。
プログラムの説明
作業用のメモリとしてMYADRS(my address,コンピュータ側の表示位置を記憶)とYRADRS(your address,プ
レーヤーの表示位置を記憶)の各1バイトとRNDDT、RNDDT2(乱数用)を使います。それだけで済むのですから簡単
かというと処理はかなり複雑です。動作のポイントはプレーヤーもコンピュータも左か右に指定しただけ移動することと、
移動後に相手の位置を確認して、キャッチできたかどうかを判定することです。
ここで、うーむと考えると、どうもコンピュータとプレーヤーは表示マークが違うだけで、同じプログラムで動かせるので
はないか、という気がします。ここが一番重要なポイントです。
そう考えた結果2つのサブルーチンを作りました。DTSETとSTEPです。
DTSETはゲーム開始時のCUPとCAPの位置を乱数で選び、その位置情報をメモリに入れるとともに、それぞれのマ
ークを表示します。Eレジスタに表示マークを、BCレジスタに位置情報を格納するメモリアドレスを入れてDTSETをCAL
Lするようにできています。このようにすることで、サブルーチンは与えられた情報の内容に関係無くまさに「機械的」に
処理をすることで目的の動作をしてしまいます。
こういうサブルーチン(場合によってはプログラム全体がこういうつくりになっているものもある)の特徴はそのサブルー
チンだけを見ると、何をやっているのかさっぱりわからないということにあります。CLRとDTSETを比べてみるとそのこと
がよくわかると思います。ではDTSETは悪いプログラムなのかというと、むしろDTSETの方がよりコンピュータ的で、よ
り望ましいプログラムなのだと言えます(まああまりこだわって無理にしなくても、基本的には好きなように書けばよいわ
けですけれど)。
たとえば良く似た処理を10回個々にプログラムするよりは何とか工夫して同じサブルーチンをCALLするようにした方
がすっきりまとまります。これが100回となるとこれはもう絶対にそうすべきです。こうすることの最大のメリットはとにかく
プログラムが短くまとまる(ということはプログラム自体がフローチャート風になって、分かりやすくなる)ことです。ことの
ついでですが、プロは滅多にフローチャートは書きません(私だけか?!)。たいていはひとりで始めから終わりまでひと
つのプログラムを書くことになるので、その場合、ここで紹介している程度のプログラムなら、フローチャートは必要あり
ません。やるべきことを、たとえば上で説明したゲームのルールをざっと読んで、理解すると、あとは頭の中でああやっ
てこうやってと自然にプログラムの流れが出来てきます。あとはいきなりパソコンに向かってアセンブラのニーモニックを
打ち込みはじめます(何と原始的な!)。
ちょっと長いプログラムなら使いたいワークエリアのアドレスとか名前をメモしたり、処理の概略チャートをメモ風にかく
こともあります。しかし、教科書にのっているようなチャートを書いているよりも直接プログラムを書いた方が速いので
す!
プログラムに慣れてくると、少なくとも自分で書いたプログラムならば、チャートなどなくても、プログラムリストを見れば
何をやっているのか分かります。あとで分からなくなるかなあと思ったときは、必要と思われるコメントを書き込んでおけ
ば十分です。
これはあくまで個人で仕事をする場合の話で、グループで作業をする場合には、チャートが必要なこともあると思いま
す(何事もケースバイケースです)。ともあれ私個人としてはチャートは面倒ですから、書きません。このプログラム集の
プログラムに書き込んでいるコメントも大半は読者向けのもので自分用には殆ど不要です(実際、たった少しのコメントを
プログラム中に書きこむのさえ、怠惰なプログラマにとっては面倒なのです)。
さて余計なことを書きすぎました。もうひとつサブルーチン化のメリットがあります。それはチェックや修正が容易な点で
す。プログラムは書いていきなり完成ということはまずありません。こんな短いプログラムでもそうです。ここで紹介したプ
ログラムも一度では終っていません。リストの最初に日付が覚えとして書いてあります。何回も訂正していることが分か
ります。こういうときにサブルーチンになっていると、そこだけ直せば済んでしまいます。同じような処理を何回もだらだら
書いたプログラムでは、バグ修正が大変です。
26
サブルーチン化にはデメリットもあります。はじめに書いたように、そこだけ読んでもなにをやっているのかよくわからな
いという点です。この点についてはたとえばプリントアウトしたリストに処理されるデータの1つを実際に書きこむなどして、
ブログラムをあらためてながめてみると、流れが見えてきます。
と無理矢理納得していただいたところでもうひとつのサブルーチンSTEPについて説明します。こちらはちょっと複雑で
す。サブルーチンに与えるべきデータ(これをパラメータとか引数とかといいます)がちょっと多くて分かりづらいかもしれ
ません。
現在自分のマークが表示されているLEDアドレス(HLレジスタ)、右へ行くのか左へ行くのか(Cレジスタ)、移動後に
現在の表示を消すためのマスク(同じ場所に相手も表示している場合を考えて、自分だけを消すようにする。Dレジスタ)、
移動後に表示するマーク(Eレジスタ)、移動後の位置情報を格納するメモリアドレス(もとはIXレジスタを使っていたが8
080にはないためそれに代わるワークエリアとしてADRSWKを使う)、とこれだけのデータをサブルーチンに与えます。
データが沢山あってなんだかややこしそうですがこれらのデータをサブルーチンのリストの各レジスタのところにメモなど
して、あらためてながめてみると、それほど複雑ではないことがわかると思います。
このサブルーチンで特にコメントしたいのがCレジスタの値です。これがテクニックです。左に行くか右に行くかをFFか0
1で示しています。どこがテクニックか?
左に行くということは現在表示しているLEDのアドレス(83F8~83FFのいずれか)から-1することです。右に行くの
は逆にアドレスを+1することです。-1はDCR、+1はINRを普通は使います。あるいはSUI 01かADI 01を使いま
す。ここから先はわからない人にはわかりません。
突然無関係のように登場したFFですが、FFを10進に直すと255です。これではわかりません。FFにはもうひとつの
意味があります。FFを符号付の数として10進に直すと-1なのです!これは約束事なのですがでたらめに決めたので
はなくて計算上の根拠があっての話なのです。SUI 01の代わりにADI FFとしても不思議なことに結果は同じになっ
てしまうのです(フラグは異なります)。どーしても納得ができない人は試してみてください。
このことを利用して本来加算と減算にしなければならないはずのところを同じADD Cで切りぬけているのです。もうひ
とつ、加算後にORI F8としている部分です。これによって加算後に結果がオーバフロー(下位アドレスがF8~FFの範
囲を超えてしまう)してもリング状に左端と右端がつながったように結果が計算されます。これも納得できない人は試して
みてください。
ことのついでにMYTURN:のところでRNDの結果から、右と左を示す01とFFをさらりと作り出しているところに注目し
てください。自画自賛ですがこのようにきれいに決まるとヤッターという気になって心が踊ります。
2016/4/20
END=8169
8000
8003
8004
8005
8006
8007
8008
8009
C30A80
00
00
00
00
00
00
00
11:51
catch8.txt
; CATCH for NDZ
; 03/05/06 5/10
;10/6/2 for ND80Z3
;16/4/15 for ND8080
;16/4/15 timer
;4/18
;4/19
;4/20
;
ORG $8000
;
MYADRS=$E800
;
YRADRS=$E801
;
RNDDT=$E810;$E811
LED1=$83F8;$FFF8
R=$FFD2
;
KEYIN2=$0223;$0623
D1=$02DD;4.684msec
;
JMP START
MYADRS:NOP
YRADRS:NOP
ADRSWK:NOP
NOP
RNDDT:NOP
NOP
RNDDT2:NOP
27
800A
800D
8010
8011
8012
8013
3AD2FF
210780
77
23
77
CDD080
8016 1E23
8018 010380
801B CDDD80
801E 1E1C
8020 03
8021 CDDD80
8024
8027
802A
802B
802C
802D
802E
3A0480
21F883
85
6F
56
42
0E00
8030
8031
8034
8037
8038
803B
803D
8040
8041
8042
8043
8046
8048
804B
804D
71
CD5C81
CD1081
B7
CA4680
FE15
CA4B80
59
48
43
C33080
0EFF
C34D80
0E01
111CE3
8050
8051
8054
8057
8058
E5
210480
220580
E1
CDEA80
805B
805C
805F
8060
8063
8064
8065
E5
2A0580
2B
220580
BE
E1
C27180
8068 7E
;data set
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
CALL CLR
;my position select
MVI E,23;cap
LXI B,MYADRS
CALL DTSET
;your posision select
MVI E,1C;cup
INX B
CALL DTSET
;GAME START
;your turn
REENT:LDA YRADRS
LXI H,LED1
ADD L
MOV L,A
MOV D,M;LED data save
MOV B,D
MVI C,00
;blink and keyin
KEY:MOV M,C
CALL TM01S
CALL KEYIN2S
ORA A
JZ LEFT
CPI 15;W INC
JZ RIGHT
MOV E,C
MOV C,B
MOV B,E
JMP KEY
LEFT:MVI C,FF
JMP RIGHT2
RIGHT:MVI C,01
RIGHT2:LXI D,$E31C;see STEP comment line
;?
LD IX,YRADRS
PUSH H;
LXI H,YRADRS;
SHLD ADRSWK;
POP H;
CALL STEP
;catch?
;?
DEC IX;MYADRS
;?
CP (IX+00)
PUSH H;
LHLD ADRSWK;
DCX H;
SHLD ADRSWK;
CMP M;
POP H;
JNZ MYTURN
;catch!
MOV A,M
28
8069
806B
806C
806E
E6DC
77
3E17
C39D80
8071
8074
8076
8079
807A
807B
807E
807F
8082
8083
8084
8087
CDB280
E601
C27A80
3D
4F
2A0580
7E
21F883
85
6F
1123DC
CDEA80
808A
808B
808E
808F
8092
8093
8094
E5
2A0580
23
220580
BE
E1
C22480
8097
8098
809A
809B
809D
809F
7E
E6E3
77
3E00
0605
CD1881
80A2
80A3
80A6
80A8
05
C29F80
0614
CD5C81
80AB 05
80AC C2A880
80AF C30A80
80B2
80B3
80B4
80B7
80B8
80B9
80BB
80BC
80BF
80C2
80C3
80C4
80C6
E5
D5
2A0780
23
7C
E603
67
220780
3A0980
57
7E
E607
BA
ANI DC;cap clear
MOV M,A
MVI A,17;piiii
JMP END
;my turn
MYTURN:CALL RND3;LEFT(FF) or RIGHT(01) select
ANI 01
JNZ MYTURN1;=01
DCR A;=FF
MYTURN1:MOV C,A
LHLD ADRSWK
MOV A,M
LXI H,LED1
ADD L
MOV L,A
LXI D,$DC23;see STEP comment line
CALL STEP
;catch?
;?
INC IX;YRADRS
;?
CP (IX+00)
PUSH H;
LHLD ADRSWK;
INX H;
SHLD ADRSWK;
CMP M;
POP H;
JNZ REENT
;catch!
MOV A,M
ANI E3;cup clear
MOV M,A
MVI A,00;buuuu
END:MVI B,05
END1:CALL SOUND
;?
DJNZ *END1
DCR B;
JNZ END1;
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B
JNZ WAIT
JMP START
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
29
80C7
80CA
80CD
80CE
80CF
80D0
80D3
80D4
80D6
80D7
CAB480
320980
D1
E1
C9
21F883
AF
0608
77
23
80D8 05
80D9 C2D680
80DC C9
80DD CDB280
80E0
80E1
80E4
80E5
80E6
80E7
80E8
80E9
02
21F883
85
6F
7B
B6
77
C9
80EA CDB280
80ED
80EE
80F0
80F3
80F4
80F7
80F8
80F9
80FA
80FB
80FC
80FE
80FF
8100
8101
3C
FE07
D2EA80
47
CD5981
7E
A2
77
7D
81
F6F8
6F
7E
B3
77
8102
8103
8106
8107
05
C2F480
7D
E607
8109 E5
810A 2A0580
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all clear
CLR:LXI H,LED1
XRA A
MVI B,08
CLR1:MOV M,A
INX H
;?
DJNZ *CLR1
DCR B;
JNZ CLR1;
RET
;
;start data set;BC=MYADRS or YRADRS;E=disp data 23(cap) or 1C(cup)
DTSET:CALL RND3
;
ANI 07
STAX B
LXI H,LED1
ADD L
MOV L,A
MOV A,E
ORA M
MOV M,A;cap or cup or both disp
RET
;
;step left or right
C=FF(left) C=01(right),HL=current position
;
D=clear mask DC(cap) or E3(cup)
;
E=disp data 23(cap) or 1C(cup)
;
IX=MYADRS or YRADRS
STEP:CALL RND3
;
ANI 07
INR A
CPI 07
JNC STEP
MOV B,A
STEP1:CALL TM02S
MOV A,M
ANA D;clear
MOV M,A
MOV A,L
ADD C
ORI F8
MOV L,A
MOV A,M
ORA E;disp
MOV M,A
;?
DJNZ STEP1
DCR B;
JNZ STEP1;
MOV A,L
ANI 07
;
STA IX+00
PUSH H;
LHLD ADRSWK;
30
810D 77
810E E1
810F C9
8110
8111
8112
8115
8116
8117
C5
D5
CD2302
D1
C1
C9
8118
8119
811A
811B
811C
811F
8120
8121
8122
8124
8125
8127
8129
812A
812B
812E
812F
8131
8133
8134
8135
8138
8139
813C
813D
813E
813F
8140
F5
E5
D5
C5
214181
85
6F
46
1E1A
50
3EFF
D398
7F
15
C22981
50
3EDF
D398
7F
15
C23381
1D
C22481
C1
D1
E1
F1
C9
8141
8142
8143
8144
8145
8146
8147
8148
8149
814A
814B
814C
814D
814E
814F
8150
7F
77
71
6A
5F
59
54
4F
47
43
3F
3B
35
32
2F
2C
MOV M,A;
POP H;
RET
;
;KEYIN with DE,BC save
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
POP D
POP B
RET
;
;
SOUND:PUSH PSW
PUSH H
PUSH D
PUSH B
LXI H,SNDTBL
ADD L
MOV L,A
MOV B,M
MVI E,1A
SNDS1:MOV D,B
MVI A,FF;SP OUT=H
OUT 98
SNDS2:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS2;10---MOV D,B
MVI A,DF;sp out=L
OUT 98
SNDS3:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS3;10---DCR E
JNZ SNDS1
POP B
POP D
POP H
POP PSW
RET
; SOUND TABLE
SNDTBL:DB 7F;so4
DB 77;so#4
DB 71;ra4
DB 6A;ra#4
DB 5F;do5
DB 59;do#5
DB 54;re5
DB 4F;re#
DB 47;fA5
DB 43;fa#5
DB 3F;so5
DB 3B;so5#
DB 35;ra#5
DB 32;si5
DB 2F;do6
DB 2C;do#6
20/2=10microsec
20/2=10microsec
31
8151
8152
8153
8154
8155
8156
8157
8158
25
27
2A
4B
38
64
23
21
8159 CD5C81
815C
815D
815F
8160
8163
8164
8165
8168
8169
D5
1E15
D5
CDDD02
D1
1D
C25F81
D1
C9
ADRSWK
D1
END1
KEYIN2S
MYADRS
R
RIGHT2
RNDDT
SNDS2
SOUND
STEP1
TM02S
DB
DB
DB
DB
DB
DB
DB
DB
25;mi6
27;re#6
2A;re6
4B;mi5
38;ra5
64;si4
23;fa6
21;fa#6
;
;0.2sec timer
TM02S:CALL TM01S
;0.1sec timer
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
=8005 CLR
=02DD DTSET
=809F KEY
=8110 LED1
=8003 MYTURN
=FFD2 REENT
=804D RND2
=8007 RNDDT2
=8129 SNDS3
=8118 START
=80F4 TM01S
=8159 WAIT
=80D0
=80DD
=8030
=83F8
=8071
=8024
=80B4
=8009
=8133
=800A
=815C
=80A8
CLR1
END
KEYIN2
LEFT
MYTURN1
RIGHT
RND3
SNDS1
SNDTBL
STEP
TM01S2
YRADRS
=80D6
=809D
=0223
=8046
=807A
=804B
=80B2
=8124
=8141
=80EA
=815F
=8004
32
プログラム№7 もぐらたたき(MOGURA8.BTK)
ゲームの説明
LEDにランダムに現れるもぐらをたたくゲームです。
8000番地からRUNするとLEDの全部の表示が”8”の一番下の”_”になります。2秒ごとにLEDのどこかの桁にモ
グラ(下向きのコの字のパターン)が現れます。1秒たつとモグラは引っ込んでしまいます。その前にうまくモグラをたたく
と(表示されているLED位置を示す1~8の数字キーを押すと)ピッと音がしてモグラがつぶれます。1~8のキーを押す
と対応するLEDにハンマー(”8”の字の上のバー)が表示され、0.5秒後に下に落とされます。ヒットするのが遅れたり、
違う数を押したりすると失敗です。ブーという音がします。
モグラは一度に1匹だけ出て来ます。全部で20匹出るとゲームオーバーです。ヒットしたモグラの数がLEDに表示さ
れ約2秒間点滅します。そのあと2秒間表示が静止したあとはじめに戻って再びゲームが開始されます。
プログラムの説明
作業用のメモリとしてRNDDT、RNDDT2(乱数用)の他は1バイトのMCOUNTのみを使います。最初20(14H)から
始って0になるまでモグラの表示回数をダウンカウントします。
はじめのMOGURA01:の処理は説明が必要です。KEYからの入力をチェックしていますが1~8が入力されると「ブ
ー」音を出しています。じつはこの時点ではまだモグラは出現していないのです。ここは「お手つき」をチェックしているの
です。
HAMMERサブルーチンはハンマーの表示とサウンド(ブーおよびピー)を行います。HAMMERサブルーチンで、AN
I 14としているのはモグラをヒットしたとき、モグラがつぶれた形を表示するためです(下向きのコの字の上のバーが消
える)。そのあとのORI 08でハンマーが落ちたところを表示しています。このANDとORによってモグラをヒットしたとき
でも、モグラがいない場所をたたいてしまったときでも同じサブルーチンが使えるようになります。そのあとのサウンド出
力も同様でCレジスタの値によって、同じサブルーチンでヒットしたときのピーと失敗したときのブーが出るようになりま
す。
さて失敗したときもヒットしたときもモグラの数は-1されます。0になったらゲーム終了処理へ行き、そうでないときは
始めの部分に戻ってモグラの出現処理をくりかえします。失敗してもヒットしても同じ処理を行います。NOT1:の部分で
す。ここはサブルーチンではありませんがサブルーチンのときと同じ考え方です。NOT:の後半部分になっていますがHI
T:の処理のあともここにジャンプしてきます。このように同じ処理にできる部分はCALLかJMPでひとつにまとめるのが
プログラムのコツです。
2016/4/20
END=816E
8000
8003
8004
8005
C30780
00
00
00
9:53
mogura8.txt
; MOGURATATAKI for NDZ (HIT'N BLOW)
; 03/5/2 5/5 5/11 5/12
;10/6/2 for ND80Z3
;7/21 9/17
;16/4/16 for ND8080
;4/18
;4/19
;4/20
;
ORG $8000
;
RNDDT=$E810;$E811
;
MCOUNT=$E812
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN2=$0223;$0623
;
JMP START
RNDDT:NOP
NOP
RNDDT2:NOP
33
8006 00
8007
800A
800D
800E
800F
8010
8013
8016
8019
801B
3AD2FF
210380
77
23
77
210000
22F683
22F483
3E14
320680
801E
8021
8024
8027
802A
802C
802F
8030
8033
8035
8038
803B
803C
803D
803E
CDF280
01D007
CD1F81
CDFF80
FE09
D23B80
3D
FA3B80
0E00
CDA080
C31E80
0B
78
B1
C22480
8041 CDBF80
8044
8045
8048
8049
804A
804C
804F
8052
8054
8057
8058
805B
805C
57
21F883
85
6F
3654
01E803
CDFF80
FE09
D26780
3D
FA6780
BA
CA7D80
805F 0E00
8061 CDA080
8064 C37080
8067
806A
806B
806C
806D
8070
8073
8074
8077
CD1F81
0B
78
B1
C24F80
3A0680
3D
CA8E80
320680
MCOUNT:NOP
;start data disp
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
SHLD DP1
MVI A,14;=20
STA MCOUNT;mogura
;wait 2sec,if keyin then buuuu
MOGURA:CALL STDTDP
LXI B,$07D0;=2000 ,wait 2000msec
MOGURA01:CALL TM1M
CALL KEYIN2S
CPI 09
JNC MOGURA02
DCR A
JM MOGURA02
MVI C,00;sound buuuu
CALL HAMMER
JMP MOGURA
MOGURA02:DCX B
MOV A,B
ORA C
JNZ MOGURA01
;"MOGURA" up
MOGURA1:CALL RND3
;
ANI 07
MOV D,A;position save
LXI H,LED1
ADD L
MOV L,A
MVI M,54;MOGURA disp
LXI B,$03E8;=1000 ,wait 1000msec
MOGURA2:CALL KEYIN2S
CPI 09
JNC NOT
DCR A
JM NOT
CMP D
JZ HIT
;BUUUUU
MVI C,00;sound buuuuu
CALL HAMMER
JMP NOT1
;not keyin
NOT:CALL TM1M
DCX B
MOV A,B
ORA C
JNZ MOGURA2
NOT1:LDA MCOUNT
DCR A
JZ END
STA MCOUNT
34
807A C31E80
807D
807F
8082
8085
8087
8088
808B
0E17
CDA080
3AF783
C601
27
32F783
C37080
808E
8091
8094
8096
CDC001
CDDD80
0614
CD1381
8099 05
809A C29680
809D C30780
80A0
80A3
80A4
80A5
80A6
80A8
80A9
80AC
80AE
80B0
80B1
80B2
80B4
21F883
85
6F
7E
F601
77
CD0781
E614
F608
77
79
0603
CD2E81
80B7
80B8
80BB
80BE
05
C2B480
CD0781
C9
80BF
80C0
80C1
80C4
80C5
80C6
80C8
80C9
80CC
80CF
80D0
80D1
80D3
80D4
80D7
80DA
80DB
80DC
E5
D5
2A0380
23
7C
E603
67
220380
3A0580
57
7E
E607
BA
CAC180
320580
D1
E1
C9
JMP MOGURA
;hit!
HIT:MVI C,17;sound piiii
CALL HAMMER
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
JMP NOT1
;game over! COUNTER disp and ALL LED blink
END:CALL DTDPS
CALL ALBLNK
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
;hammer disp
HAMMER:LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORI 01;hammer up
MOV M,A
CALL TM05S
ANI 14;hammer down
ORI 08
MOV M,A
MOV A,C
MVI B,03
HAMMER1:CALL SOUND
;?
DJNZ HAMMER1
DCR B;
JNZ HAMMER1;
CALL TM05S
RET
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
35
80DD
80DF
80E1
80E3
80E6
80E8
80EA
060A
3EEF
D398
CD1381
3EFF
D398
CD1381
80ED 05
80EE C2DF80
80F1 C9
80F2
80F5
80F7
80F9
21F883
0608
3608
23
80FA 05
80FB C2F780
80FE C9
80FF
8100
8101
8104
8105
8106
C5
D5
CD2302
D1
C1
C9
8107 C5
8108 0605
810A CD1381
810D
810E
8111
8112
05
C20A81
C1
C9
8113
8114
8116
8119
811A
811D
811E
D5
1E64
CD1F81
1D
C21681
D1
C9
811F
8120
8122
8124
8125
8128
8129
D5
1607
1E12
1D
C22481
15
C22281
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;start data disp
STDTDP:LXI H,LED1
MVI B,08
STDTDP1:MVI M,08
INX H
;?
DJNZ STDTDP1
DCR B;
JNZ STDTDP1;
RET
;
;KEYIN with DE,BC save
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
POP D
POP B
RET
;
;0.5sec timer
TM05S:PUSH B
MVI B,05
TM05S1:CALL TM01S
;?
DJNZ TM05S1
DCR B;
JNZ TM05S1;
POP B
RET
;0.1sec timer
TM01S:PUSH D
MVI E,64;=100
TM01S2:CALL TM1M
DCR E
JNZ TM01S2
POP D
RET
;
;1msec timer
TM1M:PUSH D;11
MVI D,07; ck=5 (11+7+292*7+10+10)/2.048=2082/2.048=1016
TM1M2:MVI E,12;=18 ck=7 7+15*18+15=292
TM1M3:DCR E;5
JNZ TM1M3;10
DCR D;5
JNZ TM1M2;10
36
812C D1
812D C9
812E
812F
8130
8131
8132
8135
8136
8137
8138
813A
813B
813D
813F
8140
8141
8144
8145
8147
8149
814A
814B
814E
814F
8152
8153
8154
8155
8156
F5
E5
D5
C5
215781
85
6F
46
1E1A
50
3EFF
D398
7F
15
C23F81
50
3EDF
D398
7F
15
C24981
1D
C23A81
C1
D1
E1
F1
C9
8157
8158
8159
815A
815B
815C
815D
815E
815F
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
816A
816B
816C
816D
816E
7F
77
71
6A
5F
59
54
4F
47
43
3F
3B
35
32
2F
2C
25
27
2A
4B
38
64
23
21
ALBLNK
POP D;10
RET;10
;
SOUND:PUSH PSW
PUSH H
PUSH D
PUSH B
LXI H,SNDTBL
ADD L
MOV L,A
MOV B,M
MVI E,1A
SNDS1:MOV D,B
MVI A,FF;SP OUT=H
OUT 98
SNDS2:MOV A,A;5--------DCR D;5
| 5+5+10=20 20/2=10microsec
JNZ SNDS2;10---MOV D,B
MVI A,DF;sp out=L
OUT 98
SNDS3:MOV A,A;5--------DCR D;5
| 5+5+10=20 20/2=10microsec
JNZ SNDS3;10---DCR E
JNZ SNDS1
POP B
POP D
POP H
POP PSW
RET
; SOUND TABLE
SNDTBL:DB 7F;so4
DB 77;so#4
DB 71;ra4
DB 6A;ra#4
DB 5F;do5
DB 59;do#5
DB 54;re5
DB 4F;re#
DB 47;fA5
DB 43;fa#5
DB 3F;so5
DB 3B;so5#
DB 35;ra#5
DB 32;si5
DB 2F;do6
DB 2C;do#6
DB 25;mi6
DB 27;re#6
DB 2A;re6
DB 4B;mi5
DB 38;ra5
DB 64;si4
DB 23;fa6
DB 21;fa#6
;
=80DD ALBLNK1
=80DF CNTR
=83F7
37
DP1
END
HIT
LED1
MOGURA01
MOGURA2
R
RNDDT
SNDS2
SOUND
STDTDP1
TM05S
TM1M2
=83F4
=808E
=807D
=83F8
=8024
=804F
=FFD2
=8003
=813F
=812E
=80F7
=8107
=8122
DP3
HAMMER
KEYIN2
MCOUNT
MOGURA02
NOT
RND2
RNDDT2
SNDS3
START
TM01S
TM05S1
TM1M3
=83F6
=80A0
=0223
=8006
=803B
=8067
=80C1
=8005
=8149
=8007
=8113
=810A
=8124
DTDPS
HAMMER1
KEYIN2S
MOGURA
MOGURA1
NOT1
RND3
SNDS1
SNDTBL
STDTDP
TM01S2
TM1M
WAIT
=01C0
=80B4
=80FF
=801E
=8041
=8070
=80BF
=813A
=8157
=80F2
=8116
=811F
=8096
38
プログラム№8 神経衰弱(SINKSUI8.BTK)
ゲームの説明
神経衰弱ゲームです。
8000番地からRUNするとLEDが全部消えます。この時点でコンピータは乱数によって1~Fのうちから同じものを2
個ずつ4組選んでLEDにばらばらにセットしています。
プレーヤーが1~8のキーを押すとその数で示される位置のLEDに隠されていた数(1~Fのどれか)が表示されます。
続いてもう1ヶ所のLEDを選択してその場所を示す数のキーを押します。うまく正解して同じ数を当てたときは両方のLE
Dは点灯したままになります。もし失敗して違う数だった場合には、今まで表示されていた全部が消えて始めに戻ってし
まいます(数の配置は変わりませんから点灯している間に覚えておくようにします)。
またうっかりしてすでに点灯しているLEDを示す数を入力した場合も「お手つき」で表示は全部消えてしまいます。
このようにしてうまく8個のLEDを全部点灯させることができればゲーム終了です。2秒間LEDが点滅し、そのあと試
行回数が2秒間表示されます。そして始めに戻って再びゲームが開始されます。
プログラムの説明
LEDに割り当てた数をしまっておくメモリエリアとして8バイトエリア(DTBF)を用意します。はじめに乱数で4個の数を
選択して、それぞれ2回乱数によって格納する場所を選んで、DTBFにLED表示パターンを格納します。こういうプログ
ラムではDTBFにキー入力された数値そのものを格納するように考えるのが普通なのでしょうが、今回は数値を計算に
は利用しないので、どうせ表示するときには表示パターンに変換することを考えると、ここで先に表示パターンに変換し
てしまってもよいわけです。
ところでこのとき乱数の発生がうまくいかなくて発生させる数値が片寄ってしまい、全部の表示データを算出できないこ
とがあります。このときはアドレス表示が8000のままで表示がブランクになりません。一度リセット(MONキーを押す)
してから8000から再スタートしてください。
このプログラムでもちょいとしたテクニックを使っています。DTDP:の部分です。ここではキー入力された1~8の数(こ
れを0~7に変換している)をもとに、対応するLEDに割り当てられた数値パターンを表示させるのですが、そのときすで
に表示済み(点灯している)LEDアドレスが指定されていないかをチェックして、もしチェックされていたらそのことをメイン
ルーチンに知らせるためにサインフラグ(S-FLAG)をセットしてリターンします。そうではないときには、LEDに表示す
るとともにそのデータエリア(DTBF)に表示済みのマークをつけます。
普通は表示済みマークをつけるためにデータエリア(ここではDTBFの8バイト)の他にマーク用に8バイトの場所を用
意するなどと考えます。するとそれをチェックするために余計なアドレス計算が必要になってしまいます。DTDP:ではそ
このところをちょいとした工夫でパスしています。
DTBFに格納される表示パターンは1~Fですが、共通しているところが1ヶ所あります。
そうです。最上位ビットは常に0です。最上位ビットはLEDの右下のピリオドに割り当てられているので普通は表示しま
せん。これを点灯マークに使うのです。点灯しているときはここを1にします。16進数の約束事で符号付の数として考え
るときはその最上位ビットが1のとき、この数はマイナスとして扱います。今回のプログラムでは点灯していないデータは
+で点灯しているデータは-になります。ORA A命令を使うとAの内容によってS-FLAG(サインフラグ)がON/OF
Fするので、この情報をメインルーチンに持って帰ることができます。
もうひとつ、DTDP:のはじめの部分でキー入力された情報(00~07)をもとにしてDTBFの該当するアドレスを算出
する部分で今までのようにADD L、MOV L,Aとしないで、いきなりMOV L,Aを実行しています。こういうやり方は
危険なので注意しなければいけません。ここではDTBFの先頭は8200になっていて、下位8ビットはAレジスタの値と
一致するために、ADD Lを省いたのです。危険なのは将来プログラムを変更するとか、この部分を他のプログラムに
利用するとかといった場合に、もしDTBFに半端なアドレスを割り当ててしまうと、正しい結果が得られなくなってしまうこ
とです。
2016/4/20
END=8135
10:1
sinksui8.txt
; SINKEISUIJAKU for NDZ (ODD COUPLES)
; 03/04/29 4/30 5/1 5/5 5/12 5/24
;10/6/2 for ND80Z3
;16/4/18 for nd8080
;4/19
;4/20
;
ORG $8000
DTBF=$8200;$E800
;
RNDDT=$E810;$E811
LED1=$83F8;$FFF8
39
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
;
8000
8003
8004
8005
C30680
00
00
00
8006
8009
800C
800D
800E
800F
8010
8012
8015
8016
3AD2FF
210380
77
23
77
AF
0608
210082
77
23
8017 05
8018 C21580
801B 0E04
801D CD9A80
8020
8023
8024
8026
8027
8028
802B
802D
802E
8031
210381
5F
1600
19
7E
210082
0608
BE
CA1D80
23
8032 05
8033 C22D80
8036 57
8037
8039
803C
803E
8041
8042
8043
8044
8045
8048
0602
CD9A80
E607
210082
85
6F
7E
B7
C23980
72
8049 05
JMP START
RNDDT:NOP
NOP
RNDDT2:NOP
;
;data set
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
XRA A
MVI B,08
LXI H,DTBF
DTST1:MOV M,A
INX H
;?
DJNZ *DTST1
DCR B;
JNZ DTST1;
MVI C,04
;No. select
DTST2:CALL RND4
;
ANI 0F
LXI H,SEGDT
MOV E,A
MVI D,00
DAD D
MOV A,M
LXI H,DTBF
MVI B,08
DTST3:CMP M
JZ DTST2;already selected No.
INX H
;?
DJNZ *DTST3
DCR B;
JNZ DTST3;
MOV D,A;DATA save
;ADDRESS select and DATA set
MVI B,02
ADST1:CALL RND4
ANI 07
LXI H,DTBF
ADD L
MOV L,A
MOV A,M
ORA A
JNZ ADST1;already used
MOV M,D;DATA set
;?
DJNZ *ADST1
DCR B;
40
804A C23980
804D 0D
804E C21D80
8051 210000
8054 22F683
8057 22F483
805A
805D
8060
8061
8064
8066
8067
806A
806B
806E
CDCD80
CDE280
F5
3AF783
C601
27
32F783
F1
FA5A80
47
806F CDE280
8072 FA5A80
8075 B8
8076 C25A80
8079
807C
807E
807F
8080
8083
210082
0608
7E
B7
F25D80
23
8084 05
8085 C27E80
8088
808B
808E
8090
CDB880
CDC001
0614
CD1B81
8093 05
8094 C29080
8097 C30680
809A
809B
809C
809F
80A0
80A1
80A3
80A4
80A7
80AA
80AB
80AC
80AE
E5
D5
2A0380
23
7C
E603
67
220380
3A0580
57
7E
E60F
BA
JNZ ADST1;
DCR C
JNZ DTST2
;GAME START
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
SHLD DP1
;key entry(first one)
REENT:CALL CLR
KEY:CALL KEYDP
PUSH PSW;DATA and S-FLAG save
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
POP PSW;DATA and S-FLAG
JM REENT;otetuki
MOV B,A;first DATA save
;key entry(second ONE)
KEY2:CALL KEYDP
JM REENT;otetuki
;DATA compere
CMP B; B=first data
JNZ REENT;not same
;check all open or not
LXI H,DTBF
MVI B,08
OPNCK1:MOV A,M
ORA A
JP KEY;not open data,continue GAME
INX H
;?
DJNZ OPNCK1
DCR B;
JNZ OPNCK1;
;OK! ALL LED blink
CALL ALBLNK
CALL DTDPS;COUNTER disp
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
;ransu
RND4:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 0F
CMP D
41
80AF
80B2
80B5
80B6
80B7
80B8
80BA
80BC
80BE
80C1
80C3
80C5
CA9C80
320580
D1
E1
C9
060A
3EEF
D398
CD1B81
3EFF
D398
CD1B81
80C8 05
80C9 C2BA80
80CC C9
80CD
80D0
80D3
80D6
80D7
80D8
80DA
80DB
80DC
21F883
110082
010008
71
1A
E67F
12
23
13
80DD 05
80DE C2D680
80E1 C9
80E2
80E5
80E7
80EA
80EB
80EE
80F1
80F2
80F3
80F4
80F5
80F7
80F8
80FA
80FD
80FF
8100
8101
8102
8103
8104
8105
8106
CD1381
FE09
D2E280
3D
FAE280
210082
6F
7E
B7
F8
F680
77
E67F
11F883
2600
19
77
B7
C9
5C
06
5B
4F
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;LED clear and open mark clear
CLR:LXI H,LED1
LXI D,DTBF
LXI B,$0800
CLR2:MOV M,C
LDAX D
ANI 7F
STAX D
INX H
INX D
;?
DJNZ *CLR2
DCR B;
JNZ CLR2;
RET
;
;KEYIN and DATA disp
KEYDP:CALL KEYIN1S
CPI 09
JNC KEYDP
DCR A
JM KEYDP
DTDP:LXI H,DTBF
MOV L,A
MOV A,M
ORA A
RM;otetuki!
ORI 80
MOV M,A;open mark set
ANI 7F
LXI D,LED1
MVI H,00
DAD D
MOV M,A
ORA A;clear Sign-flag
RET
SEGDT:DB 5C;0
DB 06;1
DB 5B;2
DB 4F;3
42
8107
8108
8109
810A
810B
810C
810D
810E
810F
8110
8111
8112
66
6D
7D
27
7F
6F
77
7C
39
5E
79
71
8113
8114
8115
8118
8119
811A
C5
D5
CD1602
D1
C1
C9
811B
811C
811E
8121
8122
8125
8126
D5
1E64
CD2781
1D
C21E81
D1
C9
8127
8128
812A
812C
812D
8130
8131
8134
8135
D5
1607
1E12
1D
C22C81
15
C22A81
D1
C9
ADST1
CLR
DP1
DTDP
DTST2
KEY2
KEYIN1S
R
RND4
SEGDT
TM01S2
TM1M3
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
66;4
6D;5
7D;6
27;7
7F;8
6F;9
77;A
7C;b
39;C
5E;d
79;E
71;F
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,64;=100
TM01S2:CALL TM1M
DCR E
JNZ TM01S2
POP D
RET
;
;1msec timer
TM1M:PUSH D;11
MVI D,07; ck=5 (11+7+292*7+10+10)/2.048=2082/2.048=1016
TM1M2:MVI E,12;=18 ck=7 7+15*18+15=292
TM1M3:DCR E;5
JNZ TM1M3;10
DCR D;5
JNZ TM1M2;10
POP D;10
RET;10
;
=8039 ALBLNK
=80B8 ALBLNK1
=80BA
=80CD CLR2
=80D6 CNTR
=83F7
=83F4 DP3
=83F6 DTBF
=8200
=80EE DTDPS
=01C0 DTST1
=8015
=801D DTST3
=802D KEY
=805D
=806F KEYDP
=80E2 KEYIN1
=0216
=8113 LED1
=83F8 OPNCK1
=807E
=FFD2 REENT
=805A RND2
=809C
=809A RNDDT
=8003 RNDDT2
=8005
=8103 START
=8006 TM01S
=811B
=811E TM1M
=8127 TM1M2
=812A
=812C WAIT
=8090
43
プログラム№9 WANTED(WANTED8.BTK)
ゲームの説明
これはちょっと変わった数当てゲームです。
コンピュータはあらかじめ乱数によって4桁の数(0000~9999)を求めて隠しています。
プレーヤーにはこの数は知らされませんがヒントが示されるので、プレーヤーはヒントを参考にしてこの数を推測し、こ
の数に4桁(1~3桁でもよい)の数を加算して最終的に加算した結果を9999にするとゲーム終了です。
8000番地からRUNするとピーと音がしてLEDの左1桁と3桁目が消灯し、残りは全部0になります。適当な数(たとえ
ば1234)を入力してWRITE INCキーを押すとコンピュータは入力した数ともとの数を加算して加算結果を記憶します。
加算の結果9999になればゲーム終了です。加算結果が9999より大きくなったときはオーバーフローです。ブーという
音がしてLEDの左から2桁目と4桁目に”F”が表示されます。この場合には入力した数は加算されず無視されます。オ
ーバーフローしなかった場合にはコンピュータは加算結果の数をチェックしてどこかの桁に”9”があればその9の数をL
EDの左から2桁目に表示します。しかし何桁目が9であるかは知らせてくれません。もうひとつヒントを出します。残りの
9ではない数のうちどれか1つの数をLEDの左から4桁目に表示します。そして再びピーと音がして次の数の入力待ち
になります。入力する数はWRITE INCを押すまで何回でも入れなおすことができます。
9999が完成するとピーという音がしてLEDの左4桁に9999が表示されます。
何かキーを押すとLEDの左4桁に最初に隠されていた数値が表示され、右4桁に試行回数が表示されます。
もう1回何かキーを押すと始めに戻って再びゲームが開始されます。
「マイコンゲーム21」ではゲームスタートでLEDが全部0になるようにしていますが、そうするとリセットがかかったよう
な気がしてとまどってしまいますので、ここにあるようにLEDの左1桁と3桁目をブランクにしました。
プログラムの説明
特に説明しなくても、多分理解できると思います。
2016/4/20
END=818F
8000
8003
8004
8005
8006
8007
8008
C30B80
00
00
00
00
00
00
10:22
wanted8.txt
; WANTED for NDZ
; 03/05/06 5/12
;10/6/3 for ND80Z3
;7/21 9/17
;16/4/19 for nd8080
;4/20
;
ORG $8000
;
MYDT=$E800
;
ACC=$E802
;
CNTR=$E805
;
RNDDT=$E810;$E811
DTRG=$83EC;$FFEC
ADRG=$83EE;$FFEE
LED1=$83F8;$FFF8
LED3=$83FA;$FFFA
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
R=$FFD2
;
ADDPS=$01A1;$05A1
KEYIN1=$0216;$0616
;
;data set
JMP START
MYDT:NOP
NOP
ACC:NOP
NOP
CNTR:NOP
RNDDT:NOP
44
8009
800A
800B
800E
8011
8012
8013
8014
8015
8018
8019
801A
801D
00
00
3AD2FF
210880
77
23
77
AF
320780
67
6F
22EC83
22EE83
8020 0604
8022 CD0E81
8025
8027
802A
802B
802C
802D
802E
802F
FE0A
D22280
29
29
29
29
B5
6F
8030
8031
8034
8037
05
C22280
220380
220580
803A 3E10
803C 060A
803E CD4F81
8041
8042
8045
8048
8049
804C
804F
8052
8055
8057
805A
805C
805F
8060
8061
8062
8063
8064
8065
8068
05
C23E80
CDA101
AF
32F883
32FA83
2AEC83
CD2C81
FE15
CA6B80
FE0A
D25280
29
29
29
29
B5
6F
22EC83
C34580
806B 3A0780
806E C601
NOP
RNDDT2:NOP
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
XRA A
STA CNTR;COUNTER clear
MOV H,A
MOV L,A
SHLD DTRG
SHLD ADRG
;data set
MVI B,04
DTST1:CALL RND4
;
ANI 0F
CPI 0A
JNC DTST1
DAD H
DAD H
DAD H
DAD H
ORA L
MOV L,A
;?
DJNZ *DTST1
DCR B
JNZ DTST1
SHLD MYDT
SHLD ACC
;GAME START
START1:MVI A,10;puuuu
MVI B,0A
START2:CALL SOUND
;?
DJNZ START2
DCR B
JNZ START2
KEY:CALL ADDPS
XRA A
STA LED1
STA LED3
KEY1:LHLD DTRG
KEY2:CALL KEYIN1S
CPI 15;W INC
JZ ADD
CPI 0A
JNC KEY2
DAD H
DAD H
DAD H
DAD H
ORA L
MOV L,A
SHLD DTRG
JMP KEY
;DATA add and check
ADD:LDA CNTR
ADI 01;DECIMAL COUNTER up
45
8070 27
8071 320780
8074
8075
8078
8079
807A
807B
807C
807D
807E
807F
8080
8083
8084
EB
2A0580
EB
7B
85
27
6F
7A
8C
27
DACB80
67
220580
8087
8089
808B
808D
808E
1600
0E04
0604
29
17
808F
8090
8093
8095
8097
809A
809B
809C
809F
80A0
80A2
05
C28D80
E60F
FE09
C29B80
14
0D
C28B80
7A
FE04
CADF80
80A5
80A8
80AB
80AD
80AE
80AF
80B1
80B2
2A0580
CD0E81
E603
3C
4F
0604
29
17
80B3
80B4
80B7
80B8
80BB
80BD
80BF
80C2
05
C2B180
0D
C2AF80
E60F
FE09
CAA580
5F
80C3
80C4
80C7
80C8
EB
22EE83
EB
C33A80
DAA
STA CNTR
;?
LD DE,(ACC)
XCHG;
LHLD ACC;
XCHG;
MOV A,E
ADD L
DAA
MOV L,A
MOV A,D
ADC H
DAA
JC OVER
MOV H,A
SHLD ACC
;check
MVI D,00
MVI C,04
CK1:MVI B,04
CK2:DAD H
RAL
;?
DJNZ *CK2
DCR B;
JNZ CK2;
ANI 0F
CPI 09
JNZ CK3
INR D;count "9"
CK3:DCR C
JNZ CK1
MOV A,D
CPI 04
JZ OK
;one No.(except "9") select
CK4:LHLD ACC
CALL RND4
ANI 03
INR A
MOV C,A
CK5:MVI B,04
CK6:DAD H
RAL
;?
DJNZ *CK6
DCR B;
JNZ CK6;
DCR C
JNZ CK5
ANI 0F
CPI 09
JZ CK4
MOV E,A
;result disp
;?
LD (ADRG),DE
XCHG;
SHLD ADRG;
XCHG;
JMP START1
46
80CB 3E00
80CD 0605
80CF CD4F81
80D2
80D3
80D6
80D9
80DC
05
C2CF80
21FFFF
22EE83
C34580
80DF 3E17
80E1 0605
80E3 CD4F81
80E6
80E7
80EA
80ED
80F0
80F3
80F6
80F9
80FC
80FF
8100
8102
8105
8108
810B
05
C2E380
2A0580
22EE83
CDA101
CD2C81
2A0380
22EE83
3A0780
6F
2600
22EC83
CDA101
CD2C81
C30B80
810E
810F
8110
8113
8114
8115
8117
8118
811B
811E
811F
8120
8122
8123
8126
8129
812A
812B
E5
D5
2A0880
23
7C
E603
67
220880
3A0A80
57
7E
E60F
BA
CA1081
320A80
D1
E1
C9
812C
812D
812E
8131
8132
8133
C5
D5
CD1602
D1
C1
C9
OVER:MVI A,00;buuuu
MVI B,05
OVER1:CALL SOUND
;?
DJNZ OVER1
DCR B;
JNZ OVER1;
LXI H,$FFFF
SHLD ADRG
JMP KEY
;
;result="9999"
OK:MVI A,17;piiii
MVI B,05
OK1:CALL SOUND
;?
DJNZ OK1
DCR B;
JNZ OK1;
LHLD ACC
SHLD ADRG
CALL ADDPS
CALL KEYIN1S
LHLD MYDT
SHLD ADRG
LDA CNTR
MOV L,A
MVI H,00
SHLD DTRG
CALL ADDPS
CALL KEYIN1S
JMP START
;
;ransu
RND4:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 0F
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
47
8134
8135
8137
813A
813B
813E
813F
D5
1E64
CD4081
1D
C23781
D1
C9
8140
8141
8143
8145
8146
8149
814A
814D
814E
D5
1607
1E12
1D
C24581
15
C24381
D1
C9
814F
8150
8151
8152
8153
8156
8157
8158
8159
815B
815C
815E
8160
8161
8162
8165
8166
8168
816A
816B
816C
816F
8170
8173
8174
8175
8176
8177
F5
E5
D5
C5
217881
85
6F
46
1E1A
50
3EFF
D398
7F
15
C26081
50
3EDF
D398
7F
15
C26A81
1D
C25B81
C1
D1
E1
F1
C9
8178
8179
817A
817B
817C
817D
817E
817F
7F
77
71
6A
5F
59
54
4F
;
;0.1sec timer
TM01S:PUSH D
MVI E,64;=100
TM01S2:CALL TM1M
DCR E
JNZ TM01S2
POP D
RET
;
;1msec timer
TM1M:PUSH D;11
MVI D,07; ck=5 (11+7+292*7+10+10)/2.048=2082/2.048=1016
TM1M2:MVI E,12;=18 ck=7 7+15*18+15=292
TM1M3:DCR E;5
JNZ TM1M3;10
DCR D;5
JNZ TM1M2;10
POP D;10
RET;10
;
SOUND:PUSH PSW
PUSH H
PUSH D
PUSH B
LXI H,SNDTBL
ADD L
MOV L,A
MOV B,M
MVI E,1A
SNDS1:MOV D,B
MVI A,FF;SP OUT=H
OUT 98
SNDS2:MOV A,A;5--------DCR D;5
| 5+5+10=20 20/2=10microsec
JNZ SNDS2;10---MOV D,B
MVI A,DF;sp out=L
OUT 98
SNDS3:MOV A,A;5--------DCR D;5
| 5+5+10=20 20/2=10microsec
JNZ SNDS3;10---DCR E
JNZ SNDS1
POP B
POP D
POP H
POP PSW
RET
; SOUND TABLE
SNDTBL:DB 7F;so4
DB 77;so#4
DB 71;ra4
DB 6A;ra#4
DB 5F;do5
DB 59;do#5
DB 54;re5
DB 4F;re#
48
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
818A
818B
818C
818D
818E
818F
47
43
3F
3B
35
32
2F
2C
25
27
2A
4B
38
64
23
21
ACC
ADRG
CK3
CK6
DP3
KEY
KEYIN1
LED3
OK1
R
RNDDT
SNDS2
SOUND
START2
TM1M
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
;
;
=8005
=83EE
=809B
=80B1
=83F6
=8045
=0216
=83FA
=80E3
=FFD2
=8008
=8160
=814F
=803E
=8140
47;fA5
43;fa#5
3F;so5
3B;so5#
35;ra#5
32;si5
2F;do6
2C;do#6
25;mi6
27;re#6
2A;re6
4B;mi5
38;ra5
64;si4
23;fa6
21;fa#6
ADD
CK1
CK4
CNTR
DTRG
KEY1
KEYIN1S
MYDT
OVER
RND2
RNDDT2
SNDS3
START
TM01S
TM1M2
=806B
=808B
=80A5
=8007
=83EC
=804F
=812C
=8003
=80CB
=8110
=800A
=816A
=800B
=8134
=8143
ADDPS
CK2
CK5
DP1
DTST1
KEY2
LED1
OK
OVER1
RND4
SNDS1
SNDTBL
START1
TM01S2
TM1M3
=01A1
=808D
=80AF
=83F4
=8022
=8052
=83F8
=80DF
=80CF
=810E
=815B
=8178
=803A
=8137
=8145
49
プログラム№10 すごろく迷路(SUGOROK8.BTK)
ゲームの説明
LED表示を利用したすごろくゲームです。
8個のLEDのさらに右側にゴールがあります(見えませんがあることにします)。LEDの左側にも1つダミーポジション
があります(これも見えませんがあることにします)。
8000番地からRUNするとピーと音がしてLEDが消灯します。ゲーム開始です。各LEDにはコンピュータが乱数を使
って1~8の数を隠しています。そのうち1つは1回でゴールに到着できるようにセットされています。
プレーヤーはスタートポジションを選択するため1~8のどれかを押します。ピッと音がしてその数で示される桁位置の
LEDが点灯します。表示される数は右または左に進むステップ数です。プレーヤーは右に進むか左に進むかをキー入
力で示します。右ならWRITE INCを、左なら0を押します。指定した方向にステップ数だけ移動すると、そこでまたピッ
と音がして次のLEDが点灯します。うまくLEDの右に進んでちょうどゴールで止まればゲーム終了です。ゴールに来て
もまだ進むステップが残っているときは残った数だけ左に戻ってしまいます。左に進んだときも同じで左端のLEDを超え
てダミーポジションも超えてしまうと残ったステップ数だけ右へもどってしまいます。ダミーポジションで止まってしまわな
いように計算されています。またゴールに直接行けるのは1ヶ所だけです。みごとゴールできるとプーと音がして、それま
での試行回数が表示されて、2秒間点滅します。そのあと2秒静止してからまた始めに戻って再びゲームが開始されま
す。
運が悪いと同じところをぐるぐる回るだけでゴールに行けないこともあります。リセットしてやり直してください。
プログラムの説明
まず最初に乱数によって1~8のうちのどれかを選びます。これが最後にゴールに到着するときのステップ数です。つ
ぎにこの数をセットするLEDを計算で求めます。実際にはLED位置に対応するDTBFに数を格納します。最初にDTBF
を全て00でクリアしています。その結果HLレジスタはDTBF8バイトの次のアドレス(8208)になっています。;last
position selectのところです。RNDルーチンによって、たとえば1が選ばれたとすると、ゴールに1ステップで行けるのは
右端のLED(アドレスは83FF)です。ここに対応するDTBFのアドレスは8207です。つまり選択したステップ数をHL(8
208)からマイナスすると、その数を格納するDTBFアドレスが求められます。そこでLからEを引く計算をしているので
す。
次の;data set では残った7つの場所にやはりRNDによって1~8のいずれかを選んでセットしていきます。最初にセッ
トした最終ポジションはパスします(DTST2:)。ルールにより、ゴールに行けるのは1個所だけ、また左のダミーポジジョ
ンで止まってしまうこともないようにするため、RNDで選んだステップ数とそれを格納するDTBFアドレス(下位アドレス
はLED位置と同じ)とから、次のポジションを計算してみて、その結果が08(ゴール)のときとFF(ダミー)のときを除外し
ます(DTST3:)。
さてKEYから0(左)かWRITE INC(右)かを入力すると、Dレジスタにある現在の位置情報(00~07)と、次の場所
へのステップ数(Eレジスタ)から、次のポジションを算出します。右へ進む場合と左へ進む場合とで処理が異なりま
す。;step to right と;step to left です。
ここでは何だかよくわからない計算をしています。まず右の場合です。D+Eが次のポジションになること、それからそ
の次のポジションが08ならゴール(右端のLEDのポジションが07なので)であることは納得できると思います。問題は
加算の結果が08より大きい場合です。この場合は08を超えた分だけ左に戻ります。ここはどうしているかというと、NE
GそしてANI 07で次のポジションとしています(???)。
NEGは8080には無い命令です。その代わりとしてCMAとINR Aを使っています。NEGはネガティブで0-Aを結果
とします。たとえば08より1だけ多い09について考えてみます。この場合ゴールから1ステップだけ左に戻りますから、
次のポジションは07です。では09に対してNEG命令を実行すると結果はどうなるのでしょうか?0-9=-9ですからA
レジスタの値はF7になります。どーして-9がF7になるの?という人はこの説明書を最初から順に読んでこなかった人
です。F7は10進に直すと247ですが、符号付の数として考えたときには-9なのです。
うーん。わからない?F7に09を加算してみてください。
11110111 (F7)
247
9
00001001 (09)
1 00000000 (0100)
256
結果は0100で16ビット(2バイト)の数として見れば10進に直して256となります。これは正しい。では2バイトではなく
てオーバーフローを許して結果も1バイトだとするとどうなるでしょうか?あくまで結果も1バイトにするのですから0100
ではなくて00になります。ほら-9+9=0で結果は合っています。
どーもおかしい。だまされているみたいだ、と思うかもしれませんがそういうことだと覚えてしまってください。慣れてくる
とだんだん納得できるようになります。
さてもとに戻って説明を続けます。NEG命令によってもとのAレジスタの値は09からF7に変わります。そこでANI 07
を実行するとあら不思議、行くべきポジションの07になります。
次は左の処理です。D-Eが次のポジションになることは分かると思います。ただし結果がプラスの場合に限ります。
50
減算結果がマイナス(Cフラグが立つ)の時はどうするか?またNEG命令を使っています。マイナスのマイナスでプラス
になります(もー、余計にわからーん!)。右の処理で説明したことと考え方は同じです。左の処理ではNEGのあとでSU
I 02を行っています。どーしてこれでよいのか各自確かめてみてそして考えてみてください。
2016/4/20
END=8173
8000
8003
8004
8005
C30680
00
00
00
8006 CDB480
8009
800A
800B
800D
800E
800F
8010
8012
3C
5F
3E08
93
6F
57
2682
73
8013
8016
8018
8019
801A
801D
210082
0608
7D
BA
CA3080
CDB480
8020
8021
8022
8023
8025
8028
8029
802A
802C
802F
8030
3C
4F
85
FE08
CA1D80
7D
91
FEFF
CA1D80
71
23
14:26
sugorok8.txt
; SUGOROKU for NDZ (SKIP OUT)
; 03/05/01 5/2 5/5 5/12 5/13
;10/6/3 for ND80Z3
;7/21 9/17
;16/4/20 for nd8080
;
ORG $8000
DTBF=$8200;$E800
;
RNDDT=$E810;$E811
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
D1=$02DD;4.684ms
;
JMP START
RNDDT:NOP
NOP
RNDDT2:NOP
;last position select
START:CALL RND3
;
ANI 07
INR A
MOV E,A;distance from goal
MVI A,08;goal position
SUB E
MOV L,A
MOV D,A;last position save
MVI H,82;high address of DTBF
MOV M,E
;data set
LXI H,DTBF
MVI B,08
DTST2:MOV A,L
CMP D
JZ DTST4;skip last position
DTST3:CALL RND3
;
ANI 07
INR A
MOV C,A;DATA save
ADD L;next position(right)
CPI 08;goal position
JZ DTST3
MOV A,L
SUB C;next position(left)
CPI FF;dummy position
JZ DTST3
MOV M,C
DTST4:INX H
51
;?
8031 05
8032 C21880
8035 210000
8038 22F683
803B 22F483
803E
8041
8043
8045
CDD280
3E0A
0610
CD0A81
8048
8049
804C
804F
8051
8054
8055
8058
8059
805C
805E
805F
8062
05
C24580
CDF480
FE09
D24C80
3D
FA4C80
57
3AF783
C601
27
32F783
CD4B81
8065
8068
8069
806C
806E
CDF480
B7
CA8580
FE15
C26580
8071
8072
8073
8075
8078
7A
83
FE08
CA9180
DA7F80
807B
807C
807D
807F
8082
2F
3C
E607
CDD280
C35880
8085 7A
8086 93
8087 D27F80
808A
808B
808C
808E
2F
3C
D602
C37F80
8091 3E00
8093 0610
8095 CD0A81
DJNZ *DTST2
DCR B;
JNZ DTST2;
;GAME START
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
SHLD DP1
;key entry(1-8)
CALL CLR
MVI A,0A
MVI B,10
START1:CALL SOUND
;?
DJNZ START1
DCR B;
JNZ START1;
KEY:CALL KEYIN1S;1-8 input
CPI 09
JNC KEY
DCR A
JM KEY
NEXT:MOV D,A;position save
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
CALL DTDP;data disp and save to E
;right or left in
KEY1:CALL KEYIN1S
ORA A
JZ LEFT
CPI 15;WRITE INC
JNZ KEY1
;step to right
MOV A,D;current position(00-07)
ADD E;E=step No.
D+E=next position
CPI 08
JZ GOAL
JC RIGHT1;
D+E<08
;?
NEG; 0-A
CMA;
INR A;
ANI 07;next position
RIGHT1:CALL CLR
JMP NEXT
;step to left
LEFT:MOV A,D;current position(00-07)
SUB E;E=step No.
JNC RIGHT1
;?
NEG
CMA;
INR A;
SUI 02;next position
JMP RIGHT1
;goal
GOAL:MVI A,00
MVI B,10
GOAL1:CALL SOUND
;?
DJNZ GOAL1
52
8098
8099
809C
809F
80A2
80A5
80A8
80AA
05
C29580
CDD280
CDFC80
CDC001
CDDF80
0614
CDFC80
80AD 05
80AE C2AA80
80B1 C30680
80B4
80B5
80B6
80B9
80BA
80BB
80BD
80BE
80C1
80C4
80C5
80C6
80C8
80C9
80CC
80CF
80D0
80D1
E5
D5
2A0380
23
7C
E603
67
220380
3A0580
57
7E
E607
BA
CAB680
320580
D1
E1
C9
80D2
80D5
80D8
80D9
21F883
010008
71
23
80DA 05
80DB C2D880
80DE C9
80DF
80E1
80E3
80E5
80E8
80EA
80EC
060A
3EEF
D398
CDFC80
3EFF
D398
CDFC80
80EF 05
80F0 C2E180
80F3 C9
80F4 C5
DCR B;
JNZ GOAL1;
CALL CLR
CALL TM01S
CALL DTDPS;COUNTER disp
CALL ALBLNK
MVI B,14;=20 2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED clear
CLR:LXI H,LED1
LXI B,$0800
CLR2:MOV M,C
INX H
;?
DJNZ *CLR2
DCR B;
JNZ CLR2;
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
53
80F5
80F6
80F9
80FA
80FB
D5
CD1602
D1
C1
C9
80FC
80FD
80FF
8100
8103
8104
8105
8108
8109
D5
1E15
D5
CDDD02
D1
1D
C2FF80
D1
C9
810A
810B
810C
810D
810E
8111
8112
8113
8114
8116
8117
8119
811B
811C
811D
8120
8121
8123
8125
8126
8127
812A
812B
812E
812F
8130
8131
8132
F5
E5
D5
C5
213381
85
6F
46
1E1A
50
3EFF
D398
7F
15
C21B81
50
3EDF
D398
7F
15
C22581
1D
C21681
C1
D1
E1
F1
C9
8133
8134
8135
8136
8137
8138
8139
813A
813B
813C
813D
7F
77
71
6A
5F
59
54
4F
47
43
3F
PUSH D
CALL KEYIN1
POP D
POP B
RET
;
;
;0.1sec timer
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
SOUND:PUSH PSW
PUSH H
PUSH D
PUSH B
LXI H,SNDTBL
ADD L
MOV L,A
MOV B,M
MVI E,1A
SNDS1:MOV D,B
MVI A,FF;SP OUT=H
OUT 98
SNDS2:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS2;10---MOV D,B
MVI A,DF;sp out=L
OUT 98
SNDS3:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS3;10---DCR E
JNZ SNDS1
POP B
POP D
POP H
POP PSW
RET
; SOUND TABLE
SNDTBL:DB 7F;so4
DB 77;so#4
DB 71;ra4
DB 6A;ra#4
DB 5F;do5
DB 59;do#5
DB 54;re5
DB 4F;re#
DB 47;fA5
DB 43;fa#5
DB 3F;so5
20/2=10microsec
20/2=10microsec
54
813E
813F
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
814A
3B
35
32
2F
2C
25
27
2A
4B
38
64
23
21
814B
814C
814F
8150
8151
8152
8153
8156
8157
8159
815A
815B
815C
815F
8160
8161
8162
8163
8165
8167
7A
210082
85
6F
7E
5F
216B81
4F
0600
09
7E
47
21F883
7A
85
6F
70
3E10
0603
CD0A81
816A
816B
816C
816D
816E
816F
8170
8171
8172
8173
C9
5C
06
5B
4F
66
6D
7D
27
7F
ALBLNK
CLR2
DP1
DTDP
DTST2
GOAL
KEY1
LED1
RIGHT1
RNDDT
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
3B;so5#
35;ra#5
32;si5
2F;do6
2C;do#6
25;mi6
27;re#6
2A;re6
4B;mi5
38;ra5
64;si4
23;fa6
21;fa#6
;
;
;DATA disp and save to E
DTDP:MOV A,D
LXI H,DTBF
ADD L
MOV L,A
MOV A,M
MOV E,A;DATA save
LXI H,SEGDT
MOV C,A
MVI B,00
DAD B
MOV A,M
MOV B,A;segment data
LXI H,LED1
MOV A,D
ADD L
MOV L,A
MOV M,B
MVI A,10
MVI B,03
DTDP1:CALL SOUND
;?
DJNZ *DTDP1
RET
SEGDT:DB 5C;0
DB 06;1
DB 5B;2
DB 4F;3
DB 66;4
DB 6D;5
DB 7D;6
DB 27;7
DB 7F;8
;
=80DF ALBLNK1
=80E1
=80D8 CNTR
=83F7
=83F4 DP3
=83F6
=814B DTDP1
=8167
=8018 DTST3
=801D
=8091 GOAL1
=8095
=8065 KEYIN1
=0216
=83F8 LEFT
=8085
=807F RND2
=80B6
=8003 RNDDT2
=8005
save
CLR
D1
DTBF
DTDPS
DTST4
KEY
KEYIN1S
NEXT
RND3
SEGDT
=80D2
=02DD
=8200
=01C0
=8030
=804C
=80F4
=8058
=80B4
=816B
55
SNDS1
SNDTBL
START1
WAIT
=8116
=8133
=8045
=80AA
SNDS2
SOUND
TM01S
=811B
=810A
=80FC
SNDS3
START
TM01S2
=8125
=8006
=80FF
56
プログラム№11 REVERSE(REVERSE8.BTK)
ゲームの説明
数字の並べ替えゲームです。
8000番地からRUNすると1~8の数がばらばらの順序で表示されます。これをルールにしたがって12345678に
並べ替えるとゲーム終了です。
1~8の数を入力すると左からその桁数分の表示が点滅します。WRITE INCを押すと入力が確定します。WRITE I
NCを押すまでは入力をやり直すことができます。WRITE INCによって入力が確定すると点滅していた表示が左右反
転します。これを繰り返して12345678が完成すると全体が2秒間点滅します。次に試行回数が表示され2秒間静止し
ます。そのあとまた始めに戻って再びゲームが開始されます。
プログラムの説明
まず最初にDTBF(8バイト)をクリアします。ここに1~8の数をランダムに選んで格納します。8桁の数ですし、LEDに
表示するわけですから、LED表示用のメモリエリア(83F4~83F7)を使うか、アドレスレジスタ及びデータレジスタ(83
EC~83EF)を使った方が結果の表示は簡単になります。そうすると8桁のBCD数として扱うことになります。しかし今
回のプログラムのように桁単位で数の入れ替えが必要な処理ではBCD数というのはなかなかに面倒なのです。1桁が
4ビットなのですが8080には4ビット単位でデータを扱う命令はありません。4ビット単位で扱うにはシフト命令で1ビット
ずつ4回シフトして1桁ごとに分離するしかありません。そこでこのプログラムでは処理のたびにどうせ1桁ずつ分離しな
ければならない(今のところ、多分)のならはじめから分離して1桁ずつの数にして(たとえば、56というBCD数ではなく
て、05、06という数にして)8バイトのデータエリアに格納し、ここで1バイト単位で数の入れ替えをするように考えました。
1バイト単位ならいろんな命令が使えるので楽になりそうです。8バイトのデータバッファの内容を表示するには、4バイト
のBCD数に直さなければいけませんが、これは結果を表示するときだけですから、変換するサブルーチンを作って処理
することにしました。
まずDTBFを0クリアします。DTST0:のところです。ここまでにも出てきてると思いますが、XRA AはMVI A,00の
代わりとしてよく使います。Aレジスタを00にするため以外の意図はありません。DTST1:以下のところで1~8の数を
乱数によりランダムに作り、それをDTBFに格納しています。なんだかややこしいことをしているようですが、これは1~8
を1度だけ選んで格納するための処理なのです。まずRNDにより1~8のうちの1つの数を選び、それをDTBFに格納
するのですが、そのときDTBFの先頭から順にメモリの内容を確認します(DTST2:)。ここでテクニックを使っています。
MOV A,Mとして、ORA Aなどとしたいところですが、AレジスタにはRNDで選んだ数がすでに入っています。PUSH
PSWとするとか、MOV D,AとしたりしてまずAの中身を退避させておいて…などと考えるのは、教条主義です(懐かし
い言葉。知らないだろうなー。今どき)。ここは遊んでいるCレジスタを使ってDCR Cとしてしまいます。メモリの内容が0
0ならDCR Cの結果はFFになって、前のプログラムで出てきたようにマイナスになるのでSフラグが立ちます。でJMと
いくわけです。ついでですが、SUB命令などではマイナスになると同時にキャリー(Cフラグ)も立つので、よくJCを使い
ますが、DCRとINRについてはCフラグのみ変化しないので注意してください。
さてDTBFを前から順に確認していって最初に00の場所をみつけたら、Aに入っている数を格納してしまいます(あ
れ?同じ数を選んでしまったかどうかの確認はしなくてもよいのか?)。プログラムの流れでは逆になっているようで分か
りにくいのですがちゃんとやっているのです(DTST3:)。RNDで新しい数を選んだら必ずDTBFの先頭から内容を確認
しています。もし00でなかったらDTRD3:で同じ数か異なる数かをチェックします。ですからこのチェックをパスしてきて、
もう比較するデータが無い(つまり次のDTBFの内容が00のとき)なら、新しく出てきた数になるのでDTBFに格納しても
よいことになります。
RNDで乱数がうまく作り出せなくてアドレスが8000の表示のままでハングアップしてしまうことがあります。リセットし
てもう一度8000から実行してみてください。
無事8桁の数が決まったらまずLEDに表示します。DTBFDPサブルーチンです。DTBFの8バイトの数をBCD4バイト
に変換してDP1~に格納します。DTBFは8バイトですが内容は下位4ビットに1~8が入っているだけですから、最初
のバイトを読んでそれを左に4ビットシフトして、そこに次のバイトの下位4ビット(上位4ビットは常に0)をORで合わせれ
ばBCD2桁が出来あがります。最後にLED表示ルーチンをCALLします。
キーの入力です。入力前にCレジスタに01を入れています。あとで出て来ますが、Cレジスタにはキー入力した1~8
の桁指定数が入るのです。普通はまず桁指定の数を入力して、次にWRITE INCの入力ですが、そのようにキー入力
ルーチンを2段階に並べても、WRITE INCの入力待ちのときに数値を入れなおす場合もでてきます。そうすると結構
複雑なプログラムになってしまいます。ここはこのプログラムのように数値でもWRITE INCでもその入力順序に関係無
く受けつけてしまうとよいのです。数値が入力されたらそれをCレジスタに保存しておけば、次にWRITE INCが押され
たときにCレジスタの値をもって処理ルーチンへ行くことができます。しかし中にはまだ数値を入力していないのにWRIT
E INCを押してしまうあわて者がいるかもしれません。最初にCレジスタに01を入れているのはこのあわて者対策です。
データを反転させる桁数で1を指定しても結果は変わりません。このあとで出てくる反転処理ルーチン(REV:)ではC=
01のときは何もしないでリターンします。
ではいよいよそのREV:の説明です。何をしているのかちょっと見にはよくわかりません。でもここはごく当たり前の処
理をしています。まずDTBFのトップ(LEDの左端に相当)アドレスをHLに、そしてCレジスタの値から、反転させる範囲
57
の右端のDTBFアドレスを算出してDEに入れます。CレジスタはC=01をチェックするためとDEへのアドレス計算のた
めにDCRしたものをもとに戻すためINRしたあとSRLを実行します。SRLも8080には無い命令です(その代わりとして
複数の命令を使っています)。Cレジスタの値が1/2になります。もとの値が奇数の場合は1/2した結果できる端数は
切り捨てられます。
これで準備完了です。AレジスタとBレジスタを利用して両端のデータ、(HL)と(DE)を入れ替えます。このあとHLを+
1、DEを-1します。つまり外側から内側に1バイトずつアドレスを寄せるのです。この処理をC=00になるまで繰り返
すとデータの前後が全部入れ替わります。対象が奇数桁の場合には中央の桁は動きません。アドレスをHLとDEで1ず
つせばめるのでCを1/2にしているのですが、奇数桁の場合には最後に残った1バイトは中央にあって動きませんから
Cを1/2したときに切り捨ててよいのです。むむ、我ながら、なんと巧妙な(自画自賛)。
この部分がもしBCD数であったとすると面倒な処理になります。
データを入れ替えたあと、結果をLEDに表示します(DTBFDP)。そのあと、数字が並んだかどうかチェックします
(;compare DATA)。ここもBCD数だと面倒です(ただし今回は結果が12345678になったかどうかの比較をすればよ
いので各桁の大小比較をするよりずっと楽ではあります)。このプログラムではDTBFを先頭から順に読み出して、大小
を比較するだけで済みますからいとも簡単です。
順序が逆になってしまいましたがBLNKCについて説明します。指定した桁の表示だけブリンクさせるものです。ブリン
クする桁数をCレジスタに入れます。ブリンクする準備として対象になるLEDレジスタの内容をBLNKBFにコピーします。
準備ができたら0.1秒ごとにLEDレジスタの内容を読み出して、BLNKBFと比較します。ここは比較しなくても00かど
うかを確認すればよいのですが、その次にBLNKBFの値をLEDレジスタにコピーする作業があるため、先にAレジスタ
にBLNKBFの値を読み出すという、普通の考えとは逆のようなことをしています(CMP MはあるがCMP (DE)という
命令は無い)。こういうところがちょいとした工夫です。内容が一致したら、LEDレジスタに00を書き込み、不一致なら
(つまりLEDレジスタの内容が00なら)BLNKBFにコピーしてあるもとの表示データをLEDレジスタに書き込みます。こ
れを繰り返すと表示がブリンクします。このル-チンではブリンク中にキーからの入力も確認しています。キー入力があ
るとブリンクを停止してBLNKBFの内容をもとのLEDレジスタに戻してリターンします。
2016/4/20
END=8182
8000
8003
8004
8005
8006
8007
8008
8009
800A
800B
800C
C31780
00
00
00
00
00
00
00
00
00
00
10:30
reverse8.txt
; REVERSE for NDZ
; 03/04/29 4/30 5/1 5/2 5/5 5/13 5/15
;10/6/3 for ND80Z3
;16/4/19 for nd8080
;4/20
;
ORG $8000
;
DTBF=$E800
;
BLNKBF=$E808
;
RNDDT=$E810;$E811
;
CNTR=$E812
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
KEYIN2=$0223;$0623
;
;data set
JMP START
DTBF:NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BLNKBF:NOP
NOP
58
800D
800E
800F
8010
8011
8012
8013
8014
8015
8016
00
00
00
00
00
00
00
00
00
00
8017
801A
801D
801E
801F
8020
8022
8025
8026
8027
3AD2FF
211380
77
23
77
0608
210380
AF
77
23
8028 05
8029 C22680
802C CDC480
802F
8030
8032
8035
8036
8037
803A
3C
0608
210380
4E
0D
F24280
77
803B
803C
803F
8042
8043
8046
05
C22C80
C34B80
BE
CA2C80
23
8047
8048
804B
804E
804F
05
C23580
CD3181
AF
321680
8052
8054
8057
8059
805C
805E
8061
8063
0E01
CD4B81
FE15
CA6D80
FE09
D25480
FE02
DA5480
8066 4F
8067 CDF780
NOP
NOP
NOP
NOP
NOP
NOP
RNDDT:NOP
NOP
RNDDT2:NOP
CNTR:NOP
;
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
MVI B,08
LXI H,DTBF
XRA A
DTST0:MOV M,A
INX H
;?
DJNZ *DTST0
DCR B;
JNZ DTST0;
DTST1:CALL RND3
;
ANI 07
INR A
MVI B,08
LXI H,DTBF
DTST2:MOV C,M
DCR C
JP DTST3
MOV M,A
;?
DJNZ *DTST1
DCR B;
JNZ DTST1;
JMP ENTRY
DTST3:CMP M
JZ DTST1
INX H
;?
DJNZ *DTST2
DCR B;
JNZ DTST2;
ENTRY:CALL DTBFDP
XRA A
STA CNTR;DECIMAL COUNTER clear
;key entry(1-8)
REENT:MVI C,01
KEY:CALL KEYIN1S
KEY1:CPI 15;WRITE INC
JZ REV
CPI 09
JNC KEY
CPI 02
JC KEY
;blink select data
MOV C,A
CALL BLNKC
59
806A C35780
806D
806E
8071
8074
8075
8076
8077
8078
0D
CA5280
210380
54
79
85
5F
0C
8079
807A
807B
807C
807D
807E
807F
8080
8081
8082
8083
8084
8085
8086
8087
808A
808D
8090
8092
8093
F5
79
B7
1F
4F
F1
1A
46
77
78
12
23
1B
0D
C27F80
CD3181
3A1680
C601
27
321680
8096
8099
809B
809C
809D
809E
210380
0607
7E
23
BE
D25280
80A1 05
80A2 C29B80
80A5 CDE280
80A8
80AB
80AE
80B1
80B2
80B5
80B8
80BA
210000
22F483
3A1680
67
22F683
CDC001
0614
CD5B81
80BD 05
80BE C2BA80
80C1 C31780
JMP KEY1
;reverse
REV:DCR C
JZ REENT
LXI H,DTBF
MOV D,H
MOV A,C
ADD L
MOV E,A
INR C
;?
SRL C
PUSH PSW;
MOV A,C;
ORA A;
RAR;
MOV C,A;
POP PSW;
REV1:LDAX D
MOV B,M
MOV M,A
MOV A,B
STAX D
INX H
DCX D
DCR C
JNZ REV1
REV2:CALL DTBFDP
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
;compare DATA
LXI H,DTBF
MVI B,07
COMP1:MOV A,M
INX H
CMP M
JNC REENT;not yet
;?
DJNZ *COMP1
DCR B;
JNZ COMP1;
;OK! ALL LED blink
CALL ALBLNK
;COUNTER disp
LXI H,$0000
SHLD DP1
LDA CNTR
MOV H,A
SHLD DP3
CALL DTDPS
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
;ransu
60
80C4
80C5
80C6
80C9
80CA
80CB
80CD
80CE
80D1
80D4
80D5
80D6
80D8
80D9
80DC
80DF
80E0
80E1
E5
D5
2A1380
23
7C
E603
67
221380
3A1580
57
7E
E607
BA
CAC680
321580
D1
E1
C9
80E2
80E4
80E6
80E8
80EB
80ED
80EF
060A
3EEF
D398
CD5B81
3EFF
D398
CD5B81
80F2 05
80F3 C2E480
80F6 C9
80F7
80F8
80FB
80FE
79
21F883
110B80
0600
8100
8103
8104
8107
810A
810B
810C
810D
8110
8111
8112
8113
CD7681
4F
21F883
110B80
41
1A
BE
C21181
AF
77
23
13
8114
8115
8118
811B
811E
811F
8122
8123
05
C20B81
CD5B81
CD5381
3C
CA0481
3D
210B80
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;LED blink
BLNKC:MOV A,C;save C
LXI H,LED1
LXI D,BLNKBF
MVI B,00
;?
LDIR
CALL LDIR
MOV C,A
BLNKC1:LXI H,LED1
LXI D,BLNKBF
MOV B,C
BLNKC2:LDAX D
CMP M
JNZ BLNKC3
XRA A
BLNKC3:MOV M,A
INX H
INX D
;?
DJNZ *BLNKC2
DCR B;
JNZ BLNKC2;
CALL TM01S
CALL KEYIN2S
INR A
JZ BLNKC1;no key in
DCR A;key data
LXI H,BLNKBF
61
8126 11F883
8129 0600
812B C5
812C CD7681
812F C1
8130 C9
8131
8134
8137
8139
813A
813B
813C
813D
813E
813F
8140
8141
8142
210380
11F483
0604
7E
07
07
07
07
23
B6
12
23
13
8143
8144
8147
814A
05
C23981
CDC001
C9
814B
814C
814D
8150
8151
8152
8153
8154
8155
8158
8159
815A
C5
D5
CD1602
D1
C1
C9
C5
D5
CD2302
D1
C1
C9
815B
815C
815E
8161
8162
8165
8166
D5
1E64
CD6781
1D
C25E81
D1
C9
8167
8168
816A
816C
816D
8170
D5
1607
1E12
1D
C26C81
15
LXI D,LED1
MVI B,00
PUSH B
;?
LDIR
CALL LDIR
POP B
RET
;
;DTBF data disp
DTBFDP:LXI H,DTBF
LXI D,DP1
MVI B,04
DTBFDP1:MOV A,M
RLC
RLC
RLC
RLC
INX H
ORA M
STAX D
INX H
INX D
;?
DJNZ *DTBFDP1
DCR B;
JNZ DTBFDP1;
CALL DTDPS
RET
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
POP D
POP B
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,64;=100
TM01S2:CALL TM1M
DCR E
JNZ TM01S2
POP D
RET
;
;1msec timer
TM1M:PUSH D;11
MVI D,07; ck=5 (11+7+292*7+10+10)/2.048=2082/2.048=1016
TM1M2:MVI E,12;=18 ck=7 7+15*18+15=292
TM1M3:DCR E;5
JNZ TM1M3;10
DCR D;5
62
8171 C26A81
8174 D1
8175 C9
8176
8177
8178
8179
817A
817B
817C
817D
817E
8181
8182
F5
7E
12
23
13
0B
78
B1
C27781
F1
C9
ALBLNK
BLNKC
BLNKC3
DP1
DTBFDP
DTST0
DTST3
KEY1
KEYIN2
LDIR2
REENT
REV2
RNDDT
TM01S
TM1M2
JNZ TM1M2;10
POP D;10
RET;10
;
LDIR:PUSH PSW
LDIR2:MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ LDIR2
POP PSW
RET
;
=80E2 ALBLNK1
=80F7 BLNKC1
=8111 CNTR
=83F4 DP3
=8131 DTBFDP1
=8026 DTST1
=8042 ENTRY
=8057 KEYIN1
=0223 KEYIN2S
=8177 LED1
=8052 REV
=808A RND2
=8013 RNDDT2
=815B TM01S2
=816A TM1M3
=80E4
=8104
=8016
=83F6
=8139
=802C
=804B
=0216
=8153
=83F8
=806D
=80C6
=8015
=815E
=816C
BLNKBF
BLNKC2
COMP1
DTBF
DTDPS
DTST2
KEY
KEYIN1S
LDIR
R
REV1
RND3
START
TM1M
WAIT
=800B
=810B
=809B
=8003
=01C0
=8035
=8054
=814B
=8176
=FFD2
=807F
=80C4
=8017
=8167
=80BA
63
プログラム№12 ROCK CLIMBING(ROCKCLM8.BTK)
ゲームの説明
これは今までのゲームとは異なり、コンピュータ相手ではなく、二人で行う対戦ゲームです。お互いに0mからスタート
し途中に足場を築きながら速く100mを登った方が勝ちというものです。運が悪かったりあまり先を急ぎすぎるとときどき
転落してしまいます。
8000番地からRUNするとLEDの左側と右側にそれぞれスタートの000が表示されます。プレイは交互に行います。
先攻は左側です。まず左のLEDが点滅してキー入力待ちになります。プレーヤーは上に登るかここで休憩して足場を築
くか選択することができます。上に登るならREAD INCを押します。休憩して足場を築くならREAD DECを押します。
登る場合にはLEDの1桁目(後攻は5桁目)に”8”の上側のセグメントのみ点灯表示されます。休憩なら”8”の下側のセ
グメントが点灯表示されます。確定するにはWRITE INCを押します。WRITE INCの入力前なら登るか休憩するかの
選択を変更することができます。
上に登るを選択した場合、コンピュータは乱数を利用したサイコロを2回振って出た目の合計を上に登るm数として現
在のmに加算して表示します。ただしどちらのサイコロでも1の目が出ると前の足場まで転落してしまいます。もし足場を
築いていないときは0mまで転落してしまいます。転落したら攻守交代です。適当なところまで登ったら一旦休憩してそこ
を足場にする方がよいようです。休憩したときも攻守交代になります。転落する確率は1/3ですからかなり高率です(ち
ょっとサイコロに片寄りがあって続けて転落したり片方のプレーヤーだけやたら有利なときがあります)。
どちらかが先に100mに到達すると(100mを超えてもよい)全体が2秒間点滅します。そのあとまた始めに戻って再
びゲームが開始されます。
プログラムの説明
足場を記憶するために各1バイトのメモリエリアを使います。BCDデータで00~99を入れればよいので1バイトで足り
ます。プレーヤー1の現在の位置を記憶するためにアドレスレジスタを、プレーヤー2のそれにはデータレジスタをその
まま使います。BCD数として扱うのでこうすれば表示のための処理の手間が省けます。
今回はもっと大胆に(?)手間を省くため、プレーヤー1とプレーヤー2の処理を同じプログラムでやってしまいます。そ
のためにHLレジスタだけでは足りないので、IXレジスタとIYレジスタを動員します(残念ながら8080にはIXレジスタもIY
レジスタもありませんから代わりにワークエリアとしてIXWK、IYWKを使っています)。HLにはLEDの1桁目か5桁目の
アドレスを入れます。登るか休むかのマークを表示するためです。IXWKには現在の位置データの格納アドレス(PLYR
1かPLYR2)を入れます。IYWKには足場データを記憶するアドレス(ASI1かASI2)を入れます。両者の処理の違いは
これだけなので、その相違しているところを、HL、IXWK、IYWKに入れてしまうと、全く同じ処理で済んでしまいます。
それでは処理の内容を見ていきます。DTDPで両プレーヤーの現在位置をLEDに表示します。LED1とLED5はブラ
ンクにします。次にLEDブリンクとキー入力を行います(BLNK)。このサブルーチンは №11 REVERSE のBLNK
Cと同じ動作です。今回はブリンクする桁が3バイト固定なのでCレジスタの使い方は異なります。BLBKルーチンの中
でキー入力をチェックしますが、READ INC(14)かREAD DEC(13)以外は受け付けません。いずれかをAレジスタ
に入れてリターンします。
USDISP:ではAレジスタの内容によりLEDに登りのマークか休憩のマークを表示します。ANI 03は入力されたコー
ドの14と13を簡単に区別ためのものでそれ以外の意味はありません。この値は後の処理のためCレジスタにも保存さ
れます。マーク表示後再びキー入力を待ちます(KEY:)。WRITE INCの入力を待つためです。このときまたREAD I
NCかREAD DECが入力されたら、USDISP:へ戻ってマークを表示します。WRITE INCが押されたら、Cレジスタを
確認します。DCR CでSフラグが立てばREAD INCなのでサイコロを振る処理に行きます(C=00のときDCR Cを
実行すると結果はFFでマイナスになる)。そうでなければ休憩(足場の処理)に行きます。
SAI:ではサイコロを2回振って出た目を加算します。Cレジスタを0クリアしておいて、ここに加算します。サイコロは1
~6ですが処理を簡単にするため、乱数で0~5を求め、これに1を加えます。ただし+1する前に0であれば、これは1
の目ですから、墜落の処理(DOWN)へ行きます。
サイコロの目を2回加算した結果はCレジスタとAレジスタに入ります。Cは2回加算を行うためのワークとして使っただ
けなので、この後の処理では用済みです。Aレジスタを使います。Aレジスタと現在の高さデータ(IXWKにその格納メモ
リアドレスがある)を加算します。加算した結果、キャリーが発生すればBCD2桁の加算でオーバーフローが発生したわ
けですから、100mを超えたことになります。ゲーム終了です。そうでなければ同じプレーヤーで最初の表示ブリンクと
キー入力待ちの処理に戻ります。
ASISET:では足場データの更新を行います。IXWKで示されるメモリアドレスに入っている現在の高さデータをIYWK
で示される足場データの入っているメモリアドレスにCOPYします。そのあと選手交代の処理をします。現在がどちらの
プレーヤーの番かはHLレジスタに入っているのが、LED1のアドレスかLED5のアドレスかを見ればわかります。そこで
選手交代して最初の処理に戻ります。
DOWN:ではIXWKに入っている現在の高さを格納するメモリアドレスにIYWKの情報で示される足場データをCOPY
します。そのあと選手交代の処理をしてゲームを続けます。
2016/4/20
10:36
rockclm8.txt
64
END=817F
8000
8003
8004
8005
8006
8007
8008
8009
800A
800B
800C
800D
800E
800F
8012
8015
8016
8017
8018
801B
801E
8021
C30F80
00
00
00
00
00
00
00
00
00
00
00
00
3AD2FF
210880
77
23
77
210000
22EE83
22EC83
220380
8024
8027
802A
802D
8030
8033
8036
21EE83
220B80
210380
220D80
21F883
CDEA80
CD0C81
8039 E603
; LOCK CLIMBING for NDZ
; 03/05/08 5/14
;10/6/3 for ND80Z3
;7/22 9/22
;16/4/19 for nd8080
;4/20
;
ORG $8000
;
ASI1=$E800
;
ASI2=$E801
;
BLNKBF=$E808
;
RNDDT=$E810;$E811
PLYR2=$83EC;$FFEC;=DTRG
PLYR1=$83EE;$FFEE;=ADRG
LED1=$83F8;$FFF8
LED5=$83FC;$FFFC
R=$FFD2
;
ADDPS=$01A1;$05A1
KEYIN1=$0216;$0616
KEYIN2=$0223;$0623
;
JMP START
ASI1:NOP
ASI2:NOP
BLNKBF:NOP
NOP
NOP
RNDDT:NOP
NOP
RNDDT2:NOP
IXWK:NOP
NOP
IYWK:NOP
NOP
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
LXI H,$0000
SHLD PLYR1
SHLD PLYR2
SHLD ASI1
;player1
REENT1:;LXI H,LED1
;?
LD IX,PLYR1
;?
LD IY,ASI1
LXI H,PLYR1;
SHLD IXWK;
LXI H,ASI1;
SHLD IYWK;
LXI H,LED1;
REENT2:CALL DTDP
CALL BLNK
;"UP" or "STAY" disp
USDISP:ANI 03
65
803B
803C
803E
8041
8043
8044
8047
8049
804C
804E
8051
8053
8056
4F
3E01
CA4380
3E08
77
CD4881
FE15
CA5980
FE13
CA3980
FE14
C24480
C33980
8059
805A
805D
8060
0D
F28280
010002
CDCC80
8063
8065
8068
8069
806C
806D
806E
806F
FE06
D26080
B7
CAA680
3C
81
27
4F
8070 05
8071 C26080
8074
8075
8078
8079
E5
2A0B80
86
27
807A
807B
807C
807F
77
E1
DAB380
C33380
8082
8083
8086
8087
808A
808B
E5
2A0B80
7E
2A0D80
77
E1
808C
808D
808F
8092
7D
E607
C22480
21FC83
8095 E5
8096 21EC83
MOV C,A;00 or 03 save
MVI A,01;"UP"
JZ USDISP1
MVI A,08;"STAY"
USDISP1:MOV M,A
KEY:CALL KEYIN1S
CPI 15;write inc
JZ SAI
CPI 13;read dec("STAY")
JZ USDISP
CPI 14;read inc("UP")
JNZ KEY
JMP USDISP
;saikoro
SAI:DCR C
JP ASISET;C=03(keyin=RD_DEC)
LXI B,$0200
SAI1:CALL RND3
;
ANI 07
CPI 06
JNC SAI1
ORA A
JZ DOWN
INR A
ADD C
DAA
MOV C,A
;?
DJNZ SAI1
DCR B;
JNZ SAI1;
;?
ADD A,(IX+00)
PUSH H;
LHLD IXWK;
ADD M;
DAA
;
STA IX+00
MOV M,A;
POP H;
JC WIN
JMP REENT2
;asiba set
ASISET:;LDA IX+00
;
STA IY+00
PUSH H;
LHLD IXWK;
MOV A,M;
LHLD IYWK;
MOV M,A;
POP H;
;change player
ASISET1:MOV A,L
ANI 07
JNZ REENT1;current HL=LED5
LXI H,LED5
;?
LD IX,PLYR2
;?
LD IY,ASI2
PUSH H;
LXI H,PLYR2;
66
8099
809C
809F
80A2
80A3
220B80
210480
220D80
E1
C33380
80A6
80A7
80AA
80AB
80AE
80AF
80B0
E5
2A0D80
7E
2A0B80
77
E1
C38C80
80B3
80B4
80B7
80B9
80BA
80BD
80C0
80C2
E5
210B80
3601
E1
CDEA80
CDF780
0614
CD5881
80C5 05
80C6 C2C280
80C9 C30F80
80CC
80CD
80CE
80D1
80D2
80D3
80D5
80D6
80D9
80DC
80DD
80DE
80E0
80E1
80E4
80E7
80E8
80E9
E5
D5
2A0880
23
7C
E603
67
220880
3A0A80
57
7E
E607
BA
CACE80
320A80
D1
E1
C9
80EA
80EB
80EE
80EF
80F0
80F3
80F6
E5
CDA101
E1
AF
32F883
32FC83
C9
SHLD IXWK;
LXI H,ASI2;
SHLD IYWK;
POP H;
JMP REENT2
DOWN:;LDA IY+00
;
STA IX+00
PUSH H;
LHLD IYWK;
MOV A,M
LHLD IXWK;
MOV M,A;
POP H;
JMP ASISET1
;? WIN:LD (IX+01),01
WIN:PUSH H;
LXI H,IXWK;
MVI M,01;
POP H;
CALL DTDP
CALL ALBLNK
MVI B,14;=20 2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;data disp
DTDP:PUSH H
CALL ADDPS
POP H
XRA A
STA LED1
STA LED5
RET
;
;LED all blink
67
80F7
80F9
80FB
80FD
8100
8102
8104
060A
3EEF
D398
CD5881
3EFF
D398
CD5881
8107 05
8108 C2F980
810B C9
810C
810D
810E
810F
8112
E5
23
E5
110580
010300
8115
8118
8119
811A
811D
811F
8120
8121
8124
8125
8126
8127
CD7381
E1
E5
110580
0603
1A
BE
C22581
AF
77
23
13
8128
8129
812C
812F
8132
8134
8137
8139
813C
813D
8140
05
C21F81
CD5881
CD5081
FE13
CA3C81
FE14
C21881
D1
210580
010300
8143 CD7381
8146 E1
8147 C9
8148
8149
814A
814D
814E
814F
8150
8151
8152
8155
C5
D5
CD1602
D1
C1
C9
C5
D5
CD2302
D1
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;LED blink and keyin HL=LED1 or LED5
BLNK:PUSH H;HL save
INX H
PUSH H
LXI D,BLNKBF
LXI B,$0003
;?
LDIR
CALL LDIR;
BLNK1:POP H
PUSH H
LXI D,BLNKBF
MVI B,03
BLNK2:LDAX D
CMP M
JNZ BLNK3
XRA A
BLNK3:MOV M,A
INX H
INX D
;?
DJNZ *BLNK2
DCR B;
JNZ BLNK2;
CALL TM01S
CALL KEYIN2S
CPI 13;read dec
JZ BLNK4
CPI 14;read inc
JNZ BLNK1
BLNK4:POP D
LXI H,BLNKBF
LXI B,$0003
;?
LDIR
CALL LDIR;
POP H
RET
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
POP D
68
8156 C1
8157 C9
8158
8159
815B
815E
815F
8162
8163
D5
1E64
CD6481
1D
C25B81
D1
C9
8164
8165
8167
8169
816A
816D
816E
8171
8172
D5
1607
1E12
1D
C26981
15
C26781
D1
C9
8173
8174
8175
8176
8177
8178
8179
817A
817B
817E
817F
F5
7E
12
23
13
0B
78
B1
C27481
F1
C9
ADDPS
ASI1
ASISET1
BLNK2
BLNKBF
IXWK
KEYIN1
KEYIN2S
LED1
PLYR2
REENT2
RNDDT
SAI1
TM01S2
TM1M3
WAIT
POP B
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,64;=100
TM01S2:CALL TM1M
DCR E
JNZ TM01S2
POP D
RET
;
;1msec timer
TM1M:PUSH D;11
MVI D,07; ck=5 (11+7+292*7+10+10)/2.048=2082/2.048=1016
TM1M2:MVI E,12;=18 ck=7 7+15*18+15=292
TM1M3:DCR E;5
JNZ TM1M3;10
DCR D;5
JNZ TM1M2;10
POP D;10
RET;10
;
LDIR:PUSH PSW
LDIR2:MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ LDIR2
POP PSW
RET
;
=01A1 ALBLNK
=80F7 ALBLNK1
=80F9
=8003 ASI2
=8004 ASISET
=8082
=808C BLNK
=810C BLNK1
=8118
=811F BLNK3
=8125 BLNK4
=813C
=8005 DOWN
=80A6 DTDP
=80EA
=800B IYWK
=800D KEY
=8044
=0216 KEYIN1S
=8148 KEYIN2
=0223
=8150 LDIR
=8173 LDIR2
=8174
=83F8 LED5
=83FC PLYR1
=83EE
=83EC R
=FFD2 REENT1
=8024
=8033 RND2
=80CE RND3
=80CC
=8008 RNDDT2
=800A SAI
=8059
=8060 START
=800F TM01S
=8158
=815B TM1M
=8164 TM1M2
=8167
=8169 USDISP
=8039 USDISP1
=8043
=80C2 WIN
=80B3
69
プログラム№13 WILD SEVEN(WILD78.BTK)
ゲームの説明
№5 SWAPと№11 REVERSEを組み合わせたようなゲームです。
8000番地からRUNするとLEDに1~7の数と1個のブランク(スペース)がばらばらにならんでいます。これをルール
にしたがって並べ替えて、1234567□にしてください。
ルールは№5 SWAPとほぼ同じです。スペースの隣にある数はスペースと入れ替えることができます。またスペース
の1つ飛んで隣にある数も間の数をジャンプしてスペースと入れ替えることができます。
移動したい数の指定は、表示されているLEDの位置を示す1~8の数を押すことで行われます。1~8の数を押すとそ
のLED位置にある数が点滅します。
WRITE INCを押すことで入力が確定します。WRITE INCを押す前ならばLED位置の指定をやり直すことができま
す。WRITE INCを押すと指定したLEDにスペースが移動し、スペースがあった所に指定した場所の数が移ります。ス
ペースと入れ替えができない位置を指定した場合にはWRITE INCを押しても移動は行われません。
この作業を繰り返して、1234567□(右端がスペース)が完成すると全体が2秒間点滅します。そのあと試行した回
数が2秒間表示されてから、また始めに戻って再びゲームが開始されます。
プログラムの説明
プログラムは№5 SWAPと№11 REVERSEをミックスしたようなものなのでほとんど新たに説明するところはありま
せん。REVERSEでは数値の表示を行うのにBCD数に直してLED表示データレジスタに入れて表示させていましたが
今回は1桁ずつセグメントデータに変換して直接LED表示レジスタに入れています。REVERSEの方法ではスペースが
0の表示になってしまうからです。
2016/4/20
END=816F
8000
8003
8004
8005
8006
C30780
00
00
00
00
8007
800A
800D
800E
800F
8010
8012
8014
8017
3AD2FF
210380
77
23
77
3EFF
0608
21F883
77
11:17
wild78.txt
; JUNNARABE for NDZ (WILD SEVEN)
; 03/05/02 5/5 5/14 5/23 5/24
;10/6/4 for ND80Z3
;9/17 9/18
;16/4/20 for nd8080
;
ORG $8000
;
RNDDT=$E810;$E811
;
CNTR=$E812
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
KEYIN2=$0223;$0623
;
JMP START
RNDDT:NOP
NOP
RNDDT2:NOP
CNTR:NOP
;data buffer clear
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
MVI A,FF
MVI B,08
LXI H,LED1
DTCLR:MOV M,A
70
8018 23
INX H
DJNZ *DTCLR
DCR B;
JNZ DTCLR;
;space position select
CALL RND3
;
ANI 07
LXI H,LED1
ADD L
MOV L,A
MVI M,00
;data set
MVI B,07
DTST1:CALL RND3
;
ANI 07
ORA A
JZ DTST1
;?
LD IX,SEGDT
LXI H,SEGDT;
MVI D,00
MOV E,A
;?
ADD IX,DE
DAD D;
;
LDA IX+00
MOV A,M;
LXI H,LED1
DTST2:MOV C,M
INR C
JNZ DTST3
MOV M,A
;?
DJNZ *DTST1
DCR B;
JNZ DTST1;
JMP ENTRY
DTST3:CMP M
JZ DTST1
INR L
JNZ DTST2
JMP DTST1
;GAME START
ENTRY:XRA A
STA CNTR;DECIMAL COUNTER clear
;key entry(1-8)
KEY:CALL KEYIN1S
CPI 09
JNC KEY
DCR A
JM KEY
;LED blink and wait WINC in
BLNK0:LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORA A
JZ KEY;space position
MOV D,A;LED data save
MOV B,A
MVI C,00
;?
8019 05
801A C21780
801D CD0A81
8020
8023
8024
8025
21F883
85
6F
3600
8027 0607
8029 CD0A81
802C B7
802D CA2980
8030 216881
8033 1600
8035 5F
8036 19
8037
8038
803B
803C
803D
8040
7E
21F883
4E
0C
C24880
77
8041
8042
8045
8048
8049
804C
804D
8050
05
C22980
C35380
BE
CA2980
2C
C23B80
C32980
8053 AF
8054 320680
8057
805A
805C
805F
8060
CD3D81
FE09
D25780
3D
FA5780
8063
8066
8067
8068
8069
806A
806D
806E
806F
21F883
85
6F
7E
B7
CA5780
57
47
0E00
71
8071
8072
8075
8078
807A
807D
807E
8081
8082
8085
8087
808A
808B
808C
808D
71
CD4D81
CD4581
FE09
D28580
3D
FA8A80
72
C36380
FE15
CA9080
79
48
47
C37180
8090
8091
8092
8094
8097
8098
8099
809A
809D
809E
80A0
80A3
80A4
80A5
80A6
80A9
80AA
80AB
80AC
80AE
80B0
80B3
80B4
80B5
80B6
80B9
80BA
80BC
80BE
80C1
80C2
80C3
80C4
E5
7D
E607
CAA980
2B
7E
B7
CAC780
7D
E607
CAA980
2B
7E
B7
CAC780
E1
E5
7D
E607
FE07
CA0681
23
7E
B7
CAC780
7D
E607
FE07
CA0681
23
7E
B7
C20681
80C7
80C8
80C9
80CB
80CE
80D0
80D1
72
E1
3600
3A0680
C601
27
320680
BLNK1:MOV M,C
CALL TM01S
CALL KEYIN2S
CPI 09
JNC BLNK2
DCR A
JM BLNK3
MOV M,D
JMP BLNK0
BLNK2:CPI 15;WRITE INC
JZ CHECK
BLNK3:MOV A,C
MOV C,B
MOV B,A
JMP BLNK1
;check
CHECK:PUSH H;save keyin position
MOV A,L
ANI 07
JZ CHECKR;position=LED1
DCX H
MOV A,M
ORA A
JZ REP;left=space
MOV A,L
ANI 07
JZ CHECKR;left=LED1
DCX H
MOV A,M
ORA A
JZ REP;left of left=space
CHECKR:POP H
PUSH H
MOV A,L
ANI 07
CPI 07
JZ CANT;position=LED8,cannot replace
INX H
MOV A,M
ORA A
JZ REP;right=space
MOV A,L
ANI 07
CPI 07
JZ CANT;right=LED8,cannot replace
INX H
MOV A,M
ORA A
JNZ CANT;right of right is not space,cannot replace
;replace
REP:MOV M,D
POP H
MVI M,00
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
;all check
72
80D4 21F883
80D7 0607
80D9 116981
80DC
80DD
80DE
80E1
1A
BE
C25780
23
80E2 13
80E3 05
80E4 C2DC80
80E7 CD2881
80EA
80ED
80F0
80F3
80F4
80F7
80FA
80FC
210000
22F483
3A0680
67
22F683
CDC001
0614
CD4D81
80FF 05
8100 C2FC80
8103 C30780
8106 E1
8107 C38A80
810A
810B
810C
810F
8110
8111
8113
8114
8117
811A
811B
811C
811E
811F
8122
8125
8126
8127
E5
D5
2A0380
23
7C
E603
67
220380
3A0580
57
7E
E607
BA
CA0C81
320580
D1
E1
C9
8128
812A
812C
812E
060A
3EEF
D398
CD4D81
LXI H,LED1
MVI B,07
;?
LD IX,SEGDT1
LXI D,SEGDT1;
ALCHK1:;LDA IX+00
LDAX D;
CMP M
JNZ KEY;not done
INX H
;?
INC IX
INX D;
;?
DJNZ *ALCHK1
DCR B;
JNZ ALCHK1;
;OK! ALL LED blink
CALL ALBLNK
;COUNTER disp
LXI H,$0000
SHLD DP1
LDA CNTR
MOV H,A
SHLD DP3
CALL DTDPS
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;cannot replace
CANT:POP H
JMP BLNK3
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
73
8131 3EFF
8133 D398
8135 CD4D81
8138 05
8139 C22A81
813C C9
813D
813E
813F
8142
8143
8144
8145
8146
8147
814A
814B
814C
C5
D5
CD1602
D1
C1
C9
C5
D5
CD2302
D1
C1
C9
814D
814E
8150
8153
8154
8157
8158
D5
1E64
CD5981
1D
C25081
D1
C9
8159
815A
815C
815E
815F
8162
8163
8166
8167
D5
1607
1E12
1D
C25E81
15
C25C81
D1
C9
8168
8169
816A
816B
816C
816D
816E
816F
00
06
5B
4F
66
6D
7D
27
ALBLNK
BLNK0
BLNK3
CHECKR
DP3
DTST1
ENTRY
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
POP D
POP B
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,64;=100
TM01S2:CALL TM1M
DCR E
JNZ TM01S2
POP D
RET
;
;1msec timer
TM1M:PUSH D;11
MVI D,07; ck=5 (11+7+292*7+10+10)/2.048=2082/2.048=1016
TM1M2:MVI E,12;=18 ck=7 7+15*18+15=292
TM1M3:DCR E;5
JNZ TM1M3;10
DCR D;5
JNZ TM1M2;10
POP D;10
RET;10
;
SEGDT:DB 00;space
SEGDT1:DB 06;1
DB 5B;2
DB 4F;3
DB 66;4
DB 6D;5
DB 7D;6
DB 27;7
;
=8128 ALBLNK1
=812A ALCHK1
=80DC
=8063 BLNK1
=8071 BLNK2
=8085
=808A CANT
=8106 CHECK
=8090
=80A9 CNTR
=8006 DP1
=83F4
=83F6 DTCLR
=8017 DTDPS
=01C0
=8029 DTST2
=803B DTST3
=8048
=8053 KEY
=8057 KEYIN1
=0216
74
KEYIN1S
LED1
RND2
RNDDT2
START
TM1M
WAIT
=813D
=83F8
=810C
=8005
=8007
=8159
=80FC
KEYIN2
R
RND3
SEGDT
TM01S
TM1M2
=0223
=FFD2
=810A
=8168
=814D
=815C
KEYIN2S
REP
RNDDT
SEGDT1
TM01S2
TM1M3
=8145
=80C7
=8003
=8169
=8150
=815E
75
プログラム№14 MOO(MOO8.BTK)
ゲームの説明
MOOというのは牛の鳴き声(モー)です。別名BULLS & COWSといって昔イギリスではやったゲームだそうです
(「マイコンゲーム21」から。私は知りません)。
コンピュータが乱数を使って4桁の数を隠しています。4桁の数には同じ数は含まれません(5074や3491はありうる
が2335などはない)。
8000番地からRUNするとブーと音がしてLEDが----0000という表示になります。ゲームスタートです。コンピ
ュータが隠している数を想像して4ケタの数を入力します。WRITE INCを押すことで入力が確定します。WRITE INC
を押す前ならば数を入れ直すことができます。
コンピュータは入力された数と隠している数を比較して、同じ数が同じ桁位置にある場合、それを1頭の牡牛(BULL)と
数えます。4桁とも一致したときは牡牛が4頭いることになります。位置は異なるけれど同じ数が含まれている場合、そ
れを牝牛(COW)の数で示します。牡牛は”b”、牝牛は”C”の文字を使ってその頭数が、プーという音とともにLEDの左
4桁に表示されます。全く該当しなかった場合には表示はブランクになります。この表示をヒントにしてできるだけ少ない
回数で正解することを競うゲームです。
テクニックとしてわざと同じ数の並びを入力するなどの方法も考えられますが、ルール違反とした方がよいでしょう(プ
ログラムでチェックはしていません)。
みごと正解するとピーという音がしてLEDの左4桁がbbbbになり、LED全部が2秒間点滅します。そのあと試行回数
が2秒間表示され、また始めに戻って再びゲームが開始されます。
途中でギブアップするときは”F”キーを押します。LEDの左4桁にコンピュータが隠していた数が表示されます。2秒た
つとまた始めに戻って再びゲームが開始されます。
プログラムの説明
4桁の数はBCD数ではなく、4バイトのセグメントデータに変換してデータバッファに格納します。各桁ごとに比較が必
要なのでBCD数では処理に手間がかかります。№13 WILD SEVENと同様、表示にブランク桁が含まれる場合があ
るため、表示する場合には直接セグメントに変換して表示する方が楽です。ちょっと意外な気がしますが、数の大小比較
や計算はしないので、最初からセグメントデータに変換しておいても支障はないのです。 変換はCNVTサブルーチンで
行います。
最初に4桁のデータを作成します(;data set)。1桁目に0が来ると4桁の数になりませんから、そのチェックを行ってい
ます。Lに00を入れてスタートし、RNDで選んだデータが0のときに、Lをチェックしています。DTBFのトップアドレスの
下位アドレスが00であることを利用したテクニックです。DTST4:でデータを格納したあとINC Lをしていますが、本来
不要な処理です。これを追加することによって、L=00であるのはまだ最初の桁にデータがセットされていない(つまり1
桁目の処理)であることが分かります。
牡牛と牝牛のチェック(COMP:)はちょっと複雑です。牡牛からチェックするのがポイントです。先頭の桁から比較して
いって、データが一致したら、LEDに”b”を表示します。このときDTBFのデータのbit7を1にします。次の牝牛のチェッ
クで除外するためのマークです。bit7はLED表示ではピリオドになっていて、このプログラムでのデータでは使わないビ
ットなのでマークとして利用できます。さらにビット7=1のときその数はマイナスの数として扱われるため、Sフラグの有
無で判別が可能です。Cレジスタを牡牛用のダウンカウンタに使います。C=04でスタートしデータが一致するごとに-
1します。C=00になれば4桁とも一致したことになりゲーム終了です。牡牛のチェックが終ったら、牝牛をチェックします。
牡牛の場合と似ていますが、桁の違いを考慮しないため、DTBFの各桁ごとに、LED5~8のデータと照合します。この
ときbit7=1のデータは除外すると同時に、そのマークを取り除きます(bit7=0に戻す)。データが一致するごとにLED
に”C”を表示することは牡牛の処理と同じです。
2016/4/20
END=81E0
12:26
moo8.txt
; MOO for NDZ
; 03/05/06 5/15
;10/6/4 for ND80Z3
;9/17
;16/4/20 for nd8080
;
ORG $8000
;
DTBF=$E800
;
DTBF2=$E802
;
RNDDT=$E810;$E811
LED1=$83F8;$FFF8
LED3=$83FA;$FFFA
76
LED5=$83FC;$FFFC
LED8=$83FF;$FFFF
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
D1=$02DD;4.684msec
;
8000
8003
8004
8005
8006
8007
8008
8009
C30A80
00
00
00
00
00
00
00
800A
800D
8010
8011
8012
8013
8016
8019
3AD2FF
210780
77
23
77
21FFFF
220380
220580
801C 2E00
801E CD2281
8021
8023
8026
8027
802A
802B
802E
8031
8034
8036
8037
803A
803B
803C
803F
FE0A
D21E80
B7
C22E80
BD
CA1E80
CD4081
210380
0604
BE
CA1E80
4E
0C
CA4480
23
8040
8041
8044
8045
05
C33680
77
2C
8046 05
8047 C21E80
804A 210000
804D 22F683
JMP START
DTBF:NOP
NOP
DTBF2:NOP
NOP
RNDDT:NOP
NOP
RNDDT2:NOP
;data set
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
LXI H,$FFFF
SHLD DTBF
SHLD DTBF2
;data set
MVI L,00
DTST1:CALL RND4
;
ANI 0F
CPI 0A
JNC DTST1
ORA A
JNZ DTST2
CMP L
JZ DTST1;first No. is not "0"
DTST2:CALL CNVT
LXI H,DTBF
MVI B,04
DTST3:CMP M
JZ DTST1;already selected No.
MOV C,M
INR C
JZ DTST4;(HL)=FF
INX H
;?
DJNZ *DTST3;B is never 0
DCR B;
JMP DTST3;
DTST4:MOV M,A
INR L;for first No. check
;?
DJNZ *DTST1
DCR B;
JNZ DTST1;
;GAME START
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
77
8050 22F483
8053
8056
8058
805A
CD5E81
3E00
0605
CD9381
805D
805E
8061
8064
8066
8069
806B
806E
8071
8074
8075
8076
8077
05
C25A80
CD7D81
FE15
CA8680
FE0F
CAF480
D26180
11FC83
62
6B
23
010300
807A
807D
8080
8083
CDD481
CD4081
32FF83
C36180
8086
8089
808B
808C
808F
8092
8095
8098
809B
809C
809F
3AF783
C601
27
32F783
210000
22F883
22FA83
21F883
E3
210380
11FC83
80A2
80A5
80A6
80A7
010404
1A
BE
C2B880
80AA
80AB
80AD
80AE
80AF
80B2
80B4
E3
367C
E3
0D
CA0581
F680
77
80B5
80B6
80B7
80B8
80B9
E3
23
E3
23
13
SHLD DP1
;key entry
CALL STDP
MVI A,00;buuuu
MVI B,05
START1:CALL SOUND
;?
DJNZ START1
DCR B;
JNZ START1;
KEY:CALL KEYIN1S
CPI 15;WRITE INC
JZ COMP
CPI 0F;"F"
JZ GIVUP
JNC KEY
LXI D,LED5
MOV H,D
MOV L,E
INX H
LXI B,$0003
;?
LDIR
CALL LDIR;
CALL CNVT
STA LED8
JMP KEY
;DATA compere
;BULL check
COMP:LDA CNTR
ADI 01;DECIMAL COUNTER up
DAA
STA CNTR
LXI H,$0000
SHLD LED1
SHLD LED3
LXI H,LED1;
XTHL;
LXI H,DTBF
LXI D,LED5
;?
LD IX,LED1
LXI B,$0404
COMP1:LDAX D
CMP M
JNZ COMP2
;?
LD (IX+00),7C;b
XTHL;
MVI M,7C;b
XTHL;
DCR C
JZ OK
ORI 80
MOV M,A;B "bull" mark set
;?
INC IX
XTHL;
INX H;
XTHL;
COMP2:INX H
INX D
;?
DJNZ *COMP1
78
80BA 05
80BB C2A580
80BE
80C1
80C3
80C5
80C8
80C9
80CA
80CD
80CF
80D0
80D3
80D4
110380
0604
0E04
21FC83
1A
B7
F2D380
E67F
12
C3E180
BE
C2DC80
80D7 E3
80D8 3639
80DA
80DB
80DC
80DD
80DE
80E1
23
E3
23
0D
C2D380
13
80E2
80E3
80E6
80E8
80EA
05
C2C380
3E0A
0605
CD9381
80ED 05
80EE C2EA80
80F1 C36180
80F4 210380
80F7 11F883
80FA 010400
80FD
8100
8102
8105
8107
8109
CDD481
0628
C31881
3E17
060A
CD9381
810C
810D
8110
8113
8116
8118
05
C20981
CD4981
CDC001
0614
CD8581
811B 05
811C C21881
811F C30A80
DCR B;
JNZ COMP1;
;COW check
LXI D,DTBF
MVI B,04
COMP3:MVI C,04
LXI H,LED5
LDAX D
ORA A
JP COMP4
ANI 7F
STAX D;"bull" mark
JMP COMP6
COMP4:CMP M
JNZ COMP5
;?
LD (IX+00),39;C
XTHL;
MVI M,39;C
;?
INC IX
INX H;
XTHL;
COMP5:INX H
DCR C
JNZ COMP4
COMP6:INX D
;?
DJNZ *COMP3
DCR B;
JNZ COMP3;
MVI A,0A
MVI B,05
COMP8:CALL SOUND
;?
DJNZ *COMP8
DCR B
JNZ COMP8;
JMP KEY
;give up
GIVUP:LXI H,DTBF
LXI D,LED1
LXI B,$0004
;?
LDIR
CALL LDIR;
MVI B,28;=40 ,4sec
JMP WAIT
OK:MVI A,17
MVI B,0A
OK1:CALL SOUND
;?
DJNZ OK1
DCR B;
JNZ OK1;
CALL ALBLNK
CALL DTDPS;COUNTER
MVI B,14;=20 ,2sec
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;
clear
wait
disp
wait
79
8122
8123
8124
8127
8128
8129
812B
812C
812F
8132
8133
8134
8136
8137
813A
813D
813E
813F
E5
D5
2A0780
23
7C
E603
67
220780
3A0980
57
7E
E60F
BA
CA2481
320980
D1
E1
C9
8140
8143
8144
8146
8147
8148
217381
5F
1600
19
7E
C9
8149
814B
814D
814F
8152
8154
8156
060A
3EEF
D398
CD8581
3EFF
D398
CD8581
8159 05
815A C24B81
815D C9
815E 216B81
8161 11F883
8164 010800
8167
816A
816B
816C
816D
816E
816F
8170
8171
8172
CDD481
C9
40
40
40
40
5C
5C
5C
5C
8173 5C
;ransu
RND4:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
ANI 0F
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;from key data to segment data convert
CNVT:LXI H,SEGDT
MOV E,A
MVI D,00
DAD D
MOV A,M
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;start data disp
STDP:LXI H,STDT
LXI D,LED1
LXI B,$0008
;?
LDIR
CALL LDIR;
RET
STDT:DB 40
DB 40
DB 40
DB 40
DB 5C
DB 5C
DB 5C
DB 5C
;
SEGDT:DB 5C;0
80
8174
8175
8176
8177
8178
8179
817A
817B
817C
06
5B
4F
66
6D
7D
27
7F
6F
817D
817E
817F
8182
8183
8184
C5
D5
CD1602
D1
C1
C9
8185
8186
8188
8189
818C
818D
818E
8191
8192
D5
1E15
D5
CDDD02
D1
1D
C28881
D1
C9
8193
8194
8195
8196
8197
819A
819B
819C
819D
819F
81A0
81A2
81A4
81A5
81A6
81A9
81AA
81AC
81AE
81AF
81B0
81B3
81B4
81B7
81B8
81B9
81BA
81BB
F5
E5
D5
C5
21BC81
85
6F
46
1E1A
50
3EFF
D398
7F
15
C2A481
50
3EDF
D398
7F
15
C2AE81
1D
C29F81
C1
D1
E1
F1
C9
DB
DB
DB
DB
DB
DB
DB
DB
DB
06;1
5B;2
4F;3
66;4
6D;5
7D;6
27;7
7F;8
6F;9
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
;
SOUND:PUSH PSW
PUSH H
PUSH D
PUSH B
LXI H,SNDTBL
ADD L
MOV L,A
MOV B,M
MVI E,1A
SNDS1:MOV D,B
MVI A,FF;SP OUT=H
OUT 98
SNDS2:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS2;10---MOV D,B
MVI A,DF;sp out=L
OUT 98
SNDS3:MOV A,A;5--------DCR D;5
| 5+5+10=20
JNZ SNDS3;10---DCR E
JNZ SNDS1
POP B
POP D
POP H
POP PSW
RET
20/2=10microsec
20/2=10microsec
81
81BC
81BD
81BE
81BF
81C0
81C1
81C2
81C3
81C4
81C5
81C6
81C7
81C8
81C9
81CA
81CB
81CC
81CD
81CE
81CF
81D0
81D1
81D2
81D3
7F
77
71
6A
5F
59
54
4F
47
43
3F
3B
35
32
2F
2C
25
27
2A
4B
38
64
23
21
81D4
81D5
81D6
81D7
81D8
81D9
81DA
81DB
81DC
81DF
81E0
F5
7E
12
23
13
0B
78
B1
C2D581
F1
C9
ALBLNK
CNVT
COMP2
COMP5
D1
DTBF
DTST1
DTST4
KEYIN1
LDIR2
LED5
OK1
RND4
SEGDT
SNDS3
START
STDT
WAIT
; SOUND TABLE
SNDTBL:DB 7F;so4
DB 77;so#4
DB 71;ra4
DB 6A;ra#4
DB 5F;do5
DB 59;do#5
DB 54;re5
DB 4F;re#
DB 47;fA5
DB 43;fa#5
DB 3F;so5
DB 3B;so5#
DB 35;ra#5
DB 32;si5
DB 2F;do6
DB 2C;do#6
DB 25;mi6
DB 27;re#6
DB 2A;re6
DB 4B;mi5
DB 38;ra5
DB 64;si4
DB 23;fa6
DB 21;fa#6
;
LDIR:PUSH PSW
LDIR2:MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ LDIR2
POP PSW
RET
;
=8149 ALBLNK1
=8140 COMP
=80B8 COMP3
=80DC COMP6
=02DD DP1
=8003 DTBF2
=801E DTST2
=8044 GIVUP
=0216 KEYIN1S
=81D5 LED1
=83FC LED8
=8109 R
=8122 RNDDT
=8173 SNDS1
=81AE SNDTBL
=800A START1
=816B TM01S
=8118
=814B
=8086
=80C3
=80E1
=83F4
=8005
=802E
=80F4
=817D
=83F8
=83FF
=FFD2
=8007
=819F
=81BC
=805A
=8185
CNTR
COMP1
COMP4
COMP8
DP3
DTDPS
DTST3
KEY
LDIR
LED3
OK
RND2
RNDDT2
SNDS2
SOUND
STDP
TM01S2
=83F7
=80A5
=80D3
=80EA
=83F6
=01C0
=8036
=8061
=81D4
=83FA
=8105
=8124
=8009
=81A4
=8193
=815E
=8188
82
プログラム№15 SWAP2(SWAP28.BTK)
ゲームの説明
№5 SWAPを発展させたものです。SWAPがちょっと単純なので新しく作りました。「マイコンゲーム21」にはありま
せん。
SWAPと違ってLEDは8桁全部を使います。
8000番地からRUNするとLEDに”8”の下半分と”8”の上半分がランダムに並び(それぞれの数も毎回異なる)、そ
れとともにどこかに1桁のブランクが表示されます。
ルールにしたがって表示を移動し、ブランクをはさんで左側に”8”の下半分を集め、右側に”8”の上半分を集めるとゲ
ーム終了です。入れ替えに成功すると2秒間表示が点滅し、さらに2秒間試行回数が表示されたあと、最初に戻って再
びゲームが開始されます。
ルールはSWAPと同じです。ブランクの隣の表示はブランクと位置を交代することができます。また隣に異なる表示が
あるとき、その表示をはさんでさらにその隣がブランクならば、間の表示を飛び越してブランクと表示位置を交代すること
ができます。
入れ替えたいLED位置に対応する数をKEY入力するとその位置のLEDが点滅します。それでよければWRITE INC
キーを押します。WRITE INCキーを押す前なら別の数を入れ直して位置の指定を変更することができます。WRITE I
NCを押すとルールにしたがって表示とブランクが入れ替わります。ルールに合わない場合には点滅が続きますが入れ
替えは行われません。
プログラムの説明
特に説明しなくても理解できると思います。
2016/4/20
END=8173
8000
8003
8004
8005
C30680
00
00
00
8006
8009
800C
800D
800E
800F
8011
8013
8015
8017
3AD2FF
210380
77
23
77
3EEF
D398
3EFF
0608
21F883
13:55
swap28.txt
; SWAP2 for NDZ
; 03/05/03 5/5 5/15
;10/6/4 for ND80Z3
;16/4/20 for nd8080
;
ORG $8000
;
RNDDT=$E810;$E811
LED1=$83F8;$FFF8
DP1=$83F4;$FFF4
DP3=$83F6;$FFF6
CNTR=$83F7;$FFF7;=DP4
R=$FFD2
;
DTDPS=$01C0;$05C0
KEYIN1=$0216;$0616
KEYIN2=$0223;$0623
D1=$02DD;4.684msec
;
JMP START
RNDDT:NOP
NOP
RNDDT2:NOP
;data buffer clear
START:LDA R
LXI H,RNDDT
MOV M,A
INX H
MOV M,A
MVI A,EF
OUT 98
MVI A,FF
MVI B,08
LXI H,LED1
83
801A 77
801B 23
801C 05
801D C21A80
8020 CD2381
8023
8026
8027
8028
21F883
85
6F
3600
802A CD2381
802D
802F
8032
8033
FE06
D22A80
3C
47
8034 CD2381
8037
803A
803B
803C
803D
803E
8041
8042
8045
21F883
85
6F
7E
B7
CA3480
3C
C23480
3663
8047 05
8048 C23480
804B
804E
8050
8051
8052
8055
8056
8059
805B
21F883
0608
7E
B7
CA5B80
3C
C25B80
365C
23
805C 05
805D C25080
8060
8063
8066
8069
806B
210000
22F683
22F483
3EFF
D398
806D
8070
8072
8075
CD5681
FE09
D26D80
3D
DTCLR:MOV M,A
INX H
;?
DJNZ *DTCLR
DCR B;
JNZ DTCLR;
;space position select
CALL RND3
;
ANI 07
LXI H,LED1
ADD L
MOV L,A
MVI M,00
;"UP" No. select
DTST1:CALL RND3
; ANI 07
CPI 06
JNC DTST1
INR A;from 1 to 6 select
MOV B,A
;"UP" data position select
DTST2:CALL RND3
;
ANI 07
LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORA A
JZ DTST2;space position
INR A
JNZ DTST2;already used
MVI M,63;"UP"
;?
DJNZ *DTST2
DCR B;
JNZ DTST2;
;"down" data set
LXI H,LED1
MVI B,08
DTST3:MOV A,M
ORA A
JZ DTST4;space position
INR A
JNZ DTST4;alredy used
MVI M,5C;"DOWN"
DTST4:INX H
;?
DJNZ *DTST3
DCR B;
JNZ DTST3;
;
LXI H,$0000
SHLD DP3;DECIMAL COUNTER clear
SHLD DP1
MVI A,FF
OUT 98
;key entry
KEY:CALL KEYIN1S;1-8 input
CPI 09
JNC KEY
DCR A
84
8076 FA6D80
8079
807C
807D
807E
807F
8080
8083
8084
8085
8087
8088
808B
808E
8090
8093
8094
8097
8098
809B
809D
80A0
80A1
80A2
80A3
21F883
85
6F
7E
B7
CA6D80
57
47
0E00
71
CD6681
CD5E81
FE09
D29B80
3D
FAA080
72
C37980
FE15
CAA680
79
48
47
C38780
80A6
80A7
80A8
80AA
80AD
80AE
80AF
80B0
80B3
80B4
80B7
80B8
80BA
80BD
80BE
80BF
80C0
80C3
80C4
80C5
80C6
80C7
80CA
80CB
80CC
80CD
80D0
80D1
80D4
80D5
80D6
7D
E5
E607
CAC380
2B
7E
B7
CADF80
BA
CAC380
7D
E607
CAC380
2B
7E
B7
CADF80
E1
E5
7D
3C
CA1F81
23
7E
B7
CADF80
BA
CA1F81
7D
3C
CA1F81
JM KEY
;LED blink and wait WINC in
BLNK0:LXI H,LED1
ADD L
MOV L,A
MOV A,M
ORA A
JZ KEY;space position
MOV D,A;LED data save
MOV B,A
MVI C,00
BLNK1:MOV M,C
CALL TM01S
CALL KEYIN2S;1-8,15 input
CPI 09
JNC BLNK2
DCR A
JM BLNK3
MOV M,D
JMP BLNK0
BLNK2:CPI 15;WRITE INC
JZ CHECK
BLNK3:MOV A,C
MOV C,B
MOV B,A
JMP BLNK1
;check
CHECK:MOV A,L
PUSH H;save HL(current position)
ANI 07
JZ CHECKR;current position=LED1
DCX H
MOV A,M
ORA A
JZ REP;left=space
CMP D
JZ CHECKR;left=same
MOV A,L
ANI 07
JZ CHECKR;left=LED1
DCX H
MOV A,M
ORA A
JZ REP;left of left=space
CHECKR:POP H
PUSH H
MOV A,L
INR A
JZ CANT;position=L8,cannot replace
INX H
MOV A,M
ORA A
JZ REP;right=space
CMP D
JZ CANT;right=same,cannot replace
MOV A,L
INR A
JZ CANT;right=L8,cannot replace
85
80D9
80DA
80DB
80DC
23
7E
B7
C21F81
80DF
80E0
80E1
80E3
80E6
80E8
80E9
72
E1
3600
3AF783
C601
27
32F783
80EC
80EF
80F1
80F2
80F4
80F7
21F883
0608
7E
FE5C
C2FC80
23
80F8
80F9
80FC
80FD
8100
8101
8102
8103
8105
8108
05
C2F180
B7
C26D80
23
05
7E
FE63
C26D80
23
8109 05
810A C20281
810D
8110
8113
8115
CD4181
CDC001
0614
CD6681
8118 05
8119 C21581
811C C30680
811F E1
8120 C3A080
8123
8124
8125
8128
8129
812A
812C
812D
8130
8133
8134
E5
D5
2A0380
23
7C
E603
67
220380
3A0580
57
7E
INX H
MOV A,M
ORA A
JNZ CANT;right of right is not space,cannot replace
;replace
REP:MOV M,D
POP H
MVI M,00
LDA CNTR;DECIMAL COUNTER up
ADI 01
DAA
STA CNTR
;all check
LXI H,LED1
MVI B,08
ALCHK1:MOV A,M
CPI 5C;"DOWN"
JNZ ALCHK2
INX H
;?
DJNZ *ALCHK1
DCR B;
JNZ ALCHK1;
ALCHK2:ORA A
JNZ KEY;not success
INX H
DCR B
ALCHK3:MOV A,M
CPI 63;"UP"
JNZ KEY;not success
INX H
;?
DJNZ *ALCHK3
DCR B;
JNZ ALCHK3;
;OK! ALL LED blink and COUNTER disp
CALL ALBLNK
CALL DTDPS
MVI B,14;=20 ,2sec wait
WAIT:CALL TM01S
;?
DJNZ WAIT
DCR B;
JNZ WAIT;
JMP START
;cannot replace
CANT:POP H
JMP BLNK3
;
;ransu
RND3:PUSH H
PUSH D
RND2:LHLD RNDDT
INX H
MOV A,H
ANI 03
MOV H,A
SHLD RNDDT
LDA RNDDT2
MOV D,A
MOV A,M
86
8135
8137
8138
813B
813E
813F
8140
8141
8143
8145
8147
814A
814C
814E
E607
BA
CA2581
320580
D1
E1
C9
060A
3EEF
D398
CD6681
3EFF
D398
CD6681
8151 05
8152 C24381
8155 C9
8156
8157
8158
815B
815C
815D
C5
D5
CD1602
D1
C1
C9
815E
815F
8160
8163
8164
8165
C5
D5
CD2302
D1
C1
C9
8166
8167
8169
816A
816D
816E
816F
8172
8173
D5
1E15
D5
CDDD02
D1
1D
C26981
D1
C9
ALBLNK
ALCHK2
BLNK1
CANT
CNTR
DP3
DTST1
DTST4
KEYIN1S
LED1
RND2
ANI 07
CMP D
JZ RND2
STA RNDDT2
POP D
POP H
RET
;
;LED all blink
ALBLNK:MVI B,0A;=10
ALBLNK1:MVI A,EF
OUT 98
CALL TM01S
MVI A,FF
OUT 98
CALL TM01S
;?
DJNZ *ALBLNK1
DCR B;
JNZ ALBLNK1;
RET
;
;KEYIN with DE,BC save
KEYIN1S:PUSH B
PUSH D
CALL KEYIN1
POP D
POP B
RET
;
KEYIN2S:PUSH B
PUSH D
CALL KEYIN2
POP D
POP B
RET
;
;0.1sec timer
TM01S:PUSH D
MVI E,15;=21
TM01S2:PUSH D
CALL D1;4.684ms
POP D
DCR E
JNZ TM01S2
POP D
RET
;
=8141 ALBLNK1
=8143
=80FC ALCHK3
=8102
=8087 BLNK2
=809B
=811F CHECK
=80A6
=83F7 D1
=02DD
=83F6 DTCLR
=801A
=802A DTST2
=8034
=805B KEY
=806D
=8156 KEYIN2
=0223
=83F8 R
=FFD2
=8125 RND3
=8123
ALCHK1
BLNK0
BLNK3
CHECKR
DP1
DTDPS
DTST3
KEYIN1
KEYIN2S
REP
RNDDT
=80F1
=8079
=80A0
=80C3
=83F4
=01C0
=8050
=0216
=815E
=80DF
=8003
87
RNDDT2
TM01S2
=8005
=8169
START
WAIT
=8006
=8115
TM01S
=8166
88
第2部 電子オルゴール
1. 電子オルゴールプログラム
MUSIC8.BTKは自動演奏プログラムです。
電子オルガンプログラム SOUND8.BTKはキーを押すことでオルガンのように音を出すプログラムですが、MUSIC
8.BTKはオルゴールのように自動演奏をします。
ⅰ)プログラムの使い方
nd8080フォルダにあるMUSIC8.BTKを、ND8080(ND80Zモニタ)に、HIDWR8コマンドで送信してください。
プログラムは8000番地からスタートしますが、その前に演奏データが必要です。
サンプルとして、演奏データファイルが、nd8080フォルダに入っています。
一度に1曲しか送ることはできません。
下記のうちどれかをHIDWR8コマンドでND8080(TK80モニタモード)に送信してください。
KINJIRA.BTK(速さのパラメータ03)
KOKYO.BTK(速さのパラメータ03)
NEKO.BTK(速さのパラメータ03)
SEIJA.BTK(速さのパラメータ02)
SEIYA.BTK(速さのパラメータ04)
YOROKOBI.BTK(速さのパラメータ03)
SUZANNA.BTK(速さのパラメータ01)
ELISE.BTK(速さのパラメータ03)
曲データファイルは8100番地からLOADされます。
8100番地に上書き送信することで、別の曲を演奏させることができます。
曲によっては速さのパラメータ(アドレス8003の値)を書き換える必要があります。プログラムをロードした直後は03
になっています。必要に応じて上の()の値に変更してから、プログラムを実行してください。
プログラムと曲ファイルをLOADしたら、[8][0][0][0][ADRSSET][RUN]と入力すると自動演奏がはじまります。
演奏が終了してもLED表示はアドレス8000を表示したままモニタプログラムに戻りますから、そこでまた[RUN]を押
せば、ふたたび自動演奏がはじまります。
演奏終了後かまたはリセット後に、別の曲ファイルをLOADすると、8100からのメモリエリアが新しい曲データで上書
きされ、別の曲を演奏させることができます。
8000番地からのMUSICプログラムを書き換えてしまわない限りは、自動演奏を繰り返し実行させることができます。
ⅱ)曲データコード
曲データサンプルに限らず、楽譜さえあれば任意の曲データを書いて演奏することができます。データは音の高さのコ
ードと長さのコードで構成されます。最初のデータ(偶数アドレス)が音の高さのデータで、後のデータ(奇数アドレス)は
音の長さのデータです。
休符も高さコードの1種として扱います。コード00を使います。
8100番地から、楽譜を見ながら音符データを書き込んでいくことで、任意の曲を演奏させることができます。
曲の最後(偶数アドレス)にはFFを書きます。
[音の長さデータ]
音符
コード
16分音符
01
8分音符
02
付点8分音符
03
4分音符
04
付点4分音符
06
2分音符
08
付点2分音符
0C
全音符
10
休符は高さコードが00で、長さコードは上の音の長さデータ表と同じコードにします。
たとえば4分休符は、0004になります。
89
[音の高さデータ]
オクターブ
6
6
6
6
6
6
6
6
6
6
6
6
5
5
5
5
5
5
5
5
5
5
5
5
4
4
4
4
4
音階
シ
ラ#
ラ
ソ#
ソ
ファ#
ファ
ミ
レ#
レ
ド#
ド
シ
ラ#
ラ
ソ#
ソ
ファ#
ファ
ミ
レ#
レ
ド#
ド
シ
ラ#
ラ
ソ#
ソ
休符
コード
1D
1C
1B
1A
19
18
17
16
15
14
13
12
11
10
0F
0E
0D
0C
0B
0A
09
08
07
06
05
04
03
02
01
00
周波数(参考)
1760Hz
880Hz
440Hz
ⅲ)曲の速さ
プログラムを簡略にしたため、演奏速度は下の4段階しか選択できません。
4分音符/分
コード
375
01
188
02
94
03
47
04
MUSICプログラムのアドレス8003を書き換えることで、演奏速度を変えることができます。初期値はコード03になって
います。
ⅳ)プログラムの説明
データは2バイトで1組です。前の1バイトが音の高さ、後ろの1バイトが音の長さです。高さのデータはSNDTBLを
参照することで、対応する音の高さの周波数データに変換されます。
長さのデータは40ms×8001番地の値を16分音符の長さとしたとき、その長さに対する各音符の長さ比になります。
たとえば8003番地の値が標準の03のとき、40ms×3=120msですから、このときの4分音符の長さは120ms×4
=480msです。これは1分間では60/0.48=125ですから、1分間に4分音符が125回演奏される速さということ
になります。
SND1:では8100番地からの曲データを順に読みこみ、音の高さデータがFFなら終りの処理を、00なら休符の処理
を行います。その他の場合には音の出力処理を行いますが、その前にCレジスタと比較しています。Cレジスタには1つ
前の音の高さデータが入っています(初期値は?です。手抜きですが問題はありません)。同じ高さの音が続く場合に切
れ目(約5ms)を入れるためです。
90
音の高さデータはテープルを参照することで、周波数を決定するデータになり、Dレジスタに保持されます。
SNDS1:が音を出力する中心部分です。周波数データDはカウンタCに入れられ、スピーカーにHを出力したあとSN
DS2:のループがCレジスタの値だけ繰り返されます。次にスピーカーにLを出力したあと、SNDS3:のループが同じ回
数分繰り返されます。
SNDS2:、SNDS3:のループは1回につき10μsecかかります。
たとえばオクターブ5のラの周波数データはプログラムリストのテーブルデータを見ると、38です。10進数に直すと56
ですから、スピーカーからはH=560μsec、L=560μsecのパルスが出力されることになります。
つまり周期は1120μsecになります。
オクターブ5のラの音の周波数は880Hzですから、その周期は1136μsecです。計算上の周期は本来の周期より
少し短いのですが、データは整数値なので20μsecきざみになることと、ループ以外の部分でも若干の実行時間がか
かることから、本来の周期よりも短い値になるようにしているためです。
音階データテーブルも2バイトで構成され、周波数データと繰り返し回数データがペアになっています。
周波数データは1回の周期を決定し、それで音の高さが決まります。しかし1回の周期は音の高さによって異なり、音
が高ければ短く、低ければ長くなってしまいます。
このままでは音の長さが高さによって異なってきてしまいます。そこで周波数データとペアにした2番目のデータによっ
て、音の高さが異なっていても、一定の期間、音が出力されるようにしてあります。
オクターブ5のラでは、そのデータは23になっています。10進数に直すと35です。このデータは、プログラムではアド
レス8004(REPEAT)に保持され、Eレジスタに入れられてダウンカウントされます。
周期×Eレジスタを計算すると、(1120+10)×35=39550μsecです。
これをオクターブ6のラと比較してみます。
周波数データは1Bなので、10進数の27になります。ですから周期は540μsecです(オクターブ6のラの周波数は1
760Hzですから、本来の周期は568μsecです)。
2番目のデータは47ですから、10進数では71になります。
周期×Eレジスタは、(540+10)×71=39050μsecになります。
高さによって多少の差異はありますが概ね40msecで一定になるようにしてあります。
音符の長さデータは、この40msecの乗数です。Hレジスタに保持され、その値はBレジスタに入れられてダウンカウ
ントされます。
たとえば4分音符の長さデータは04ですから、40×4=160msecの長さになります。
これは1分間では60/0.16=375回演奏される長さです。
実際の音の長さは、さらに速さのパラメータ(アドレス8001の値)が乗じられることで決まります。速さのパラメータはL
レジスタに入れられてダウンカウントされます。
上で計算した音符の長さ時間は、速さのパラメータが01のときのものです。
速さのパラメータが、02、03、04のときの音符の長さ時間は、上で計算した長さの2倍、3倍、4倍になります。
2016/4/29
END=80D5
8000
8003
8004
8005
8006
8009
800C
800D
800E
C30680
03
00
00
210081
3A0580
4F
7E
FEFF
11:25
music8.txt
;;; music 09/10/9 10/10 10/12 10/15
;;;
;16/4/20 for nd8080
;4/29
;
ORG $8000
;
; SPEED=$EFFF
; REPEAT=$EFFE
; MAE=$EFFD
DATA=$8100
END=$0051;MONITOR START
;
JMP START
SPEED:DB 03
REPEAT:NOP
MAE:NOP
START:LXI H,DATA
SND1:LDA MAE
MOV C,A
MOV A,M
CPI FF
91
8010
8013
8014
8017
8019
801C
801D
801E
8021
8022
8023
8024
8025
8026
8029
802A
802B
802D
802E
802F
8030
8031
8034
8035
8036
8037
CA5100
B7
CA6380
FE1E
D27C80
F5
B9
CC8180
23
46
23
F1
E5
219A80
87
5F
1600
19
56
23
5E
3A0380
6F
60
7B
320480
803A
803B
803D
803F
8040
8041
8044
8045
8047
8049
804A
804B
804E
804F
8052
8055
8056
8057
805A
805B
805C
805F
8060
4A
3EFF
D398
7F
0D
C23F80
4A
3EDF
D398
7F
0D
C24980
1D
C23A80
3A0480
5F
05
C23A80
44
2D
C23A80
E1
C30980
8063
8064
8065
8066
8067
806A
806B
23
46
23
E5
3A0380
6F
60
JZ END
ORA A
JZ YASUMI
CPI 1E
JNC ERROR
PUSH PSW
CMP C
CZ T5MS
INX H
MOV B,M;NAGASA
INX H
POP PSW
PUSH H
LXI H,SNDTBL
ADD A
MOV E,A
MVI D,00
DAD D
MOV D,M;TAKASA
INX H
MOV E,M;KURIKAESI KAISU
LDA SPEED
MOV L,A
MOV H,B
MOV A,E
STA REPEAT
;
SNDS1:MOV C,D
MVI A,FF;sp out H
OUT 98
SNDS2:MOV A,A;5
DCR C;5
JNZ SNDS2;10
MOV C,D
MVI A,DF;sp out L
OUT 98
SNDS3:MOV A,A;5
DCR C;5
JNZ SNDS3;10
DCR E
JNZ SNDS1
LDA REPEAT
MOV E,A
DCR B
JNZ SNDS1
MOV B,H
DCR L
JNZ SNDS1
POP H
JMP SND1
;;;
YASUMI:INX H
MOV B,M;NAGASA
INX H
PUSH H
LDA SPEED
MOV L,A
MOV H,B
92
806C
806F
8070
8073
8074
8075
8078
8079
CD8680
05
C26C80
44
2D
C26C80
E1
C30980
807C 23
807D 23
807E C30980
8081 0E05
8083 C38880
8086
8088
808B
808C
808F
0E28
CD9080
0D
C28880
C9
8090
8091
8093
8094
8095
8098
8099
F5
3E60
7F
3D
C29380
F1
C9
809A
809B
809C
809D
809E
809F
80A0
80A1
80A2
80A3
80A4
80A5
80A6
80A7
80A8
80A9
80AA
80AB
80AC
80AD
80AE
80AF
80B0
80B1
80B2
80B3
80B4
00
00
7F
10
77
11
71
12
6A
13
64
14
5F
15
59
16
54
18
4F
19
4B
1A
47
1C
43
1E
3F
YASUMI2:CALL T40MS
DCR B
JNZ YASUMI2
MOV B,H
DCR L
JNZ YASUMI2
POP H
JMP SND1
;;;
ERROR:INX H
INX H
JMP SND1
;
T5MS:MVI C,05
JMP T40MS2
;
T40MS:MVI C,28;=40
T40MS2:CALL T1MS
DCR C
JNZ T40MS2
RET
;
T1MS:PUSH PSW
MVI A,60;=96
T1MS2:MOV A,A;5
DCR A;5
JNZ T1MS2;10
POP PSW
RET
;
; SOUND TABLE
SNDTBL:DB 00;DUMMY
DB 00;DUMMY
DB 7F;so4
DB 10
DB 77;so#4
DB 11
DB 71;ra4
DB 12
DB 6A;ra#4
DB 13
DB 64;si4
DB 14
DB 5F;do5
DB 15
DB 59;do#5
DB 16
DB 54;re5
DB 18
DB 4F;re#5
DB 19
DB 4B;mi5
DB 1A
DB 47;fa5
DB 1C
DB 43;fa#5
DB 1E
DB 3F;so5
93
80B5
80B6
80B7
80B8
80B9
80BA
80BB
80BC
80BD
80BE
80BF
80C0
80C1
80C2
80C3
80C4
80C5
80C6
80C7
80C8
80C9
80CA
80CB
80CC
80CD
80CE
80CF
80D0
80D1
80D2
80D3
80D4
80D5
1F
3B
21
38
23
35
25
32
27
2F
2A
2C
2C
2A
2F
27
32
25
35
23
38
21
3B
1F
3F
1D
43
1B
47
1A
4A
18
50
DATA
MAE
SNDS1
SNDTBL
T1MS
T40MS2
YASUMI2
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
;END
=8100
=8005
=803A
=809A
=8090
=8088
=806C
1F
3B;so#5
21
38;ra5
23
35;ra#5
25
32;si5
27
2F;do6
2A
2C;do#6
2C
2A;re6
2F
27;re#6
32
25;mi6
35
23;fa6
38
21;fa#6
3B
1F;so6
3F;
1D;so#6
43;
1B;ra6
47;
1A;ra#6
4A;
18;si6
50;
END
REPEAT
SNDS2
SPEED
T1MS2
T5MS
=0051
=8004
=803F
=8003
=8093
=8081
ERROR
SND1
SNDS3
START
T40MS
YASUMI
=807C
=8009
=8049
=8006
=8086
=8063
94
2. 電子オルゴールデータ
①プログラムの8003番地を速度のパラメータの値に変更してください。
②プログラムは8000番地から実行します。
禁じられた遊び(KINJIRA.BTK)
速度のパラメータ(8003番地の値)=03
8100 0F 04 0F 04 0F 04 0F 04 0D 04 0B 04
8110 08 04 08 04 0B 04 0F 04 14 04 14 04
8120 12 04 10 04 10 04 0F 04 0D 04 0D 04
8130 0F 04 10 04 0F 04 13 04 10 04 0F 04
8140 0B 04 0B 04 0A 04 08 04 0A 04 0A 04
8150 0B 04 0A 04 08 04 08 04 08 04 08 08
8160 0C 04 0C 04 0C 04 0A 04 08 04 08 04
8170 07 04 06 04 07 04 11 04 11 04 11 04
8180 11 04 11 04 0F 04 0F 04 0F 04 11 04
8190 14 04 14 04 14 04 13 04 12 04 11 04
81A0 11 04 0F 04 0D 04 0C 04 0C 04 0C 04
81B0 0A 04 08 10 FF
故郷の廃家(KOKYO.BTK)
速度のパラメータ(8003番地の値)=03
8100 0D 06 0F 02 0D 04 0A 04 12 06
8110 0D 04 0A 04 12 04 0A 04 08 0C
8120 0D 04 0A 04 12 06 14 02 12 04
8130 0A 06 08 02 06 0C 00 04 08 06
8140 0A 06 09 02 0A 04 0D 04 0F 04
8150 08 0C 00 04 0D 06 0F 02 0D 04
8160 12 04 0F 04 0D 04 0A 04 0A 02
8170 0D 06 09 02 0A 04 0D 0C 00 08
8180 0F 02 0D 08 00 08 0D 06 09 02
8190 12 04 0A 04 0A 02 08 06 06 0C
0B
14
0F
0F
0A
00
07
11
13
11
0C
04
04
04
04
04
04
04
04
04
04
04
0A
14
10
0D
0A
0C
07
13
14
11
0D
04
04
04
04
04
04
04
04
04
04
04
14
00
0F
07
0D
0A
08
0D
0A
FF
02
04
04
02
04
04
06
04
04
02
12
0D
12
08
0B
12
06
08
0D
0F
04
06
04
04
04
06
0C
04
0C
02
0F
0F
0A
0B
0A
14
00
11
00
0D
04
02
04
04
04
02
04
06
08
02
ねこふんじゃった(NEKO.BTK)
速度のパラメータ(8003番地の値)=03
8100 0F 02 0D 02 06 02 00 02 12 02 00
8110 0F 02 0D 02 06 02 00 02 12 02 00
8120 0F 02 0D 02 06 02 00 02 12 02 00
8130 12 02 00 02 01 04 11 02 00 02 11
8140 0D 02 01 02 00 02 11 02 00 02 11
8150 0D 02 01 02 00 02 11 02 00 02 11
8160 0D 02 01 02 00 02 11 02 00 02 03
8170 00 02 06 02 00 02 12 02 00 02 12
8180 16 02 00 02 12 02 00 02 12 02 00
8190 16 02 00 02 12 02 00 02 12 02 00
81A0 16 02 00 02 12 02 00 02 19 02 00
81B0 1B 04 11 02 00 02 11 02 00 02 0F
81C0 00 02 11 02 00 02 11 02 00 02 0F
81D0 00 02 11 02 00 02 11 02 00 02 0F
81E0 00 02 11 02 00 02 19 02 00 02 11
81F0 12 02 00 02 12 02 00 02 0F 02 0D
8200 12 02 00 02 01 02 00 02 12 02 00
8210 12 02 00 02 01 02 00 02 12 02 00
8220 06 04 07 04 08 04 11 02 00 02 11
8230 0D 02 08 02 00 02 11 02 00 02 01
8240 00 02 08 02 00 02 11 02 00 02 01
8250 00 02 08 04 07 04 08 04 09 04 0A
02
02
02
02
02
02
02
04
02
02
02
02
02
02
02
02
02
02
02
02
02
04
12
12
03
00
00
00
00
0F
0F
0F
12
0D
0D
0D
00
06
06
06
00
00
00
16
02
02
02
02
02
02
02
02
02
02
02
02
02
02
02
02
02
04
02
02
02
02
00
00
00
0F
0F
0F
11
0D
0D
0D
00
1B
1B
1B
16
00
00
05
0F
11
11
00
02
02
02
02
02
02
02
02
02
02
02
02
02
02
04
02
02
04
02
02
02
02
95
8260
8270
8280
8290
82A0
82B0
82C0
82D0
82E0
82F0
16
12
12
03
00
00
00
00
0D
FF
02
02
02
02
02
02
02
02
02
00
00
00
00
0F
0F
0F
11
0C
02
02
02
02
02
02
02
02
02
0F
0F
0F
12
0D
0D
0D
00
0D
02
02
02
02
02
02
02
02
02
0D
0D
0D
00
01
01
01
12
0E
02
02
02
02
02
02
02
02
02
06
06
06
01
00
00
00
00
0F
02
02
02
04
02
02
02
02
02
00
00
00
11
11
11
11
12
10
02
02
02
02
02
02
02
02
02
12
12
12
00
00
00
00
00
11
02
02
02
02
02
02
02
02
02
00
00
00
11
11
11
03
12
12
02
02
02
02
02
02
02
04
04
聖者の行進(SEIJA.BTK)
速度のパラメータ(8003番地の値)=02
8100 0B 04 0F 04 10 04 12 10 00 06
8110 12 10 00 06 0B 02 0F 04 10 04
8120 0F 08 0D 10 00 08 0F 04 0D 04
8130 12 04 12 04 12 04 10 0C 00 06
8140 12 08 0F 08 0B 08 0D 08 0B 10
0B
12
0B
0B
FF
02
08
0C
02
0F
0F
0B
0F
04
08
04
04
10
0B
0F
10
04
08
08
04
聖夜(SEIYA.BTK)
速度のパラメータ(8003番地の値)=04
8100 0D 06 0F 02 0D 04 0A 0C 0D 06
8110 14 08 14 04 11 0C 12 08 12 04
8120 12 06 11 02 0F 04 0D 06 0F 02
8130 0F 04 12 06 11 02 0F 04 0D 06
8140 14 08 14 04 17 06 14 02 11 04
8150 0D 02 0A 04 0D 06 0B 02 08 04
0F
0D
0D
0F
12
06
02
0C
04
02
0C
0C
0D
0F
0A
0D
16
FF
04
08
0C
04
0C
0A
0F
0F
0A
12
0C
04
08
0C
06
04
08
04
04
04
04
04
12
14
10
12
12
14
10
04
04
04
04
04
08
04
08
18
08
04
0C
04
04
10
18
08
0A
06
06
08
08
0A
0A
0F
06
06
08
04
0C
04
04
08
08
08
04
0C
よろこびのうた(YOROKOBI.BTK)
速度のパラメータ(8003番地の値)=03
8100 14 04 14 04 15 04 17 04 17 04 15 04 14
8110 10 04 10 04 12 04 14 04 14 06 12 02 12
8120 14 04 15 04 17 04 17 04 15 04 14 04 12
8130 10 04 12 04 14 04 12 06 10 02 10 08 12
8140 14 04 10 04 12 04 14 02 15 02 14 04 10
8150 14 02 15 02 14 04 12 04 10 04 12 04 0B
8160 14 04 15 04 17 04 17 04 15 04 14 04 12
8170 10 04 12 04 14 04 12 06 10 02 10 08 FF
おおスザンナ(SUZANNA.BTK)
速度のパラメータ(8003番地の値)=01
8100 06 04 08 04 0A 08 0D 08 0D 08 0F
8110 06 0C 08 04 0A 08 0A 08 08 08 06
8120 08 04 0A 08 0D 08 0D 0C 0F 04 0D
8130 08 04 0A 08 0A 08 08 08 08 08 06
8140 0A 08 0D 08 0D 08 0F 08 0D 08 0A
8150 0A 08 0A 08 08 08 06 08 08 18 06
8160 0D 08 0D 08 0F 08 0D 08 0A 08 06
8170 0A 08 08 08 08 08 06 18 00 08 0B
8180 0F 10 0F 08 0D 08 0D 08 0A 08 06
8190 08 04 0A 08 0D 08 0D 08 0F 08 0D
81A0 08 04 0A 08 0A 08 08 08 08 08 06
08
08
08
18
08
04
0C
10
08
08
10
0D
08
0A
06
06
08
08
0B
08
0A
FF
エリーゼのために(ELISE.BTK)
速度のパラメータ(8003番地の値)=02
8100 16 04 15 04 16 04 15 04 16 04 11 04 14 04 12 04
8110 0F 08 00 04 06 04 0A 04 0F 04 11 08 00 04 0A 04
8120 0E 04 11 04 12 08 00 04 0A 04 16 04 15 04 16 04
96
8130
8140
8150
8160
8170
8180
8190
81A0
81B0
81C0
15
0A
00
14
11
14
00
15
00
11
04
04
04
0C
04
04
04
04
04
04
16
0F
11
0B
00
12
0A
16
06
7A
04
04
04
04
04
04
04
04
04
00
11
11
12
16
16
0F
0E
15
0A
0F
04
08
04
04
04
08
04
04
04
08
14
00
14
14
15
00
11
16
0F
FF
04
04
04
04
04
04
04
04
04
12
0A
16
12
16
06
12
11
11
04
04
0C
0C
04
04
08
04
08
0F
12
0D
0A
15
0A
00
14
00
08
04
04
04
04
04
04
04
04
00
11
17
14
16
0F
0A
12
0A
04
04
04
04
04
04
04
04
04
06
0F
16
12
11
11
16
0F
12
97
04
08
04
04
04
08
04
08
04
[memo]
98