スキップしてメイン コンテンツに移動

GAME-CC

5月5日の「GAME09」で一部紹介した、
ttps://www.zukeran.org/shin/d/2024/06/04/bm-development-environment-8/
「ず」さんのブログを見ていたら、6800用のGAME68関連のアーカイブにGAME言語のソースをアセンブラのソースの形で出すコンパイラが紹介されていたので、ダウンロードして6809用に書換えてみた。

ここに、一応 使い物になる程度の形になったので公開しょうと思う。


GAME-CC0_0531.zip 4shared.comのリンクなので気になる方はご遠慮ください。

先に、着手していたGAME09の方は、インテルHEX形式でのシリアル転送のルーチン部分が目処がたったので、GAME09インタプリタ内に内包させるすり合わせ作業中。

GAME-CC0は、それ以外にasm6809を使っていますのでa09などの他のアセンブラを使用の場合は、適宜makefileの修正を行ってください。

 以下はGAME-CCオリジナルからの改変作業過程の作業メモです。何をどうイジったかの参考にでも どうぞ。

makefile
 11から17行、gameオブジェクト生成ルール コメントアウト
common.hの構造体宣言をmain.cに移動
 print_string_t    STRING_FCC[10000];
 opt_do_loop_t    odl[1000];
 opt_for_loop_t    ofl[1000];
 Node    *code[10000];
 Token    *token;
シリアル端末専用のSBC6809用のため 不要なBM-L2専用の音楽、タイマー、カーソル制御関係の機能をコメントアウト

ここまでやると、linuxのgccでコンパイルが通る。
この時点で判るバグは、'=nn のRNDシード設定が何もコードを吐き出さない。
論理否定notが使えない。
文字列と改行のみのプリント文の行でエラーになる。

手持ちのアセンブラが「.」(ピリオド)「_」(アンダーバー)で始まるラベルをエラーとするので、「.」「_」で始まるラベルを生成する部分を修正。

