SSブログ
English Version

3チップ構成Pic24CPMマイコン(その7)GAMEコンパイラ [Z80]

 ネットで久々にGAME言語ネタを見つけた^^ので平成最後のカキコはGAME言語ネタです。
 Old68funさんが6809 / 6800とFLEXのブログで書かれている「SBC8080でGAME80がようやく動作」の記事です。TK-80BS用のGAME80インタプリタをSBC8080上で動かされています。

 TK-80BSと言えば中島さんにより開発されたGAME80コンパイラが発表された環境であり、Jun's Homepageの「GAME80コンパイラ解説 (2003/08/05)」に解説とともにソースが掲載されています。

 久々にGAMEコンパイラを動かしてみたいものですねぇ^^

 最初にGAME80をCP/M-80に移植してみました。GAMEインタプリタ自体はコンソール入出力関連の処理をハード環境に合わせて変更すれば動作するのでCP/M-80用に先頭にコールドスタートへのジャンプ命令を追加し、末尾にコンソール関連の処理を追加しました。使用した環境はマイクロソフトのMACRO80/LINK80です。
 全体をリロケートしなかったのは上記のコンパイラを動かしてみたかったからです。

GAMEインタプリタのCP/M-80へのインプリメント
;******************************** ; GAME interpreter ; TK-80BS version on CP/M-80 ; 2019/05/01 ;******************************** 8600 PRGST EQU 8600H ; program start addres CBFF RAMEND EQU 0CBFFH ; for CP/M-80 64K 001B K_STOP EQU 01BH ; stop key 0020 K_PAUSE EQU ' ' ; pause key 8E00 SRCSTA EQU 08E00H ; sorce start addres 8DC4 STACK2 EQU 08DC4H ; second stack 8D42 Y8D42 EQU 08D42H 8D46 Y8D46 EQU 08D46H 8D4A Y8D4A EQU 08D4AH 8D4B Y8D4B EQU 08D4BH 8D4E Y8D4E EQU 08D4EH 8D50 Y8D50 EQU 08D50H 8D52 Y8D52 EQU 08D52H 8D58 Y8D58 EQU 08D58H 8D5A Y8D5A EQU 08D5AH 8D68 Y8D68 EQU 08D68H 8D6A Y8D6A EQU 08D6AH 8D70 Y8D70 EQU 08D70H 8D72 Y8D72 EQU 08D72H 8D74 Y8D74 EQU 08D74H 8D76 Y8D76 EQU 08D76H 8D77 Y8D77 EQU 08D77H 8D7E Y8D7E EQU 08D7EH 8D88 Y8D88 EQU 08D88H 8D8A Y8D8A EQU 08D8AH .Z80 0000' ASEG ORG 00100H 0100 C3 8600 JP START ORG PRGST 8600 C3 8606 START: JP A8606 ; cold start 8603 C3 8611 JP A8611 ; hot start ; 8606 21 8E00 A8606: LD HL,SRCSTA 8609 22 8D7E LD (Y8D7E),HL 860C 22 8D50 LD (Y8D50),HL 860F 36 FF LD (HL),0FFH 8611 21 CBFF A8611: LD HL,RAMEND 8614 22 8D58 LD (Y8D58),HL   ~~~ 途中省略 ~~~ 8C7B C2 8C4E JP NZ,A8C4E 8C7E 36 00 LD (HL),000H 8C80 21 8D8A LD HL,Y8D8A 8C83 3E 0D A8C83: LD A,00DH 8C85 CD 8C99 CALL PUTCH 8C88 3E 0A LD A,00AH 8C8A C3 8C99 JP PUTCH ; 8C8D 0D 0A 2A 52 T8C8D: DB 0DH,0AH,'*READY',00H 8C91 45 41 44 59 8C95 00 ;*** added by skyriver 2019/04/30 *** 8C96 CD 8CA7 GETCH: CALL CONIN 8C99 C3 8CB1 PUTCH: JP CONOUT 8C9C E5 KBHIT: PUSH HL 8C9D D5 PUSH DE 8C9E 1E 03 LD E,03H ; CONST 8CA0 CD 8CBE CALL GOBIOS 8CA3 0F RRCA ; if exist then set carry 8CA4 D1 POP DE 8CA5 E1 POP HL 8CA6 C9 RET 8CA7 E5 CONIN: PUSH HL 8CA8 D5 PUSH DE 8CA9 1E 06 LD E,06H ; CONIN 8CAB CD 8CBE CALL GOBIOS 8CAE D1 POP DE 8CAF E1 POP HL 8CB0 C9 RET 8CB1 E5 CONOUT: PUSH HL 8CB2 D5 PUSH DE 8CB3 F5 PUSH AF 8CB4 1E 09 LD E,09H ; CONOUT 8CB6 4F LD C,A 8CB7 CD 8CBE CALL GOBIOS 8CBA F1 POP AF 8CBB D1 POP DE 8CBC E1 POP HL 8CBD C9 RET 8CBE 2A 0001 GOBIOS: LD HL,(0001H) ;WBOOT addres 8CC1 16 00 LD D,0 8CC3 19 ADD HL,DE 8CC4 E9 JP (HL) END

