月別アーカイブ: 2021年6月

光速船 Vectrex(3)PiTrex プログラミングのデバッグ

引き続き Raspberry Pi を使った PiTrex プログラムの作成方法について検討します。今回はベアメタル環境でデバッグプリントを表示する方法を調べました。

ベアメタル環境でのエラー

前回の投稿で、ベアメタル版 hello.img をインストールする際に次の手順が含まれていました。

2. /boot/settings ディレクトリを作成します。
sudo mkdir /boot/settings

/boot/settings ディレクトリはベアメタル版バイナリの実行に必須ですが、Makefile では作成されないため手動で作成する必要があります [注]。当初私はこれに気づかなかったため、/boot/settgings ディレクトリがない状態で hello.img プログラムを起動して Vectrex 画面に次のようなエラーメッセージを出していました。

このエラーメッセージは十分な情報を与えてくれないので原因を絞り込めません。さらに悪いことに、この画面でプログラムが停止してしまいます。ベアメタル環境では OS に戻ってあれこれ調べるというわけにもいかず、電源を切る以外にできることはありません。

ひとまず SD カードを PC に接続して /boot/config.txt の設定をベアメタル環境から OS 起動環境に戻しました。Raspberry Pi OS を起動して pitrex リポジトリ全体で文字列 “NO DIRECTORY” を検索したところ、pitrex/vectrex/osWrapper.c に次の記述が見つかりました。

問題のエラーはカレントディレクトリの変更中に発生していることがわかります。行番号 398 の
v_error("NO DIRECTORY");
が Vectrex 画面にエラーメッセージを表示しているようです。その上の行(行番号 397)に
printf("NO %s directory found...!\r\n", _dir);
という記述があります。これはいわゆるデバッグプリントで、移動先ディレクトリ名を表示しています。このデバッグプリントを読んで問題となるディレクトリ名を確定したいところですが、残念ながら printf() 関数は Vectrex 画面へは出力されません。printf() の出力は標準出力、つまり Raspberry Pi のコンソールに対する出力になりますが、ベアメタル環境では ssh 端末や HDMI モニタは使えません。OS が走っていないので、特に配慮しなければ Wifi もディスプレイコントローラも初期化されないためです。

シリアルコンソールの追加

実はベアメタル環境でもシリアルインターフェイスだけは初期化されており、printf() 出力は Raspberry Pi Zero W の GPIO UART ピンに出ます。詳細は PiTrex baremetal の作者 Malban 氏の blog で説明されています。UART ピンの設定は
GPIO Header pin8 : TX
GPIO Header pin10 : RX
GPIO Header pin 9 : Gnd
となっており、printf() の内容は RX ピンにシリアル信号として出力されます。

これらの GPIO ピンに USB シリアル変換モジュールを繋げば PC 上の端末ソフトウェアで printf() 関数によるデバッグ出力を確認できます。USB シリアル変換モジュールは Raspberry Pi GPIO 対応のもの、つまり 3.3V レベルのシリアル接続ができるモジュールを選択します。以下のように接続します。
GPIO pin8 (TX) : USB Serial RX
GPIO pin10 (RX) : USB Serial TX
GPIO pin9 Gnd : USB Serial Gnd

RX と TX はクロス接続します。これはコンピュータ同士をシリアル接続する際の要点です。実態は次の写真のような感じになります。

Raspberry PI GPIO シリアルピンの接続
Vectrex/Pitrex に接続したところ

USB ケーブルの他方の端は PC の USB 端子に接続します。

Malban 氏の blog によるとシリアルコンソールの通信速度は 115200 bps ですので、これに準じて PC のシリアル通信ソフトを設定、起動します。例えば Mac の場合はターミナルウィンドウで次のコマンドを実行します。

screen /dev/tty.usbserial-00000000 115200

usbserial-00000000” の部分は使用する USB シリアル変換モジュールによって異なります。

デバッグプリントの確認

以上でデバッグプリントを PC で受信する準備が整ったので、再度 hello.img をベアメタル環境で起動します。Vectrex の電源を入れると前掲のエラー画面で停止しますが、同時に Mac 上のターミナルウィンドウに次の内容が出力されます。

メッセージ中の次の行
NO settings directory found...!
が、前述の pitrex/vectrex/osWrapper.c ファイル内の printf() 関数によるデバッグプリントです。つまり失敗した移動先ディレクトリの名前が ‘settings’ であることがわかります。

残念ながらディレクトリのフルパスはここでは表示されません。しかし実行元プログラムである hello.img は /boot/ ディレクトリにありますから、プログラム実行中に作業ディレクトリを移動していなければ期待されるフルパスは /boot/settings です。