parse.c内のToken *tokenize()関数の中にある、変数名判別部がアルファベットの大文字しか受け付けてないので
ソース上で小文字のアルファベットであっても内部処理で大文字に置き換えるように修正

        }else if ((('A'<=*p) && (*p<='Z')) || (('a'<=*p) && (*p<='z'))){
//            printf(";tokenize TK_LVAR '%c',p='%s'\n",*p,get_least_line(p));
            p[0]=*p & 0xdf;

grep -nHIF -- .L (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:574:    sprintf(label,".LN%d",(v>=0)?v:65536);
codegen.c:584:    sprintf(label,".LL%d",labelnum++);
codegen.c:593:    sprintf(label,".LD%d",v);
codegen.c:601:    sprintf(label,".LF%d",v);

「.L」を「L_L」に変更

grep -nHIF --     RMB (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:2032:void    RMB_comment(char *label,int size,char *comment)
codegen.c:2036:void    RMB(char *label,int size)
codegen.c:4409:    RMB("_RETSP",2);
codegen.c:4411:    RMB("_A",2);
codegen.c:4412:    RMB("_B",2);
codegen.c:4413:    RMB("_C",2);
codegen.c:4414:    RMB("_D",2);
codegen.c:4415:    RMB("_E",2);
codegen.c:4416:    RMB("_F",2);
codegen.c:4417:    RMB("_G",2);
codegen.c:4418:    RMB("_H",2);
codegen.c:4419:    RMB("_I",2);
codegen.c:4420:    RMB("_J",2);
codegen.c:4421:    RMB("_K",2);
codegen.c:4422:    RMB("_L",2);
codegen.c:4423:    RMB("_M",2);
codegen.c:4424:    RMB("_N",2);
codegen.c:4425:    RMB("_O",2);
codegen.c:4426:    RMB("_P",2);
codegen.c:4427:    RMB("_Q",2);
codegen.c:4428:    RMB("_R",2);
codegen.c:4429:    RMB("_S",2);
codegen.c:4430:    RMB("_T",2);
codegen.c:4431:    RMB("_U",2);
codegen.c:4432:    RMB("_V",2);
codegen.c:4433:    RMB("_W",2);
codegen.c:4434:    RMB("_X",2);
codegen.c:4435:    RMB("_Y",2);
codegen.c:4436:    RMB("_Z",2);
codegen.c:4437:    RMB("_CALLRET",2);
codegen.c:4449:            RMB_comment(label,2,comment);

「_」「V_」に変更

grep -nHIF -- \t_ (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:755:        printf("\tINC\t_%s\n",v);
codegen.c:760:        printf("\tDEC\t_%s\n",v);
codegen.c:765:        printf("\tINC\t_%s+1\n",v);
codegen.c:770:        printf("\tDEC\t_%s+1\n",v);
codegen.c:775:        printf("\tTST\t_%s+1\n",str);
codegen.c:779:        printf("\tTST\t_%s\n",str);
codegen.c:1036:        printf("\tNEG\t_%s+1\n",v);
codegen.c:1038:        printf("\tDEC\t_%s\n",v);
codegen.c:1039:        printf("%s\tCOM\t_%s\n",label,v);
codegen.c:1158:        printf("\tLDA%s\t_%s\n",r,str);
codegen.c:1172:        printf("\tLDA%s\t_%s+1\n",r,str);
codegen.c:1324:        printf("\tSTAB\t_%s+1\n",    str);
codegen.c:1325:        printf("\tSTAA\t_%s\n",        str);
codegen.c:1361:        printf("\tSTAA\t_%s\n",str);
codegen.c:1366:        printf("\tSTAA\t_%s+1\n",str);
codegen.c:1376:        printf("\tSTAB\t_%s\n",str);
codegen.c:1381:        printf("\tSTAB\t_%s+1\n",str);
codegen.c:1415:        printf("\tADDB\t_%s+1\n", v);
codegen.c:1459:        printf("\tADDB\t_%s+1\n",    v);
codegen.c:1460:        printf("\tADCA\t_%s\n",        v);
codegen.c:1495:        printf("\tSUBB\t_%s+1\n",    v);
codegen.c:1496:        printf("\tSBCA\t_%s\n",        v);
codegen.c:1569:        printf("\tANDB\t_%s+1\n",    v);
codegen.c:1575:        printf("\tANDB\t_%s+1\n",    v);
codegen.c:1576:        printf("\tANDA\t_%s\n",        v);
codegen.c:1606:        printf("\tORAB\t_%s+1\n",    v);
codegen.c:1607:        printf("\tORAA\t_%s\n",        v);
codegen.c:1631:        printf("\tEORB\t_%s+1\n",    v);
codegen.c:1632:        printf("\tEORA\t_%s\n",        v);
codegen.c:1671:            printf("\tCLR\t_%s+1\n", v);
codegen.c:1682:            printf("\tCLR\t_%s\n", v);
codegen.c:1788:        printf("\tCMPA\t_%s\n",str);
codegen.c:1792:        printf("\tCMPA\t_%s+1\n",str);
codegen.c:1800:        printf("\tCMPB\t_%s\n",str);
codegen.c:1804:        printf("\tCMPB\t_%s+1\n",str);
codegen.c:1866:        printf("\tLDX\t_%s\n",str);
codegen.c:1895:        printf("\tSTX\t_%s\n",    v);
codegen.c:1909:        printf("\tCPX\t_%s\n",str);
codegen.c:1936:        printf("\tLDX\t_%s\n",str);
codegen.c:4398:    printf("\tSTS\t_RETSP\n");

「_」「V_」に変更

grep -nHIF -- \tRMB\t2 (ディレクトリ: /home/nikohon/ダウンロード/DIY/SBC6809/GAME9/BASICMASTER-main/GAME-CC0_0517)
codegen.c:4457:            printf("_%s\tRMB\t2\t; for loop pseudo array\n",ofl[i].label[j]);
codegen.c:4465:            printf("_%s\tRMB\t2\t; do loop pseudo array\n",odl[i].label[j]);

「_%s」を「V_%s」に変更

asm6809では「FCC 'ABC'」などと記述すると 'ABC'の最初のAしかオブジェクトに反映されないバグ? 仕様?
なので、「FCC 'ABC'」は「FCC /ABC/」などと記述を変更する。

DO-untilループの出現数カウンタのodlの扱いが、for-nextループの出現カウンタのoflと
混同されているところを2箇所発見修正

エミュレータ6809内蔵のアセンブラのバグで #-1を8ビットの#$ffと変換する。8ビットのA,Bに対してなら問題ないがD,X,Yなど16ビット計算では意味が変わってくる。
追記:#-$01とすると $00ffを#-$0001とすると$ffffを出してくれる。
GAMECC側に16ビット数値を扱うときに変更するように工夫が必要。
ADDD,LDX命令のイミディエイト コードを出す所に負号拡張処理を追加
FCCコードの部分で文字列中に「/」スラッシュを使うと、
デリミターとしての/と混同されて文字列の一部が消滅するのでデリミターとして「”」ダブルクォートを使うことにする。

この時点で引っかかっているのは、RNDのシード値が設定できない。
do-untilの「@=1」をコンパイルするとコンパイラが警告文を出すが動作するコードを吐く
othello.gで使われているのだが、所謂 do-untilループ内からのbrakeらしいのだが
do-untilの一対しか許されてないっぽいので、警告のエラーを出してるっぽい?
BM-L2用の特殊文字の変換ルーチンを無くす。SBC6809などのACIAのシリアル接続だけの環境用に作っているので
所謂7ビット文字だけの扱いに収めるのが目標
プログラムの終端をどうしようか思案中、インタプリタでは
「#=-1」でプログラム終了してインタプリタに戻ってきたが、
今のところ何も入れてないのでメモリ空間一周してバッファフローしてエミュレータがフォールトする。

そろそろ、SBC6809実機に入れる算段も考えたい。EEPROMを外して焼いて戻してだと非効率だから、
HEX形式でシリアル転送して、メモリに転送するルーチンをROMに組むこむか?

6800−6809のニーモニックコンバータが無いのかと探している。
6809が出た当初に、6800から移行した先達が作っていそうだと思ったんだが見つけられていない。

rev 0520
BM-L2の固有文字を変換する部分を無効化、
LDXに対して 変数領域 オリジナルだと「_」で始まる変数のラベルをこちらでは「V_」で始まるようにしてるので
LDXに付ける変数ラベルが変えられてないのを修正。

オリジナルだと
    LDX    #_TMP
なのを
    LDX    #V_TMP
と出すようにしてるつもりで、オリジナルのままだったのを修正

インタプリタのGAME9EXのセットのGAME9CCを試しにgameccでコンパイルさせてみた際にこのバグを発見。
GAME9CCにもいくつかバグを発見
行番号3610と3700の間に、3520があってエラーになる。

あとGAME言語的には仕様であってバグではないのだが、存在しない行番号に向けてジャンプする命令が何箇所か
gameccではエラー扱いなので、コメント文のダミー行を入れて対処。

intelHEX形式の端末画面経由のアップロード、ダウンロードツールを作る。
要はHEX形式のテキスト文をコピーして6809上でペーストするとメモリ上に落とされる。ダウンローダと
6809のメモリ上のバイナリデータをHEX形式に整えて、画面に表示させ
それを端末上からコピーしてPCでテキスト文として保存する。セーバー。
ダウンローダーはZ80のアセンブラで組まれたものが参考に出来たので、
6809でもアセンブラで組んでみた。
セーバーは、GAME言語で組んでGAMECCでアセンブラのソースにした。
その際に、「TSX」のコードのミスを発見。
単に「TFR S,X」で良いのを「LD X,S」としていた。
レジスタ同士のデータのやり取りをLD命令でやる80系の癖でヤラカシていた。
あと、6800ではSを1加算すると説明されていたが、
6809でSに1加算するとスタック絡みでフォールトするので不要だと判断した。

入力動作の際に、16進のA-Fの小文字での入力を受け付けないのを
小文字のA-Fを内部で大文字に変換するようにした。

RNDシード値の設定をできるように修正
オミットしたTIMER設定部を参考にRNDに置き換えてみた。

あと、#-1を#-$0001に修正する部分で#0も#-$0000になっていたのを修正

オプティマイズルーチンが過剰反応して、無駄な省略をするせいで
却って変数の無駄な差し渡しが発生しているところを直したいが最適化処理の流れを追うのが面倒で放置中
現状、なんとか動いているので一旦はコレで良しとする。ソース上でもインタプリタでも問題なく動作するが
GAMECCでコンパイルすると動作がおかしい場合は、出てきたアセンブラのソースを眺めて
該当部分のデータの流れを適宜見てもらうしかない。

例を示すと
maze.gの
102 D(0)=1 D(1)=S D(2)=-1 D(3)=-S U=S*T-1
がオリジナルだが
GAMECCでコンパイルして動作させるために
102 D(0)=1 U=S D(1)=S D(2)=-1 D(3)=-U U=S*T-1
オプティマイザの処理で、変数Sとそれを負数にした-Sが同一の値だと認識されてD(3)に代入されるので
一旦変数Uという別の器を用意している。

変数領域として$800、プログラム本体は$2000に生成するように.asm内のORG文を設定して
GAMECCの中でコンパイル時に変更できるようなコマンドラインオプションなどは用意していない。 

コメント

このブログの人気の投稿

screen コマンドでの コピーペースト転送の実現について

 以前、GAME言語のあれこれについての中で、GAME80ICなどでZ80-MBC2とのscreenコマンドでのシリアル接続中にソーステキストのコピーペースト転送ができない事に触れていたが、単に使ってる環境に依存した所謂「おまかん」なのだが、回避したければ、素直にwindowsで使うか 若しくは linuxでもwine上でteratermを使えば済む話ではある。だが、我が家に於いては普段使いにできるwindows機など無い。棚の奥を探せばwin7の入った古PCが有るとは思うがボードマイコンとの接続の為だけに引っ張り出してきたいとまでは思わない。そこで ふと考えるにteratermにあってscreenやcu,minicomにないものはと、teratermには、テキスト転送中に行単位、文字単位でミリセカンドのディレイを挟む設定がある。対してlinux系のシリアル接続コマンドにそういった類のモノを知らない(単に自分が知らないだけの可能性もある) 。そこで、duckduckgo検索のサービスである「Duck.AI」に聞いてみた。自分の思いついた革新的なアイデアは大概は先人が既に思いついてる当たり前過ぎるモノというのはいつもの事であっさりと解決策を教えてくれた。

一部の関西の人にしか通じないネタ

たぶん「30年モノ」くらいだと思う?  拡大 値札に注目! ちなみに、ATMEGA32へのファーム書込用のアダプタを作るのに使用。

GAME言語 あれこれ

 MZ-700用にSDカードからMZTファイルの読み書きが出来る基板を入手して以降、MZ用のインタープリタやコンパイラの打ち込みをやってた延長でZ80-MBC2上のCPMで動作するGAMEインタープリタとコンパイラをいくつか発見。GAME-MZは国会図書館のコピーサービスで当時のアスキー誌の記事を入手済で打ち込みMZT化は済んでいるが動作の確認はしてない。 CP/M-80で動作するGAME80言語を3点ほど紹介する。 まず、動作環境は実機としては8Mhz動作のZ80-MBC2にXMODEMでPCからのファイル転送 PC側はFedora40の端末から「screen」コマンドでの接続、比較用に同じくFedora40の端末上で動作するCPMエミュレータ2種類。エミュレータで動作確認がとれたモノを実機に転送して最終動作させてみる流れ。    skyriverさんのGameOnCpm80 端末のエミュレータ上ではコピーペーストによるソースの転送もできるが ファイル読み書き用のコマンドが組み込まれているので、なぜか実機の方ではコピペに転送が出来ないのでありがたい。コンパイラも組み込まれているのでインタプリタで実行確認後、コンパイルもできる。 難点は、コンパイルの際にソース格納アドレスやデータエリア、オブジェクト格納エリアの指定をする必要がある。GAME-MZでもコンパイルの際は普通に必要な事ではあるが、自分の頭の中でシステムのメモリマップを把握しておくのが意外と面倒くさい。 コンパイルで 出来たオブジェクトをCOMファイルにするのにDDTなんかの別ツールでメモリ上に残ってるデータをCOMファイルとして保存するしかない。 COMファイル化とかを視野に入れずインタープリト、コンパイル、実行だけなら使いやすくお薦め。   ファイル操作コマンド例 files ファイル一覧表示 :\\ *.g 拡張子 .g のファイルの表示      \\のみ、\\ *.* での表示は出ない模様(単に自分の使い方が悪いだけかも?)  save(¥>FileName)とload(¥<FileName) 詳細は https://piclabo.blog.ss-blog.jp/CPM80GameCompiler...