★2019/04/30 変更
 連続表示中にスペースでポーズできなかったので修正
 オリジナルは'!'キーで中断ですが、ESCで中断するように変更
★2019/05/01 変更
 コール先やワークのアドレスをラベル名に変更


 GAME80インタプリタがCP/M-80上で動いたので上記のGAME80コンパイラの解説ブログページからコンパイラのソースを頂いて動かしてみます。
 ブログにも「リストは昔に記事を読んで打ち込んだもので、実行して確認していません。ミスがあるかもしれませんが、その場合はご容赦下さい。」と書かれているように実際に動かそうとすると数ヶ所修正が必要です(手元にエンサイクロペディアアスキーの該当ページのコピーがあったので突合チェックした)。
 オリジナルとの差分を以下にメモしておきます。

No.修正箇所
1 225 ?(5)=V .=5 ??=A .=5 ??=G /
2 3270 ;=H="+" #=3300
3 3410 ;=G:0)="=" G=G+1 !=4000 H=$FA #=3600
4 5620 A:0)=$CD A=A+3 A(-1)=A A:0)=$D5 A=A+1


 これで何十年かぶりにGAMEコンパイラのコンパイルぶりを見れる(私が当時動かしていたのはTRS-80用のGAME-Z80を自作マイコンに移植したものだったのでTK-80BSのGAMEは初体験)と思いきやコンパイルしたコードが全く動きません・・・
 コンパイラのソースを確認したところ、文字列出力部で$FA52をコールしているコードを生成しています。
 そこで1文字出力ルーチンを使ったループ処理のコードを生成するように変更し、機種依存性を無くしました。

オリジナル 2410 @=(G:I-1)=""") A(0)=A+I
2420 G=G+I A=A+I A:0)=$3E
2430 A:1)=I-2 A:2)=$32 A=A+5 A(-1)=$847A
2440 A:0)=$21 A=A+3 A(-1)=Q
2445 A:0)=$22 A=A+3 A(-1)=$847B
2450 A:0)=$CD A=A+3 A(-1)=$FA52
2460 #=700
変更後 2410 @=(G:I-1)=""") A(0)=A+I
2420 G=G+I A=A+I A:0)=$06
2430 A:1)=I-2 A:2)=$21 A=A+3
2432 A(0)=Q A(1)=$CD7E A(2)=$8C99
2433 A(3)=$0523 A=A+11 A:-3)=$C2 A(-1)=A-9
2460 #=700


 ソースを見ると生成するコードが何となく判ると思いますが、文字列生成処理のコンパイル結果を確認してみます。
 サンプルソースとしては単に"Hello"と出力するだけのものを使用しました。

文字列出力処理のコンパイル例
:0 10 "Hello" *READY :=$8E00 *READY :#=1 GAME PROGRAM FROM:$B000 START ADRRESS:$4000 WORK AREA FROM:$100 10 4000 B000 10 4000 B000 PROGRAM SIZE: 25(4000-4018) END *READY :>=0 b>


 0x4000以降にコンパイルされたコードが書かれているので、一旦GAMEを抜けてCP/Mのディバッガ(ZSID)を起動し、確認しました。
 ZSIDDはZSIDに小文字シンボル対応や1行ダンプ等のパッチをあてたものです。