Vectrex の電源を切り、Raspberry Pi Zero W から SD カードを抜き出して PC にセットします。boot ディレクトリがマウントされるので、その中に settings ディレクトリを作成します。

SD カードを Raspberry Pi Zero W に戻して Vectrex の電源を入れると、hello.img プログラムが正しく実行されるようになりました。

同じ hello_world プロジェクトを Raspberry Pi OS 環境でビルドした場合は hello_world ディレクトリに hello バイナリが作成されます。hello_world/settings ディレクトリはリポジトリ内に最初から用意されているので、hello バイナリを実行しても ”NO DIRECTORY” エラーは発生しません。つまり settings ディレクトリの欠落はベアメタル環境特有の問題であるため、シリアルコンソールを接続してベアメタル環境でデバッグプリントを確認しない限り見つけるのは困難だったと思われます。

注:あとから調べたところ pitrex-config.sh を実行すると /boot/settings ディレクトリが作成されるようです。

光速船 Vectrex(2)PiTrex の開発環境

前回は光速船 Vectrex に Raspberry Pi と PiTrex を接続して PiTrex baremetal ソフトウェアを実行しました。今回は PiTrex の開発環境について書きます。

PiTrex プログラミングでは、次の 2 つの実行環境がターゲットになります。

  1. Raspberry Pi OS 環境:Raspberry Pi OS をインストールし、OS から PiTrex プログラムを起動する
  2. ベアメタル環境:Raspberry Pi の SD カードから直接 PiTrex プログラムを実行する

どちらもプログラミングは Raspberry Pi OS 上で行えますが、使用するコンパイラが異なります。以下では Raspberry Pi 上の 2 種類の開発環境を実際に使ってみた様子について説明します。

環境構築(1)Raspberry Pi OS 環境

PiTrex の Raspberry Pi OS 開発環境をインストールして、その上で開発から実行まで行う方法です。今回は Headless 設定を使い、Raspberry Pi Zero W にはキーボード、モニタ、電源アダプタなどを一切接続しません。この場合電源は Vectrex から供給されます。また Wifi/ssh を介して PC(Linux/Win/MacOS)から Raspberry Pi OS のコンソールに接続します。

まず Raspberry Pi OS をインストールしてから必要な設定に進みます。

Raspberry Pi OS のインストール

Raspberry Pi での一般的な手順通りです。

  1. SD カードを PC に接続します。
  2. Raspberry Pi Imager を PC(Linux/Win/MacOS)にインストールして実行します。
  3. Raspberry Pi Imager ウィンドウの「Operating System」をクリックして「Raspberry Pi OS (other)」を選択、さらに「Raspberry Pi OS Lite (32-bit)」を選択します。インストール先として SD カードを指定し、 Raspberry Pi OS Lite をインストールします。

従来通り OS イメージを手動でダウンロードして SD カードに書き込む方法でもかまいません。

前回の投稿で紹介した方法で Raspberry Pi OS をインストールしてから PiTrex baremetal を上書きしている場合は上記の手順を省略できますが、その代わりにバックアップしておいた内容を boot パーティションに書き戻します。

この時点ではまだ SD カードを Raspberry Pi Zero W にセットしません。

Headless 設定

Wifi 経由で Raspberry Pi OS にログインするための Headless 設定を行います。次の手順で進めます。

  1. SD カードを PC に接続します。カード内の boot パーティションが見えます。
  2. boot/wpa_supplicant.conf ファイルを新規作成しテキストエディタで編集します。このファイルに Wifi 接続先のパラメータを指定します。詳細はこの記事にわかりやすく説明されています。
  3. 空の boot/ssh ファイルを作成します。
  4. PiTrex プロジェクトリポジトリ Readme に従い、boot/config.txt に次の行を追加します。
gpio=0-5,16-24,26-29=ip
gpio=6-13,25=op
gpio=24=np
dtoverlay=dwc2,dr_mode=host

以上を完了したら SD カードを PC からアンマウントして、Raspberry Pi Zero W にセットします。

ログインと開発環境のダウンロード

