【MSX】ubuntu20.04でopenMSX+debuggerの環境を構築する
WindowsにはblueMSXというデバッガ機能を内蔵した強力なエミュレータがあるが、Linux(ubuntu)には用意されていない。
そこで、openMSXに用意されているdebuggerを使って、デバッグ環境を構築してみる。
なお、openMSXはリポジトリからのインストールも可能だが、今回はgithubに公開されているソースからビルドする。
openMSXのインストール
githubからcloneする。
$ git clone https://github.com/openMSX/openMSX.git
configureする。
$ cd openMSX $ ./configure
すると以下の出力がされる。
Using Python: python3 Probing target system... Creating derived/x86_64-linux-opt/config/probed_defs.mk... Creating derived/x86_64-linux-opt/config/systemfuncs.hh... Found libraries: ALSA: version 1.2.2 GLEW: no libogg: no libpng: version 1.6.37 libtheora: no libvorbis: no OpenGL: version 4.6 SDL2: version 2.0.10 SDL2_ttf: no Tcl: version 8.6.10 zlib: version 1.2.11 Components overview: Emulation core: no GL renderer: no Laserdisc: no ALSA MIDI: yes Customisable options: Install to /opt/openMSX (you can edit these in build/custom.mk) Please install missing libraries and headers and rerun "configure". If the detected libraries differ from what you think is installed on this system, please check the log file: derived/x86_64-linux-opt/config/probe.log
このうち、Found Libraries
のところでno
と出ているのが不足しているライブラリになる。
追加でインストールする。
$ sudo apt install libglew-dev $ sudo apt install libogg-dev $ sudo apt install libtheora-dev $ sudo apt install libvorbis-dev $ sudo apt install libsdl2-ttf-dev
make、install。
$ sudo make $ sudo make install
起動する。
BIOSを適切に配置して設定すると実機と同様にBASICが使えるが、素の状態ではC-BIOSという互換BIOSが起動する。
$ openmsx &
debuggerのインストール
OpenMSX debuggerにはqt5が必要なのでインストールする。
$ sudo apt install qtbase5-dev qttools5-dev-tools qt5-default
githubからcloneする。
$ git clone https://github.com/openMSX/debugger.git
configureはないので、そのままmake。
$ cd debugger $ make
するとエラーが出る。
Compiling DebuggerForm.cpp... src/DebuggerForm.cpp: In member function ‘void DebuggerForm::createForm()’: src/DebuggerForm.cpp:624:45: error: ‘SkipEmptyParts’ is not a member of ‘Qt’ 624 | QStringList s = list.at(i).split(" ", Qt::SkipEmptyParts); | ^~~~~~~~~~~~~~ src/DebuggerForm.cpp: In member function ‘void DebuggerForm::setDebuggables(const QString&)’: src/DebuggerForm.cpp:1454:38: error: ‘SkipEmptyParts’ is not a member of ‘Qt’ 1454 | QStringList l = list.split(" ", Qt::SkipEmptyParts); | ^~~~~~~~~~~~~~ make: *** [build/main.mk:326: derived/obj/DebuggerForm.o] Error 1
表示されたとおり、Qt::SkipEmptyParts
がqt
にないよ、と言われている。
調べてみると現在のバージョンでは廃止になっているようで、代わりにQString::SplitBehavior::SkipEmptyParts
を使う模様。
エラーに出ているsrc/DebuggerForm/cpp
の624行目と1454行目の該当箇所を書き換えて、改めてmake。
2021/9/9 追記
z88dkの.mapを読んでdisassemblerウィンドウにラベルを表示するパッチを適用する。
以下からzipを取得して展開。
[openmsx-debugger で z88dk の -m 形式の .map symbol を読ませる hack (github.com)]
中にある0001-add-z88dk-symbol-read-hack.patch
をopenmsx-debugger
ディレクトリに配置し、以下コマンドを実行。
$ patch -p1 < 0001-add-z88dk-symbol-read-hack.patch
@h1romas4さん、ありがとうございました!
無事にコンパイルできたら、openmsxと同じ場所にコピーしておく。(make install
は用意されていない)
$ sudo cp -p derived/bin/openmsx-debugger /usr/local/bin
起動してみる。
$ openmsx & $ openmsx-debugger &
起動したデバッガーウィンドウのメニューから[System]-[Connect]を選ぶか、[Ctrl]+[C]を押す。 メモリやレジスタなどの情報が表示されれば、ひとまず成功。
補足
この記事の内容は、ubuntu20.04、及びWindows10+WSL2のubuntu20.04で実施済です。
また、記事執筆時点(2021/8/31)でのソース及びライブラリの状態での結果ですので、今後はエラーが解消していたり、新しいエラーが発生する可能性があります。
この記事を参考に作業される場合は、上記をご理解の上、行ってください。
【MSX】GALAXY ZONE
これまでのMSX-BASICの研究結果をもとに、ちょっとしたゲームを作ってみました。
以下のURLで遊べます。
webmsx.org
遊び方
しばらく待って、タイトルが出たらSPACE or Aボタンでスタート。
カーソルキー or コントローラの左右で移動、スペースキーで前進して、ミサイルを動かします。
アステロイドにぶつからないように、画面上部のマザーシップを破壊してください。
以下のいずれかの条件でミスになります。
- アステロイドに当たった
- 燃料がなくなった
- マザーシップに当てられなかった
3回ミスするとゲームオーバーです。
ソースなど
githubでもソースとディスクイメージを公開しています。
詳細については、こちらを参照してください。
github.com
ではでは。
【MSX】MSX-BASICの研究(2) PRINTとVPOKEの性能比較
- この記事について
- テスト方法
- 1文字表示編
- 比較結果
- 2×2キャラクタ表示編
- パターン4:PRINT(セミコロンなし)
- パターン5:PRINT(セミコロンあり)
- パターン6:VPOKE
- 比較結果
- 余談
- 関連記事
この記事について
MSXでキャラクタを画面表示する際には、PRINT
を使うよりはVPOKE
を使う方が速いのだが、ではどれくらい速度差があるのだろうか?
具体的に数値として知らなかったので、調べてみました。
テスト方法
今回のテスト方法は、以下の方針としています。
- WebMSXで実施。
- 一般的に使用される、SCREEN 1、WIDTH 32、DEFINT A-Zで初期化した状態で実行する。
- 文字表示を1,000回繰り返し、経過時間を測る。(
TIME
を使用)
1文字表示編
パターン1:PRINT(セミコロンなし)
プログラムリスト
10 SCREEN 1:WIDTH 32:DEFINT A-Z 20 TI=TIME 30 FOR I=0 TO 999:LOCATE 0,0:PRINT "A":NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
結果
パターン2:PRINT(セミコロンあり)
プログラムリスト
10 SCREEN 1:WIDTH 32:DEFINT A-Z 20 TI=TIME 30 FOR I=0 TO 999:LOCATE 0,0:PRINT "A";:NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
結果
パターン3:VPOKE
プログラムリスト
10 SCREEN 1:WIDTH 32:DEFINT A-Z 20 TI=TIME 30 FOR I=0 TO 999:VPOKE &H1800,&H41:NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
結果
比較結果
パターン | 概要 | 処理時間 |
---|---|---|
1 | PRINT(セミコロンなし) | 355 |
2 | PRINT(セミコロンあり) | 305 |
3 | VPOKE | 116 |
VPOKE
がPRINT
の2倍以上速いという結果になりました。
また、PRINT
も、セミコロンをつけることで若干高速化されています。
2×2キャラクタ表示編
パターン4:PRINT(セミコロンなし)
プログラムリスト
10 SCREEN 1:WIDTH 32:DEFINT A-Z 20 TI=TIME 30 FOR I=0 TO 999:LOCATE 0,0:PRINT "マイ":LOCATE 0,1:PRINT "コン":NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
結果
パターン5:PRINT(セミコロンあり)
プログラムリスト
10 SCREEN 1:WIDTH 32:DEFINT A-Z 20 TI=TIME 30 FOR I=0 TO 999:LOCATE 0,0:PRINT "マイ";:LOCATE 0,1:PRINT "コン";:NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
結果
パターン6:VPOKE
プログラムリスト
10 SCREEN 1:WIDTH 32:DEFINT A-Z 20 TI=TIME 30 FOR I=0 TO 999:VPOKE&H1800,&HCF:VPOKE&H1801,&HB2:VPOKE&H1820,&HBA:VPOKE&H1821,&HDD:NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
結果
比較結果
パターン | 概要 | 処理時間 |
---|---|---|
4 | PRINT(セミコロンなし) | 733 |
5 | PRINT(セミコロンあり) | 633 |
6 | VPOKE | 362 |
1文字表示の時と比べての処理時間は、PRINT
は約2倍強ですが、VPOKE
は約3倍強ほどになっています。
これは、プログラムリストの通り、キャラクタの数だけVPOKE
する(=4回実行する)必要があるためですが、それを差し引いても、PRINT
よりは速いですね。
通常、ゲームで表示するパターンは2×2キャラクタ(16×16ドット)が多いと思われるため、なるべくVPOKE
を使うことで高速化が見込めると思います。
余談
なお、VPOKE
する値を10進数で書いて計測もしてみたのでが、16進数の時とほとんど変わりませんでした。
MSXのBASICプログラムでは、16進数、10進数のどちらで書いても良いと思います。
※2021/8/11追記: エスケープシーケンスで、1回のPRINT文で2×2キャラクタを表示した場合の処理速度を計測してみました。
パターン7:PRINT(エスケープシーケンス使用)
プログラムリスト
10 SCREEN 1:WIDTH 32 20 TI=TIME 30 FOR I=0 TO 999:LOCATE 0,0:PRINT "マイ"+CHR$(29)+CHR$(29)+CHR$(31)+"コン";:NEXT 40 LOCATE 0,5:PRINT "TIME="; TIME-TI
CHR$(29)がカーソル左移動、CHR$(31)がカーソル下移動になります。
処理結果
結果、961とPRINT2回より遅いという結果になりました。
MZとかだと速かった気がしたんですけど、MSXだと結構遅かったのですね…。
関連記事
【MSX】MSX-BASICの研究(1) 条件分岐ロジック
この記事について
MSX-BASICでプログラムを書いていて思い出すのが、昔ベーマガでDr.Dが「論理式を使うのじゃ」と口を酸っぱくして言っていたこと。
確かに論理式を使うとIF文は無くなるが、しかし、論理式は本当に速いのだろうか?
というのも、ネットでBASICの高速化テクニックを探していたところ、ON〜GOTO〜を使うほうが速い、という記事を見つけたためで、本当はどれが速いのだろうか?と考えた次第。
それじゃあ実際に比較してみようか、というのがこの記事の趣旨になります。
今の時代にどれだけの人が必要としている情報なのかわかりませんが(汗
※(2021/8/9)パターン4として、移動量を配列変数に定義した場合をテストしてみました。
記事の最後に追記しています。
テスト方法
今回のテスト方法は、以下の方針としています。
- WebMSXで実施。
- 一般的に使用される、SCREEN 1、WIDTH 32、DEFINT A-Zで初期化した状態で実行する。
- ロジックは、実際の実装を考慮して4方向の判定処理とする。
- カウントダウン終了から画面右端までの移動時間を測る。
パターン1
素直に入力値をIF文でひとつひとつ判定していくコードです。
プログラムリスト
100 ' ******************************* 110 ' CHARACTER MOVE LOGIC TEST 1 120 ' ******************************* 130 ' *** COMMON INITIALIZE *** 140 SCREEN 1:WIDTH 32:DEFINT A-Z 150 LOCATE 0,0:FOR I=3 TO 1 STEP-1:PRINT I;:FOR J=0 TO 999:NEXT J,I:PRINT " START" 160 X=0:Y=10:TM=TIME 200 ' *** LOGIC *** 210 S=STICK(0):VX=0:VY=0 220 IF S=1 THEN VY=-1:GOTO 260 230 IF S=3 THEN VX=1:GOTO 260 240 IF S=5 THEN VY=1:GOTO 260 250 IF S=7 THEN VY=-1 260 LOCATE X,Y:PRINT " ";:X=X+VX:Y=Y+VY:LOCATE X,Y:PRINT "A"; 270 IF X<32 GOTO 200 300 ' *** RESULT *** 310 LOCATE 0,1:PRINT "TIME="; TIME-TM 320 END
実行結果
パターン2
ON〜GOTO〜で分岐させるコードです。
プログラムリスト
100 ' ******************************* 110 ' CHARACTER MOVE LOGIC TEST 2 120 ' ******************************* 130 ' *** COMMON INITIALIZE *** 140 SCREEN 1:WIDTH 32:DEFINT A-Z 150 LOCATE 0,0:FOR I=3 TO 1 STEP-1:PRINT I;:FOR J=0 TO 999:NEXT J,I:PRINT " START" 160 X=0:Y=10:TM=TIME 200 ' *** LOGIC *** 210 S=STICK(0) 220 ON S+1 GOTO 270,230,270,240,270,250,270,260,270 230 VX=0:VY=-1:GOTO 270 240 VX=1:VY=0:GOTO 270 250 VX=0:VY=1:GOTO 270 260 VX=-1:VY=0:GOTO 270 270 LOCATE X,Y:PRINT " ";:X=X+VX:Y=Y+VY:LOCATE X,Y:PRINT "A"; 280 IF X<32 GOTO 200 300 ' *** RESULT *** 310 LOCATE 0,1:PRINT "TIME="; TIME-TM 320 END
実行結果
パターン3
論理式を使ったコードです。
プログラムリスト
100 ' ******************************* 110 ' CHARACTER MOVE LOGIC TEST 3 120 ' ******************************* 130 ' *** COMMON INITIALIZE *** 140 SCREEN 1:WIDTH 32:DEFINT A-Z 150 LOCATE 0,0:FOR I=3 TO 1 STEP-1:PRINT I;:FOR J=0 TO 999:NEXT J,I:PRINT " START" 160 X=0:Y=10:TM=TIME 200 ' *** LOGIC *** 210 S=STICK(0) 220 VX=(S=7)-(S=3) 230 VY=(S=1)-(S=5) 240 LOCATE X,Y:PRINT " ";:X=X+VX:Y=Y+VY:LOCATE X,Y:PRINT "A"; 250 IF X<32 GOTO 200 300 ' *** COMMON RESULT *** 310 LOCATE 0,1:PRINT "TIME="; TIME-TM 320 END
実行結果
比較結果
結果は以下のようになりました。
パターン | 処理方法 | 処理時間 |
---|---|---|
1 | IF文のみ | 56 |
2 | ON〜GOTO〜 | 51 |
3 | 論理式 | 59 |
総括
ON〜GOTO〜で処理するのが一番速いですね。実際にテストしていても、体感できるくらいに違いました。
また、パターン3の論理式がパターン1のIF文のみより遅かったという結果は、ちょっと意外でした。
しかし、パターン1のプログラムを見ていただけるとわかりますが、IF文で判定とは言え、条件に合致したときに他のIF文に入らないようにGOTOで飛ばしていますので、速くなっていたのでしょう。
論理式ではすべての値を評価する必要があるので、全てのIF文を実行しているのと同じことになっているのだと考えます。
実際、パターン1で各IF文のGOTOを書かなかった場合、処理時間は64と最も遅い結果になっていました.。
プログラムで条件分岐書く時は、ON〜GOTO〜で書けるように変数の値も考えると良いですね。
また気になる事があったら、検証してみたいと思います。
※2021/8/9 追記
パターン4
入力に対する各方向への移動量を配列変数に定義したコードです。
プログラムリスト
100 ' ******************************* 110 ' CHARACTER MOVE LOGIC TEST 4 120 ' ******************************* 130 ' *** COMMON INITIALIZE *** 140 SCREEN 1:WIDTH 32:DEFINT A-Z 142 DIM VX(9),VY(9):FOR I=0 TO 8:READ VX(I),VY(I):NEXT I 144 DATA 0,0,0,-1,0,0,1,0,0,0,0,1,0,0,-1,0,0,0 150 LOCATE 0,0:FOR I=3 TO 1 STEP-1:PRINT I;:FOR J=0 TO 999:NEXT J,I:PRINT " START" 160 X=0:Y=10:TM=TIME 200 ' *** LOGIC *** 210 LOCATE X,Y:PRINT " ";:S=STICK(0):X=X+VX(S):Y=Y+VY(S):LOCATE X,Y:PRINT "A"; 220 IF X<32 GOTO 200 300 ' *** COMMON RESULT *** 310 LOCATE 0,1:PRINT "TIME="; TIME-TM 320 END
実行結果
比較結果
パターン4を含むと、以下の結果になりました。
パターン | 処理方法 | 処理時間 |
---|---|---|
1 | IF文のみ | 56 |
2 | ON〜GOTO〜 | 51 |
3 | 論理式 | 59 |
4 | 配列変数 | 43 |
配列変数が抜き出て速いですね。
パターン1や2にあるGOTOが無いのでこの結果になったのだと考えます。
BASICはインタプリタ言語なので、命令数が1つ増えただけでも処理速度に影響するというのは認識ありましたが、実際に結果を見ると相当違いますね。
なお、このテストでは、座標の上限値/下限値を1方向しか判定していないので、実際にゲームに組み込んだ場合の性能とは異なります。
あくまで指標として捉えていただけると幸いです。
【MSX】GitHubに置いた.dskファイルをWebMSXで実行する方法
今日書いたこちらの記事の補足です。
最初、WebMSXでGitHubに置いた.dskファイルを読めなかったので、フリーのWebサーバに.dskファイルを置いていたのですが、URLパラメタの指定方法を見直したらGitHubの.dskファイルでも実行できましたので、書いておきます。
具体的には、以下のように指定します。
https://webmsx.org/?MACHINE=MSX1J&DISKA_URL=<対象の.dskファイルのURL>&FAST_BOOT
「DISKA_URL」パラメタで与えるのがミソです。
なお、最後の「FAST_BOOT」は気持ち起動が速くなるようなので付けていますが、任意です。(この指定の仕方でいいのか自信がない…)
そして、この「DISKA_URL」に与える「対象の.dskファイルのURL」ですが、GitHubで対象の.dskファイルのページにある「Download」ボタンのURLになります。
このボタンを右クリックした「URLをコピー」することで取得したURLを指定してください。
他、多数のオプションを指定できますが、詳細は以下のGitHubリポジトリのドキュメントを参照してください。
ちなみに、使用する.dskファイルがあるリポジトリは、publicにしておいてくださいね。
ではでは。
【MSX】BLOCK BREAKER
唐突ですが、MSX-BASICの練習で、ブロック崩しゲームを作ってみました。
(ボールの挙動が若干怪しいのと、パドルの移動にイライラしますが…)
以下のURLで遊べます。
(※GitHubの.dskをWebMSXに直接渡せたので、URLを変更しました)
しばらく待って、タイトルが出たらSPACE or Aボタンでスタート。
カーソルキー or コントローラの左右でパドルを動かしてボールを落とさないようにして、ブロックを壊してください。
ボールを3回落とすとゲームオーバーです。
githubでもソースとディスクイメージ、某雑誌風のドキュメントを公開しています。 詳細については、こちらのドキュメントを参照してください。
このプログラムを元にアセンブラ化していきたいと思っていますが、小数点の計算をどうするかな…
ではでは。
【git】GithubにSSH接続する
Githubのリポジトリへのアクセスは、主にhttpsとSSHがある。
一度cloneするだけであればhttps接続で問題ないが、GitHubではSSH接続が推奨されており、アクセスするたびにユーザー名とアクセストークンを入力することも不要になるため、普段から利用するリポジトリへのアクセスはSSHが望ましい。
このSSHの設定方法については既に多数の記事が存在するが、ようやく自分の中で手法が固まったので、まとめ直したものを記載する。
0. SSHキー生成の準備
基本的に、1つの端末に1つ作成するイメージで良いと思う。
Windowsの場合は自分のホームディレクトリに.sshフォルダを作成後、スタートメニューからGit Bashを起動する。
Linuxの場合は、ホームディレクトリでそのまま作業を行う。
1. SSHキー生成コマンド
以下のコマンドを実行する。
$ ssh-keygen -t rsa -C <メールアドレス>
作成先のディレクトリの確認。
デフォルトで問題ないため、そのままEnter
を押す。
Enter file in which to save the key (/c/Users/hitoshi/.ssh/id_rsa):
作成先に既に作成されている場合は以下のメッセージが表示される。
上書きして良いならy
を入力する。
/c/Users/aburi/.ssh/id_rsa already exists. Overwrite (y/n)?
続いてパスフェーズの入力を求められる。
何も入力せずEnter
を入力する。
Enter passphrase (empty for no passphrase): Enter same passphrase again:
パスフェーズを設定するとVS Codeからのpush/pull操作が上手くいきませんでした。
回避方法があると思われますが、個人利用であれば未設定で構わないと思います。
以下のメッセージが表示され、公開鍵が生成される。
Your identification has been saved in /c/Users/hitoshi/.ssh/id_rsa. Your public key has been saved in /c/Users/hitoshi/.ssh/id_rsa.pub. The key fingerprint is: SHA256:<暗号化文字列> The key's randomart image is: +---[RSA 2048]----+ | +o*o | | . *.=. | | O o | | + = = | | .. * o S | |+..+ + = + | |==o . + = | |#... ..o.. | |@O ... E | +----[SHA256]-----+
後半のランダムアートの内容は、生成するごとに変わります。
2. 作成結果確認
.ssh
ディレクトリにid_rsa.pub
が存在していれば成功。
$ ll total 6 -rw-r--r-- 1 hitosh i 197121 1671 2月 3 01:51 id_rsa -rw-r--r-- 1 hitoshi 197121 401 2月 3 01:51 id_rsa.pub -rw-r--r-- 1 hitoshi 197121 405 2月 3 01:35 known_hosts
3. Githubに公開鍵を登録
生成した公開鍵の内容をコピーする。
id_rsa.pub
をテキストエディタで開き中身をコピーするか、以下でコンソールに出力したものをコピーする。
$ cat ~/.ssh/id_rsa.pub
$ clip < ~/.ssh/id_rsa.pub
githubのアカウントの「Settings」ページを開き、「SSH and GPG keys」を選択、「SSH keys」の右側にある「New SSH key」ボタンを押す。
名前は適当に、「<端末名>@<OS名>」のようにすると良いかもしれない。
4. GithubとのSSH接続確認
接続の確認は以下で行う。
$ ssh -T git@github.com
成功すると以下のメッセージが表示される。
Hi <ユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.
5. トラブルシューティング
失敗した場合は、以下を確認する。
1. そもそもネットワークに接続されているか。wifiや有線LANの接続を確認する。
2. Githubに登録したSSH公開鍵の内容。一度削除して登録しなおしてみる。
3. ssh公開鍵の作成内容。暗号化方式が誤っていないかなど。一度.ssh
ディレクトリ内のファイルを削除し、再度作り直してみる。