生成されたコード
b>a:zsidd ZSID VERS 1.4 #l4000,4018 4000 JP 4008 4003 LD C,B 4004 LD H,L 4005 LD L,H 4006 LD L,H 4007 LD L,A 4008 LD B,05 400A LD HL,4003 400D LD A,(HL) 400E CALL 8C99 4011 INC HL 4012 DEC B 4013 JP NZ,400D 4016 JP 8603 4019 #d4000 4000: C3 08 40 48 65 6C 6C 6F 06 05 21 03 40 7E CD 99 ..@Hello..!.@~.. 4010: 8C 23 05 C2 0D 40 C3 03 86 00 00 00 00 00 00 00 .#...@.......... 4020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 40A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ #


 想定通りのコードが生成されていますね。当然実行結果もokでした。
 当初の目的であるGAMEコンパイラをインタプリタ動作でコンパイラ自身をコンパイルし、コンパイルされたコンパイラで更にコンパイラをコンパイルすることも問題なくできました(^^)/

 GAME言語のインタプリタやコンパイラのソースを公開していいか判らないのでCP/M-80に移植したバイナリだけ置いておきます。
 冒頭で紹介したブログと本ブログを参照すれば、CP/M環境でGAMEコンパイラのセルフコンパイル(通常とは違う意味での「セルフ」)まで試せると思います。

  • GameOnCpm80_20231130_005d.zip
    ★2023/11/30 Ver 0.05d
     filesコマンド(¥¥)の表示を改善
    ★2023/11/29 Ver 0.05c
     files(¥¥)命令を追加(ワイルドカード対応)
    ★2023/11/29 Ver 0.05b
     files(¥¥)命令を追加
    ★2023/11/04 Ver 0.05a
     エラーの表示の改善とBIOSコール部の若干の高速化
    ★2023/11/02 Ver 0.05
     save(¥>FileName)とload(¥<FileName)コマンドをインプリメント
    ★2023/11/01 Ver 0.04a
     キーセンス部分の間引き処理廃止
    ★2023/10/30 Ver 0.04
     キーセンス部分で実際のキーセンスを8回に1回コールすることで若干高速化
     起動時にアーギュメントを付けてるとホットスタート起動するように変更
    ★2019/05/18 Ver0.03
     コンパイル時の表示をGAME-Z80版のように見易くした
    ★2019/05/09 Ver0.02
     スペースキーでのポーズ及びESCでのブレーク時にエコーバックしないようにした
    ★2019/05/06 Ver0.01
     コンパイラを0200H~に包括した( >=$200 でコンパイラ起動)
     版数特定ができるようにVer付きオープニングメッセージを表示するようにした
    ★2019/05/04
     起動時にGAME本体を8600Hへ転送するようにして起動時間短縮
    ★2019/05/01
     コンソール関連処理を2バイト軽量化しました(機能的には変わらず)


★2019/04/30 追記
 twitterにポストした動画付きコメントを貼り付けておきます。


★2019/05/02 追記
 コメントに書いたように文字列出力処理部のコンパイルでインタプリタ内の'\0'で終端された文字列の出力処理である0x8785を呼び出すようにして生成コードを短縮し、更にキーチェックだけを行う長さゼロの文字列出力 "" に対応してみました。

 GAMEコンパイラの修正箇所は下記になります。ソース自体も短くなりました。

オリジナル 2300 A:0)=$C3 A=A+1 I=2
2400 Q=A+2 @ A:I)=G:I-1) I=I+1
2410 @=(G:I-1)=""") A(0)=A+I
2420 G=G+I A=A+I A:0)=$3E
2430 A:1)=I-2 A:2)=$32 A=A+5 A(-1)=$847A
2440 A:0)=$21 A=A+3 A(-1)=Q
2445 A:0)=$22 A=A+3 A(-1)=$847B
2450 A:0)=$CD A=A+3 A(-1)=$FA52
2460 #=700
変更後 2300 A:0)=$C3 Q=A+1 A=A+2
2400 @ G=G+1 A=A+1 A:0)=G:0) @=(G:0)=""")
2410 G=G+1 A(0)=$2100 A(1)=Q+2 Q(0)=A+1
2420 A=A+7 A:-3)=$CD A(-1)=$8785
2460 #=700


 それではコンパイル結果を確認してみます。