ここまでの手順で、Headless 設定を含む Raspberry Pi OS が書き込まれた SD カード、Raspberry Pi Zero W、および PiTrex が一体となったボードが Vectrex のカードスロットにセットされている事になります。ここからは PC(Linux/Win/MacOS)から Wifi と ssh 経由で Raspberry Pi にアクセスします。

  1. Vectrex の電源をオンにします。画面には何も表示されません。Raspberry Pi 表面の緑 LED が点滅し(ボードが裏向きなので確認しにくいですが)、SD カードにアクセスしながら Raspberry Pi OS がブートするのがわかります。
  2. 1 分前後でブートが完了しますがコンソールがないのではっきりとは確認できません。LED の点滅具合を見ながら適当な時間待機して、同じ Wifi に接続している PC の端末ウィンドウから次のコマンドで Raspberry Pi にログインします。
    ssh pi@raspberrypi.local
    password: (デフォルトパスワード "raspberry" を入力)
  3. ログインに成功し raspberrypi のプロンプトが表示されたらまず安全のためデフォルトパスワードを変更します。
  4. git パッケージをインストールします。
    sudo apt-get install -y git
    必要に応じて git の環境設定を行います(必須ではありません)。
  5. pitrex プロジェクトリポジトリをクローンします。
    git clone https://github.com/gtoal/pitrex.git

以上で開発環境の準備が完了します。

hello_world のビルド

次に例として、開発環境に含まれるサンプルプログラム hello_world をビルドします。

  1. hello_world ディレクトリへ移動します。
    cd ~/pitrex/hello_world/
  2. Raspberry Pi OS 環境用の Makefile.raspbian を指定してビルドします。
    make -f Makefile.raspbian
    初回はコア機能を実装する他ディレクトリ(piTrexBoot, pitrex)の内容も含めてコンパイルするのでしばらくかかります。成功すると終了時に次のメッセージが表示されます。
    All up to date
  3. ビルドされた hello コマンドを実行します。
    sudo ./hello
  4. Vectrex 画面に次の内容が表示されます(画面を斜め上から撮影しています)。

コードの内容を確認します。hello.c をエディタで開くと次のような処理をしていることがわかります。

  • 関数 startFrame(), main() が定義されています。
  • main() 関数では最初の数行で初期化を行います。v_setname() は文字列表示ではなくプログラムの ID を定義する関数です。
  • 具体的な描画は for(;;) ループ内で行なっています。最初にループ毎の定期処理ルーチン startFrame() を呼び出します。
  • その後、具体的な描画を行なっています。
    • v_directDraw32() は線分の描画を行います。
    • v_printString() はベクタフォントによる英数文字列を表示します。
    • v_printStringRaster() はラスタフォントによる英数文字列を表示します。

このページに vectrexInterface ライブラリのリファレンスがあります。

プログラムを終了するには Vectrex コントローラ 1 の 4 個のボタンを同時押しするか、hello コマンドを実行した ssh 端末で Ctrl-C を押します。

電源を切る前に Raspberry Pi OS をシャットダウンします。
sudo shutdown -h now
コマンドを入力したらシステムが終了するまで数十秒待ち(ssh が切断された後も待つ)、それから Vectrex の電源を切ります。

環境構築(2)ベアメタル用バイナリの開発

pitrex リポジトリにはベアメタル用バイナリをビルドするための Makefile.baremetal が用意されています。ここでは主に hello_world ディレクトリをビルドする方法を説明します。

必要パッケージのインストール

gcc-arm-none-eabi(ベアメタル環境向けの arm gcc)その他必要なパッケージをインストールします。

sudo apt-get update
sudo apt-get install -y gcc-arm-none-eabi libsdl2-dev libsdl2-2.0 libsdl2-mixer-2.0-0 libsdl2-mixer-dev alsa-oss locate

ベアメタル版 hello_world のビルドとインストール

ベアメタル対応の Makefile.baremetal を使って hello_world ディレクトリをビルドします。

cd ~/pitrex/hello_world
make -f Makefile.baremetal

ビルドが完了すると hello.img というファイルができます。このファイルは Raspberry Pi OS の kernel.img と同じ方法で起動できます。次の手順でインストールします。

  1. hello.img ファイルを /boot/ ディレクトリにコピーします。
    sudo cp hello.img /boot/
  2. /boot/settings ディレクトリを作成します。
    sudo mkdir /boot/settings
  3. /boot/config.txt に次の 1 行を追加します。
kernel=hello.img

なお、Raspberry Pi OS で /boot 下のファイルを編集するときは sudo コマンドで権限を上げます。例:sudo vi /boot/config.txt

この後、Raspberry Pi OS を再起動(sudo reboot)すると hello.img プログラムが起動します。

ただしこの起動方法には問題点が一つあり、電源を再投入するとすぐ hello.img が立ち上がるので Raspberry Pi OS に戻ることができません。戻るには電源オフののち SD カードを PC に接続して、/boot/config.txt ファイルの kernel=hello.img 行を削除またはコメントアウトします。この方法はビルドのたびに SD カードを差し替える必要があり面倒です。

