パピコン(PC-6001)でGAME言語(その2)GAMEコンパイラ [PC-6001]
- GAME80インタプリタの改善
前回の初期バージョンではバックスペースに対応していませんでしたが、左カーソルキーのコード(1DH)でカーソルが左移動することが判ったのでBSキーに対応しました。
更にコントロールXの操作で入力キャンセルにも対応しています。
起動時の画面を貼っておきます。
GAME80(PC-6001)起動画面
- GAMEコンパイラの移植
元版のGAME80インタプリタの開始アドレスは8600Hからですが、今回パピコンに移植するにあたり、インタプリタのコードを拡張ROMエリアである4100Hからにし、ワークエリアを8406Hからにリロケートしています。
このためコンパイラがコンパイル時に埋め込むインタプリタ内の処理アドレスとワークアドレスを変更する必要があります。
手作業では大変なのでGAMEコンパイラのリロケートツールを作成し一括変換しました。
リロケート時のログが下記になります。コンパイラソースの行カウント値、行番号、変更前データ、変更後データを表示しています。
GAME80コンパイラ リロケート時のログ C:\src\PC-6001\compiler>perl cnvcomp.pl <GAMECOM.GAM >GAMEC6001.GAM 7 65 : $8D06 -> $8406 15 220 : $8603 -> $4103 15 220 : $8603 -> $4103 25 380 : $8C83 -> $4783 31 440 : $8B58 -> $4658 33 460 : $8B85 -> $4685 34 470 : $8D52 -> $8452 75 2420 : $8785 -> $4285 78 2510 : $8C26 -> $4726 80 2610 : $8C32 -> $4732 81 2620 : $8C31 -> $4731 83 2710 : $8C31 -> $4731 85 2810 : $8B9C -> $469C 95 3210 : $8A03 -> $4503 96 3220 : $8A0F -> $450F 97 3230 : $8A2C -> $452C 111 3610 : $8A03 -> $4503 140 4620 : $889E -> $439E 144 4720 : $8D4E -> $844E 145 4750 : $8C96 -> $4796 148 4800 : $8A5B -> $455B 149 4810 : $8872 -> $4372 150 4820 : $8881 -> $4381 151 4830 : $8904 -> $4404 190 5740 : $8A03 -> $4503 C:\src\PC-6001\compiler>
このツールはperlを使って作っています。ソースは以下になります。
GAME80コンパイラ リロケータ(perl) #!/usr/bin/perl # convert GAME compiler to any offset # ver 0.02 2020/01/28 skyriver use strict; use warnings; my $OrgStart = 0x8600; my $OrgSrcSt = 0x8E00; my $NewStart = 0x4100; # set here new code start address my $NewSrcSt = 0x8500; # set here new source save address my $OfstCod = $NewStart - $OrgStart; my $OfstDat = $NewSrcSt - $OrgSrcSt; my $Border = $OrgSrcSt - 0x100; # code/data border adrs my $LinCnt; # line counter my $LinNo; main(); sub main { my ( $ln, $find, $change ); while( <> ) { chomp(); $LinCnt++; $ln = $_; if( $ln =~ /^(\d+)/ ) { $LinNo = $1; while ( $ln =~ /\$(8[0-9,A-F]{3})/ ) { $find = $1; $change = eval( "0x" . $find ); $change += $change < $Border ? $OfstCod : $OfstDat; $change = sprintf( "%04X", $change ); printf( STDERR "\n%5d %5s : \$%s -> \$%s", $LinCnt, $LinNo, $find, $change ); $ln =~ s/\$$find/\$_$change/; } $ln =~ s/\$_/\$/g; printf( "%s\n", $ln ); } } }
これでコンパイラはできたのですがエミュレータに入れるため、エミュレータ(PC6001V)の「打込み代行」機能を使ってインタプリタに読込ませる段階で1行が64文字程度以上ある行が文字化けでうまく読み込めなかったため、若干ソースをいじって長い行をなくしました。
コンパイラは自信をコンパイルするのに時間が掛かること、及びコンパイラのソースを開示していいか不明なことからコンパイル後のバイナリで公開する予定ですが、メモリの何処に配置するかが悩ましいところです。
※コンパイラのソースに関しては「3チップ構成Pic24CPMマイコン(その7)GAMEコンパイラ」の記事を参照すればGAMEコンパイラのソースを入手できます。
拡張メモリの5000H-5FFFH、7000H-7FFFHを使用すると実機のROM&RAMカートリッジで試すのが難しくなるというコメントをTwitterで頂いたのですが、コンパイル結果のサイズが1939H程度で4KBの枠には収まりません・・
そこで下表のように拡張ROMの最後の方にコンパイラを配置することにしました。
>=$6666でコンパイラが起動します。4桁なので縁起が悪いということもないと思いますw
No. address content 1 4000-4001 'A'+'B'(auto exec mark) 2 4002-4003 初期化処理のエントリアドレス 3 4004 exit処理 4 4006 locate処理(変数Aに位置情報 High:ライン、Low:カラム) 5 400C-40FF 初期化処理など 6 4100-47DF GAMEインタプリタ本体 7 6666-7F9E GAMEコンパイラ 8 8406-84FF GAMEインタプリタ用ワーク 9 8500 ソース保存アドレスの初期値
- ダウンロード場所
今回変更したコンパイラ付きGAMEインタプリタは「パピコン(PC-6001)でGAME言語」のページからダウンロードできます。
★2020/01/29 追記
適切か否かは疑問がありますが、コンパイラの有効性を示す簡単なデモを作ってみました。
パピコン(PC-6001)に移植したGAME言語コンパイラの簡単なデモを作ってみた
— skyriver (@wcinp) January 29, 2020
コンパイルするだけで結構速くなる(大きなソースなら尚更)
この程度ならマシン語でも更に高速なのが簡単に作れるけどねw#PC6001 #パピコン #GAME言語 #GAMEコンパイラhttps://t.co/oJIEzSOIie pic.twitter.com/fl8G4mOVuJ
ソースは以下のとおりです。
GAME80コンパイラ デモ(GAME言語) |
1' PC-6001 sample2 source 2' ver 0.01 2020/01/29 by skyriver 100 B=&+1 VRAM=$8200 X=32 Y=15 110 D=VRAM+X M=X*(Y-1)/2-1 $=12 120 I=0,X-1 130 B:I)=" " ;='3=1 B:I)='224+" " 140 @=I+1 150 @ 160 I=M @ D(I)=VRAM(I) I=I-1 @=(I<0) 170 I=0,X/2-1 VRAM(I)=B(I) @=I+1 180 I=0,'4 190 R='X-1 ;=B:R)=" " B:R)='224+" " #=210 200 B:R)=" " 210 @=I+1 220 "" 230 @=(0) |
[TOP] [ 前へ ] 連載記事 [ 次へ ]
パピコン(PC-6001)でGAME言語 [PC-6001]
PC-6001の実機を所有していないのでGAME言語の移植は予定していなかったのですが、今ではパソコン上でエミュレータ(PC6001V)が動くようなので実機ROM無しの状態ではありますが、GAME言語のインタプリタを移植してみました。
コンソール入出力関連の処理はN60-BASICとROM内ルーチンで互換性のあるPC-6001用互換BASICの処理をコールする形で実装しました。
画面表示は1075Hの表示ルーチンを使用していますが、この処理はバックスペースでカーソルが移動しないため(実物もそうなのでしょう)、
★2020/01/28 変更
BSキーとコントロールXでの入力キャンセルに対応しました。
また、キー操作としてはスペースキーでポーズ(その後任意のキーで再開)、エスケープキーで中断です。
実装方法としては拡張ROMの 4000Hからのアドレスに配置したのでこのページからダウンロードしたファイルをエミュレータで拡張ROMとして設定すれば下図のようなGAME言語のインタプリタが自動起動するはずです。
PC-6001でのGAMEインタプリタ起動画面 |
|
Twitterにポストした動画付きコメントも貼っておきます。
エミュレータ環境を使ってパピコン(PC-6001)にGAME言語インタプリタを移植してみた
— skyriver (@wcinp) January 27, 2020
実機のROMが無いので実機環境で動作するのかは未確認^^;;
メモリマップのVRAM方式なのでGAME言語との相性はいいかも^^#PC6001 #GAME言語 #パピコン #PC6001Vhttps://t.co/KxE6MxkINv pic.twitter.com/eWFqGiP4Pn
上の動画で実行しているサンプルソースは以下の通りです。VRAMの内容を参照して方向を変更しています。
サンプルソース(GAME言語) |
1' PC-6001 sample source 2' ver 0.01 2020/01/27 by skyriver 100 VRAM=$8200 X=32 Y=15 O="1" 110 B=0 C=0 120 M=1 N=0 $=12 130 @ 140 @ 150 D=B E=C 160 VRAM:C*X+B)=O O=O+1 ;=O>"z" O="1" 170 B=%((B+M+X)/X) 180 C=%((C+N+Y)/Y) 190 @=(VRAM:C*X+B)<>" ") 200 B=D C=E 210 ;=M<>0 N=M M=0 #=230 220 ;=N<>0 M=-N N=0 230 B=B+M C=C+N 240 @=(VRAM:C*X+B)<>" ") |
今回はROMカートリッジの前半(4000H-5FFFH)に入れる想定なので元版のインタプリタのコードとワークをそれぞれ異なるオフセットで移動しました。
メモリマップの概要は以下のとおりです。
No. | address | content |
---|---|---|
1 | 4000-4001 | 'A'+'B'(auto exec mark) |
2 | 4002-4003 | 初期化処理のエントリアドレス |
3 | 4004 | exit処理 |
4 | 4006 | locate処理(変数Aに位置情報 High:ライン、Low:カラム) |
5 | 400C-40FF | 初期化処理など |
6 | 4100-47DF | GAMEインタプリタ本体 |
7 | 6666-7F9E | GAMEコンパイラ |
8 | 8406-84FF | GAMEインタプリタ用ワーク |
9 | 8500 | ソース保存アドレスの初期値 |
★2020/01/28 追記 Ver0.02でメモリマップにコンパイラを追加
【ダウンロード】
・GameCompV002_20200128.zip
・GAME_V001_20200127.zip(旧バージョン)
【履歴】
- Ver 0.02 2020/01/28
BSキー対応、コントロールXキー対応、コンパイラ同梱、詳細はこちらを参照 - Ver 0.01 2020/01/27 初版 公開
★2020/02/01 追記
GAMEソースをリナンバ処理するGAMEのソースリストがここにあります。
【参考にさせて頂いた主なサイト】
- 秋川藤志のページ PC-6001用互換BASIC
互換BASICの内部コール処理等 - Hashi's HomePage THE B-TYPE UNION.
N6x BASIC リファレンス-付録2:メモリマップ - ぱぴこんのこころ PC6001V
PC6001Vエミュレータに関する情報 - 戦士のカートリッジmkII 技術資料
- P6つくろうブログ ROMカートリッジについて
ROMカートリッジに関する情報
[TOP] [ 前へ ] 連載記事 [ 次へ ]
ポケコン(PC-G850V)でGAME言語(その6)LifeGame2 [ポケコン]
この時は動作確認ということもあり、キャラクタベースで、かつ処理の最適化は考慮していませんでした。
今回はグラフィック機能を使い1キャラクタを4分割することで解像度を縦横それぞれ2倍にしてライフゲームを動かしてみました。
データ量が4倍になるのでGAME言語のソースも高速化を考慮し変更しています。
PC-G850でグラフィック表示するためにはIOCS(BIOS)コールの一つであるパターン表示(BFD0H)をコールするか、I/Oを直に制御するかのどちらかになりますが、今回はIOCSコールを使用しました。
パターン表示処理への引数はレジスタ経由で
なのでGAME言語からの直接コールではなく、アセンブラ経由でコールしています。
引数の位置情報はキャラクタ表示時のキャラクタ位置で書込み開始がキャラクタの左端の位置からになるので、1文字分より少ない書込みでは隙間が空いてしまいます。
このため、書込みは1文字単位(8bit x 6)とし、4ピクセル分なので16通りのビットパターンを持たせました。
今回作成したライフゲームが動作中のサンプル画面が下図です。前回のものと比べると表示領域がかなり広くなりました。^^
GAME言語でライフゲーム(グラフィック版) |
|
アセンブラのソースは次のとおりで1回のコールで
PC-G850Vでライフゲーム(アセンブリ言語) |
|
タイトルは適当に作ったこれ⇒
★2020/01/24 変更 MAX更新時のパターン追加
また、GAME言語のソースは下記になります。ループ内では乗算及び除算の計算回数を少なくする等の変更を行いました。
ソースサイズが小型で小メモリの環境向きであることもGAME言語の特徴ですね。
PC-G850Vでライフゲーム(GAME言語) |
|
★2020/01/24 変更 乱数seed設定追加(Returnでデフォルト値)
尚、GAME言語のインタプリタやコンパイラ等は「ポケコン(PC-G850V)でGAME言語」からダウンロードできます。
Twitterにポストした動画付きメッセージを貼っておきます。
ポケコン(PC-G850V)へのGAME言語の移植が完了したのでグラフィック表示のライフゲームを作ってみた
— skyriver (@wcinp) January 21, 2020
グラフィック描画コール部は最小限のアセンブラを使いそこそこの速度で描画出来ている^^#PCG850V #G850V #ポケコン #GAME言語https://t.co/3DVwHh6fat pic.twitter.com/djNFgsAJ3X
★2020/01/21 追記 {
Twitterにアップした動画は編集ミスやtypoが・・・・orz
編集時に何とかしようと思うと後が大変なので録画時に気合を入れてミスをなくすのがbetterですね(自分への教訓)
}
★2020/01/23 追記 {
今回のLifeGameのプログラムはソースエンド位置を保持する'&'の値の次のアドレスからテーブル用ワークとして使っています。
ビデオ内では実施していませんでしたが、ソース先頭アドレスである'='の設定だけでは'&'はアップデートされないため、'&'をアップデートするための == コマンドを行ってからプログラム実行するようにしてください。
}
以下は今回作成したライフゲームの自動起動HEXファイルの作成についての個人的なメモ書きです。
GAMEソースの開始アドレス(=空エリア)は0C00Hからで次のようにメモリに配置した。
No. | start | end | contents |
---|---|---|---|
1 | 0C02H | 0D6DH | assembled object |
2 | 0D70H | 134AH | compiled object |
3 | 1350H | 1716H | work area |
更にGAME内に下記のパッチを入れ、コンパイルしたプログラムが自動起動するようにした。
・0406 21 0C 00 -> 21 4F 13 change '=' and '&' value ・0420 21 8D 0A -> C3 70 0D jump to compiled object
GAMEインタプリタを含む自動起動HEXファイルは以下からダウンロードできます。
※使用メモリ領域は 0100H-1716H で、G100で起動します。
注意:インタプリタに上記のパッチを入れているので通常のGAME言語インタプリタを使用する場合は再度インタプリタのダウンロード(もしくは上記のパッチを元に戻す)が必要です。
・lifeAuto20200124.zip
★2020/01/24 変更 {
・いつも同じパターンだとつまらないので起動時に乱数のseed入力追加
・MAX記録時のドット表示を別パターン化
GAME言語でライフゲーム(2020/01/24版) |
|
★2020/01/26 追記
起動時の乱数初期値を987で入力すると途中で面白い模様のパターンになるのを発見w
[TOP] [ 前へ ] 連載記事 [ 次へ ]
ポケコン(PC-G850V)でGAME言語(その5)LifeGame [ポケコン]
グラフィックを使えば細かくできるでしょうが、GAMEコンパイラの動作確認の意味合いも込めてまずはキャラクタベースで動かしました。
短い周期の定常パターンであれば検出したら乱数で新しい種パターンを自動生成するようにしていますが、LCD画面が狭いのでそのうちに長い周期の定常パターンになってしまいます・・・
動作確認目的なのでソースは綺麗に整理してはいませんが下記の通りです。
結果として今回ポケコンに移植したGAME言語のインタプリタ及びコンパイラで問題の検出はありませんでした。
PC-G850Vでライフゲーム(GAME言語) |
|
Twitterにポストした動画付きメッセージを貼っておきます。
★2020/01/20 追記 {
尚、GAME言語のインタプリタやコンパイラ等は「ポケコン(PC-G850V)でGAME言語」からダウンロードできます。
下記の動画では次の操作を行っています。
- GAMEソースのロード
エミュレータなので一瞬で終了していますが、パソコン側にあるライフゲームのGAME言語のソースをシリアル通信でTEXTエディタ領域にロードする。 - TEXTエディタ内データの変換
GAMEインタプリタを起動し、ロードしたTEXTエディタ内のソースデータを4E00Hに置いておいた変換ツールにより、GAME言語のソースに変換する(変換後のソースは0C00Hからにセーブ)
- 変換ソースの確認
変換したソースをリスト表示して確認する。
- コンパイル
変換したソースを3400Hに配置しておいたコンパイラでコンパイルする。
- 実行
コンパイルしたオブジェクトを実行する。
ポケコン(PC-G850V)へのGAME言語の移植も一段落したのでGAME言語のインタプリタ/コンパイラの動作確認も兼ねてライフゲームを動かしてみました^^#PCG850V #G850V #ポケコン #GAME言語https://t.co/KbCVWuiQFQ pic.twitter.com/rK0lSJvqTw
— skyriver (@wcinp) January 19, 2020
[TOP] [ 前へ ] 連載記事 [ 次へ ]
ポケコン(PC-G850V)でGAME言語(その4)GAME高速化 [ポケコン]
気になったので原因を調査しました。結果、やはりキーセンス処理で時間が掛かっていたようです。
今回のキーセンスセンス処理ではG850のIOCS(BIOS)処理であるリアルタイムキー入力(0BE53H)を使用しています。
ネット情報ではIOCSのコールの中ではキーマトリックス回路にセンスビットを出力する度に0.2msのソフトタイマを実行しているようです。
また、キー入力があった(Cy:1)場合に、Aレジスタで帰ってくるキーマトリックスデータを自前の処理でデコードし有効なキーが押されているか確認しています。この処理も通常のキー入力バッファ内のキャラクタ数を確認するような処理よりは重くなります(でもこの処理はキーが押されている間だけなので影響は少ない)。
一方、GAMEインタプリタではキーセンス処理をコールするところが次の2ヶ所ありました。
- ソースのステートメント解析部
予期せぬループ状態になった場合にBREAKできるように、ステートメントを解析する度にキーセンス処理をコールしている。
- 文字列出力部
文字列出力後にキーセンス処理をコールしている。
後者はあまり影響ないのですが、前者のコールは頻繁に発生するので前述のような今回の実装では実行速度に大きな影響が出ていました。
(因みにGAMEコンパイラは高速化のために後者だけコールしています)
対策として上記 i のケースでのキーセンス処理を間引いてコールすることにしました。
間引き数と実行時間の関係は下記の通りです。
No. | コール比率 | ベンチマーク実行時間[sec] |
---|---|---|
1 | 1/1 | 553(9m13s) |
2 | 1/16 | 113(1m53s) |
3 | 1/32 | 98(1m38s) |
4 | 1/64 | 91(1m31s) |
5 | 1/128 | 87(1m27s) |
6 | 1/256 | 85(1m25s) |
この結果から間引き率は1/64としました。
★2010/01/17 追記 {
上表に1/128と1/256を追記。256ではブレークキー('TAB')の感度低下が感じられた。
Ver0.02dで1/128に変更しました。
}
今回高速化したGAME言語のインタプリタは「ポケコン(PC-G850V)でGAME言語」のページからダウンロードできます。
今回の変更でバージョンを 0.02c としました。
また、ベンチマーク結果は「MSX-DOS上でのGAME言語のベンチマーク」の記事にまとめています。
GAME言語起動画面 |
|
[TOP] [ 前へ ] 連載記事 [ 次へ ]