コンパイル結果確認
*READY :=$B000 *READY :&=0 *READY :10 "Hello" :20 "" :0 10 "Hello" 20 "" *READY :=$8E00 *READY :#=1 GAME PROGRAM FROM:$B000 START ADRRESS:$4000 WORK AREA FROM:$100 10 4000 B000 20 400F B00B 10 4000 B000 20 400F B00B PROGRAM SIZE: 28(4000-401B) END *READY :>=$4000 Hello *READY :>=0 b>a:zsidd ZSID VERS 1.4 #l4000,401b 4000 JP 4009 4003 LD C,B 4004 LD H,L 4005 LD L,H 4006 LD L,H 4007 LD L,A 4008 NOP 4009 LD HL,4003 400C CALL 8785 400F JP 4013 4012 NOP 4013 LD HL,4012 4016 CALL 8785 4019 JP 8603 401C #d4000,401f 4000: C3 09 40 48 65 6C 6C 6F 00 21 03 40 CD 85 87 C3 ..@Hello.!.@.... 4010: 13 40 00 21 12 40 CD 85 87 C3 03 86 00 00 00 00 .@.!.@.......... #g0 b>


 想定通りですね^^
 GAMEコンパイラはコンパイラ自身をコンパイルし、拡張していけるのでマイコン環境でC言語等の開発環境が無かった時代にブートストラップ方式で言語仕様を拡張することでいくつかのコンパイラが作られました。独自言語が色々出てきて楽しい時代でしたね。


★2019/05/03 追記
 インタープリタ ⇒ インタプリタ に変更


★2019/05/03 追記
 CP/MでGAME言語が動くようになったので以前、「PIC24FJ64GAでGAME言語(その5)」で記載した迷路生成/探索のプログラムを動かしてみました。

GAME80ではPIC24FJ版GAMEとの相違点として
  • &(AND)演算子が無い
  • 配列のインデックス部で計算ができない配列が参照できない※1
  • 乱数 'N の範囲が0~N-1ではなく、1~Nである
  • タイマ管理変数の '¥' が無い

等がありましたが容易に移植できました。
★2019/05/03 追記
※1 インデックス部で計算はできるようです。下記の事象が発生しました。
W=B:P+D(Z)) ⇒ NG
C=D(Z) W=B:P+C) ⇒ OK
★2019/05/09 追記 {配列値評価時に8D70HにHLレジスタを保存しているため}

 ソースを以下に貼りました。TeraTermのWindowサイズは80カラム×32行で動かしてください(と言ってもTeraTerm接続で動くCP/M-80環境を持っている人は希少だとは思いますが)。

Maze for GAME80
1' Maze for GAME80 2019/05/03 by skyriver 2 S=78 T=30 #=100 8' move cursor 9 Y=P/S X=%(0) 10 $=$1B "[" ?=Y+1 ";" ?=X+1 "H" ] 18' set wall 19 Y=P/S X=%(0) 20 B:Y*S+X)=8 ] 29' wait 30 C=1,100 "" @=C+1 ] 100 D=&+1 B=D+8 '=157 102 D(0)=1 D(1)=S D(2)=-1 D(3)=-S U=S*T-1 110 @ 119' create maze 120 I=S*T @ I=I-1 B:I)=0 @=(I=0) 130 Y=0,T 140 X=0 !=20 150 @=Y+1 160 X=0,S 170 Y=0 !=20 Y=T !=20 180 @=X+1 190 G=2,T-2 200 F=2,S-2 210 X=F Y=G !=20 P=S*G+F 220 @ R=P+D('(4-(G>2))-1) @=(B:R)=0) 230 P=R !=19 240 @=F+2 250 @=G+2 259' display maze 260 $=$1B "[2J" X=0 Y=0 !=10 $=$1B "[36m" 270 Y=0,T 280 X=0,S 290 Z=" " ;=B:Y*S+X) Z="#" 300 $=Z 310 @=X+1 320 / 330 @=Y+1 340 $=$1B "[m" 350 X=S-1 Y=T-1 !=10 $="@" 360 !=30 369' explore 370 P=S+1 Z=0 380 @ 390 !=9 "+" $=8 Z=%((Z+2)/4) 400 @ "" 410 Z=%((Z+1)/4) R=P+D(Z) 420 @=(B:R)<8) 430 P=R B:P)=B:P)+1 440 !=30 450 @=(P=U) 459' best route 460 $=$1B "[43m" P=S+1 470 @ 480 !=9 "+" $=8 490 N=0 E=8 500 Z=0,3 510 C=P+D(Z) W=B:C) 520 ;=(W>0)*(W<E) E=W N=Z 530 @=Z+1 540 B:P)=7 P=P+D(N) 550 !=30 560 @=(P=U) 570 $=$1B "[m" 580 @=(0)


 参考にtwitterにポストした動画付きコメントを貼ります。