解決策として、pitrex/Makefile.baremetal ファイルおよび pitrex/Makefile.baremetal-install ファイルを使用してプロジェクト全体をビルド、インストールすることで pitrex.img が起動イメージとして実行されメニューが使えるようになります。メニューで「HELLO」を選ぶと hello.img が実行され、「RASPBIAN」を選ぶと Raspberry Pi OS を起動できます。ただし現状では pitrex/Makefile.baremetal でビルドすると一部のゲームディレクトリがエラーで止まってしまうので、エラーの出るディレクトリを Makefile から除外する等の回避処置が必要です。

参考

光速船 Vectrex: PiTrex のセットアップ

光速船 Vectrex は 1982 年発売の家庭用ゲーム機です。ベクタスキャン方式の内蔵モノクロモニタが最大の特徴でした。

日本では 1983 年発売、定価は 5 万円超で同時代の他機種と比べると随分高価だったという印象です。本機に関しては内蔵モニタのコストを差し引いて比較するべきかもしれませんが、まあしかし当時の為替相場は 1 ドル 240 円前後でしたから輸入モデルはいずれも高めの価格設定でした。光速船は業務用としての展開も考えられており、タイマ式コイン装置(時間が来ると問答無用でゲーム終了になる)が追加できるようになっていました。おもちゃ屋の店頭で 15 分 50 円程度で遊んだ記憶があります。

Vectrex はプロセッサとして 1.5MHz 68A09 を使用しており、6522 VIA と D/A コンバータを介してベクタスキャンモニタの X/Y スイープと輝度値 Z を制御する比較的シンプルなシステム構成です。CPU 自体が定期的に画面を再描画する必要があり、処理速度とメモリ容量の制限もあって画面オブジェクトの描画には直線が多用されます。ベクタスキャンの性質上、線が密集している領域は他の部分と比べて輝度が若干上がって見えます。

これらはソフトウェア作成上の制約ではありますが、ベクタスキャン画像に独特のタッチが加わる効果もあります。こういった性質を熟知した長年のユーザの中には独自にプログラムを書く方々もいて、近年に至っても新作ゲームやデモが公開されています。

* * *

Vectrex のカートリッジスロットに Raspberry Pi Zero W を接続するボードが PiTrex です。ベクタスキャンモニタのほか、コントローラやサウンドなど本体内の I/O デバイスすべてが Raspberry Pi から直接制御できます。Vectrex のカートリッジスロットには CPU バスが直接出ているので、HALT ピンをアサートして本体の 6809 を止めてしまい(6809 とバスは Hi-Z で切り離される)Raspberry Pi の GPIO 信号をバスに接続してシステム全体を乗っ取る仕組みだそうです。Vectrex ではモニタ制御回路含めほぼすべての I/O が 6522 VIA に接続されているので、Raspberry Pi の主な処理は 6522 の制御です。

今回 PiTrex 開発元が組み立て済み基板を生産販売するということで、販売サイトの説明に従ってメールアドレスを登録しました。しばらくすると「5/14 に次のバッチの頒布を開始するよ」というメールが送られてきたので指定の時刻にサイトへアクセスして 1 個注文しました。受付開始から数時間内に品切れになったようで、数はそれほど出ていないのでしょう。当面はこのペースで生産・頒布されると思われます。

注文後 10 日ほどでオーストラリアから PiTrex 基板が送られてきました。Vectrex 本体は、数年前に入手して保守点検ののちしまいこんであったものを出しました。この他に Raspberry Pi Zero W とピンヘッダ、SD カードが必要です。

本投稿の残りでは PiTrex の組み立てと接続の様子を説明します。また、PiTrex 説明書で推奨されている PiTrex baremetal ソフトウェアをインストールしてみます。

1. PiTrex の組み立てと接続

PiTrex キットには PiTrex 本体基板(部品はんだ付け済み)と レターサイズ 1 枚の説明書が含まれています。これ以外に次のものが必要です。

  • RaspBerry Pi Zero W
  • Zero W GPIO 用ピンヘッダ(20×2)
  • SD メモリカード

まず Raspberry Pi Zero W に GPIO 用ピンヘッダをはんだ付けします。部品面にピンを立てる方向で取り付けます。最初からピンヘッダが装着されている Raspberry Pi Zero WH を使うという方法もあります。