★2019/05/10 追記
 GAME80のソースのリナンバプログラムを作ったので貼っておきます。
 GAME68等でも動作すると思います。

renumber for GAME80
1' renumber for GAME Ver0.03a 2020/12/01 by skyriver 2 "src address " S=? 3 "dst address " D=? 4 "line start " B=? 5 "line step " E=? 6 Z=&+1 TBL=Z+6 7 P=S IDX=0 C=D 8 @ 9 TBL(IDX)=P:0)*256+P:1) IDX=IDX+1 ;=%(IDX/10)=0 "*" 10 P=P+2 @ P=P+1 @=(P:-1)=0) 11 @=(P:0)>=$F0) 12 P=S IDX=0 13 @ 14 NEW=E*IDX+B 15 D:0)=NEW/256 D:1)=NEW D=D+2 P=P+2 16 / ?(5)=TBL(IDX) " :" ?(5)=NEW 17 ;=P:0)<>" " @ D:0)=P:0) D=D+1 P=P+1 @=(P:0)=0) 18 @ 19 ;=(P:0)=""")*(P:1)=""")*(P:2)=""") D:0)=""" D=D+1 P=P+1 20 ;=(P:0)=""") @ D:0)=P:0) D=D+1 P=P+1 @=(P:0)=""") 21 ;=(P:0)="#")+(P:0)="!") !=31 22 D:0)=P:0) 23 D=D+1 P=P+1 24 @=(P:-1)=0) 25 IDX=IDX+1 26 @=(P:0)>=$F0) 27 D:0)=P:0) 28 /"Renumbered(" ??=C "-" ??=D ")" 29 #=-1 30' goto,gosub 31 ;=(P:1)<>"=")+(P:2)="-") ] 32 D:0)=P:0) D:1)="=" D=D+2 P=P+2 33 LINE=0 @ LINE=LINE*10+(P:0)-"0") P=P+1 @=((P:0)<"0")+(P:0)>"9")) 34 " " $=D:-2) "=" ?=LINE " -> " 35 F=-1 @ F=F+1 @=(TBL(F)>=LINE) 36 LINE=E*F+B X=Z-1 ?=LINE 37 @ X=X+1 LINE=LINE/10 X:0)=%(0)+"0" @=(LINE=0) 38 @ D:0)=X:0) D=D+1 X=X-1 @=(X<Z) 39 ]

★2020/12/01 追記
 Ver 0.03a リナンバー後のプログラム範囲の表示を追加
★2019/05/11 追記
 Ver 0.03 """処理部簡略化
 Ver 0.02 行短縮しました

★2019/12/01 追記
 MSX-DOSでCP/M-80のコマンドを実行できることからWebMSX環境で動作させたMSX-DOS上でGAMECを動かしてみた。
 Twitterにアップしたコメントを貼っておきます。



★2019/12/03 追記
 上のTwitterではWebMSXでコピペができないと書いてしまいましたが、ALT+V の操作でコピペできました^^
 なんとWebSMXの作者であるPaulo PeccinさんからTwitterで教えて頂きました。

★2020/01/05 追記
 「MSX-DOS上でのGAME言語のベンチマーク」の記事にWebMSX上で動かしたMSX-DOSでのGAME言語(インタプリタ&コンパイラ)やBASIC等のベンチマーク計測結果を記載しました。

★2020/01/16 追記
 ポケコン(PC-G850V)にGAMEコンパイラを移植しました。
ポケコン(PC-G850V)でGAME言語(その3)GAMEコンパイラ
 twitterにポストしたメッセージも貼っておきます。



★2020/05/03 追記
 エミュレータ環境を使ってパピコン(PC-6001)にGAMEインタプリタとコンパイラを移植しました。
 「パピコン(PC-6001)でGAME言語(その2)GAMEコンパイラ
Twitterのメッセージも貼っておきます。




★2020/08/08 追記
 GAMEコンパイラの開発者である中島さんがコンパイラのソースをgithubで公開!!





[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(2)  コメント(15) 
共通テーマ:趣味・カルチャー