PiTrex 基板の部品面を確認し、電源供給用のジャンパブロックは接続したままにしておきます。こうすると Vectrex 本体から Raspberry Pi へ電源が供給されます。PiTrex 基板上の 5V 電源ジャック(付いてないモデルもある)は使用しません。ただし Vectrex の電源供給能力は限られているので、この場合 Raspberry Pi に外部デバイス(キーボード、USB ハブ、外部ストレージなど)は繋がずヘッドレスで使用します。

Raspberry Pi と PiTrex 基板を接続します。2 つの基板の部品面が向かい合う形になります。ピンヘッダとコネクタがずれていないことを確認します。

次に Vectrex 本体のカートリッジスロットへ PiTrex を接続します。Raspberry Pi Zero 基板が上、PiTrex 基板が下になる方向で挿入します。

この時点では Raspberry Pi に SD カードを挿入していないので、電源を入れても何も起きません。

2. Pitrex baremetal の実行

PiTrex の使用環境は大きく分けて 2 種類あります。

  1. Raspberry Pi の SD カードから直接 PiTrex プログラムを実行する(ベアメタル環境)
  2. Raspberry Pi の SD カードに Raspberry Pi OS をインストールし、OS 上で各種 PiTrex プログラムを起動する(Raspberry Pi OS 環境)

このうちベアメタル環境で実行するプログラムとして現在最も充実しているのは Vide Malban 氏による PiTrex baremetal です。カートリッジやエミュレータのイメージの起動もサポートされています。

以下、PiTrex baremetal のインストールを実際に行った結果をもとに手順を説明します。といっても詳しい手順は配布元ページに説明されているので、ここでは後々 Raspberry Pi OS 環境を使用することも考慮した方法についてまとめます。

  1. SD カードのフォーマットを行います。今回は Raspberry Pi OS 環境と併用することを考慮し、Raspberry Pi Imager を使ってフォーマットと OS のインストールを行います。インストールする OS として Raspberry Pi OS Lite を指定します。
  2. SD カードを PC(macOS/Win/Linux)に再セットします。boot ボリュームがマウントされます。この時点で、boot ボリューム内の全ファイルをバックアップしておきます。
  3. PiTrex baremetal 配布元ページから SD_Drive_<日付>.zip をダウンロードします(ページ内の緑のボタンをクリック)。zip を展開して得られる内容を boot ボリュームにコピーします。
  4. boot ディレクトリに含まれる boot/config.txt の内容を確認します。このファイルには以下の行が含まれており、Raspberry Pi 起動時に自動的に pitrex.img が起動します。
    kernel=pitrex.img
  5. SD カードを PC からアンマウントし、Raspberry Pi にセットします。

PiTrex と Raspberri Pi Zero W を前項の説明通り Vectrex にセットし、Vectrex の電源を入れると PiTrex baremetal ソフトウェアが立ち上がります。

カートリッジ bin イメージを追加しなくても起動画面、Movies デモ、オリジナルゲーム等で PiTrex の性能を確認できます。特に起動画面(下の動画参照)の 3D ロゴアニメーションは高速かつスムーズな動きで、Raspberry Pi の GPIO による制御がオリジナルの 68A09 MPU の処理速度を凌駕していることがわかります。

PiTrex baremetal には結構深いメニュー階層があり、Vectrex コントローラのジョイスティックでナビゲートできます。Movies カテゴリから “Bad Apple” が選べますが再生してみると描画の座標ずれがやや目立ちます。キャラクターやリンゴ、ナイフ等がアウトライン描画でスムーズに動くのですが、描画が細かい、つまりアウトラインを構成する線分の数が多いせいか始点と終点が常にずれており一筆書きが閉じません。このずれを調節するための設定があるようなのですが、具体的にどのパラメータを動かせばいいのかよくわかりません。Github リポジトリ Readme の “Known Issues” の項に「ベアメタルでは Calibrate プログラムが動かない」と書いてあるので、現状では調節が効かないのかもしれません。

また Movies と Music カテゴリのデモはいずれも音声出力レベルが極端に低いようです。ボリュームつまみを最大にしてかろうじて聞き取れるレベルなのですが、これは他の方の動画を見ても同様だったので機能仕様上の問題かと思われます。

* * *

以上で、とりあえず PiTrex 添付マニュアルでできるところまで進めました。この先は次の 2 通りの方向が考えられます。

  1. カートリッジやエミュレータのイメージファイルをインストール、設定して実行する
  2. Raspberry Pi 上のプログラミング環境を利用して Vectrex を制御する

エミュレータ方面の作業はアーケード機、特にベクタスキャン機の知識が必要とされるようで私にはちょっと歯が立ちません。次回は 2. のプログラミング環境について探ろうと思います。

参考