Boot cable


以下は,2003/6 頃に試行錯誤した際の記録です。
最新の情報はこちら
Back to Home

Mac 上で開発した GBA 用プログラムを実機で(GBAで)確認するには,プログラムを GBA に転送し,実行する必要がある。
普通なら,Flash メモリーカートリッジ等にプログラムを書き込んで,GBA  のカートリッジにさす必要があるところだが,GBA には,ROM カートリッジをさしていなくても,対戦ケーブル経由でプログラムを読み取り,実行する機能がある(PC等のネットワークブートに近いイメージ)。
つまり,わざわざプログラムを ROM に焼かなくても Mac から対戦ケーブル経由で GBA 用のプログラム転送して実行すればよいということになる。

最近の Mac の場合には,USB 接続が一番簡単なのは皆さんご存じの通り。
PC と GBA を USB で接続するケーブルは,いくつか存在しているようだが,Mac 用というのは見つからなかった。
私は,ケーブルの技術仕様,プログラムソースが公開されていて,しかも(日本の)オプティマイズが開発販売しているブートケーブル USB を使うのがよいと判断した。
(開発元で Mac に対応していなくても,Mac で使えるようにプログラムを書けば良いので。)

さらには,ブートケーブル USB 用の Linux 版転送プログラム(optusb)は,西田さんがすでに作成し,ソースと共に公開して いらっしゃる。
また,幸いにも optusb の前提ライブラリである libusb は,darwin にも対応している(自分で IOKit を使って USB ケーブルを制御するプログラムを書かずに済む!)ため,optusb は,Mac OS X に libusb をインストールしてからコンパイルするだけで簡単に動作する...はずだったがそうは行かなかった。

ここでは暫定的に,Mac OS X で optusb を使うために私が試行錯誤した過程と,darwin 版 optusb を公開する。
将来は,libusb (と optusb) が darwin 対応すると思われる。
darwin で libusb と optusb が普通に使えるようになった場合,以下の記述,プログラムは削除する予定である。

2003/06/22 現在の情報なので,これより時間が経っている場合には,以下に書いてある事を試すより,まずは最新の libusb (と optusb)が本当に簡単に利用できないのかどうか検証するのがよいだろう。

そのままでは動かなかった組み合わせは以下の通り。

libusb(その1)

最初,安定版の0.1.7を入手し,./configure; make したが,途中でコンパイルが止まった。
調べたところ,usb.h.in から,usb.h を生成する際,darwin では #if @LINUX_API@ が #if になってしまい,コンパイルエラーになっていた。(本来は #if 0 に展開されるべきである。)
きっと,configure 関連のファイルを修正すれば直るのだろうが,とにかく先に進みたいので,usb.h のほうを手で修正した。
今度は,コンパイルが成功したので,make install してみた。
prefix は特に指定していないので,/usr/local/lib と /usr/local/include にインストールされた。

optusb(その1)

エラー出力

libusb  と IOKit がリンクされるようにして,ビルドしてみた。すんなりできあがった。
しかし,実行すると Negotiation error! となってしまう。
しかたなく,ソースを見て,何が悪いか当たりをつけようとしたが, 複数の場所で「Negotiation error!」を出力するようになっており,エラーメッセージとエラー発生行の関係がわからなかった。
デバッガで追ってもよかったが,デバッグ時だけでなく,通常使用時でもこれではエラーの原因と対処方法がわかりにくいので,どの段階でエラーとなったの か,また,エラーコードは何だったのか出力するようにしてみた。

これだけでもまだ,エラーの要因がわからなかった。
libusb で何をやっていて,どのようなエラーが出ているかを知る方法がないか,libusb  のドキュメントを見たところ,usb_set_debug()  という関数があり,これでレベルを指定すれば,標準エラー出力に libusb  のエラー情報が出ることがわかった。
そこで,optusb にオプション引数を追加し,オプション指定時には,usb_set_debug() を使って詳細なトレースがとれるようにしてみた。

初期化

ブートケーブルのデバイスは見つけられているものの,usb_open() 後の usb_bulk_write() で失敗しているようだ。
WEB で他の libusb を使うプログラムを適当に探してみると,初期化処理として,usb_set_configuration(), usb_claim_interface() を呼ばなければならないように見えた。
ここで,いろいろ組み合わせてテストした結果,darwin  の場合,usb_set_configuration() だけを呼ばなければならないことがわかった。第2引数は 1 固定でもよさそうだが,WEB 上のマニュアルと libusb  付属の testlibusb プログラムを見たところ,デバイスの config 情報から指定すべき値が取れるように見えたので使うことにした。

libusb(その2)

どうしても,usb_bulk_write() がエラーになってしまう。
悩んだ挙げ句,libusb Version 0.1.7 の Linux 版と darwin 版でリターン値の仕様が異なっていることを見つけた。
Linux 版:成功時に書き込んだバイト数を返す。
darwin版:成功時に 0 を返す。
darwin版は,成功時に 0 を返すので,Linux 版 libusb を前提に作成した(optusbのような)プログラムでは,usb_bulk_write() 成功時の 0 を書き込みエラーとみなしてしまう。
libusb の CVS 履歴を見てみると,darwin の固有コードが記述されている darwin.c において,Linux 版(linux.c)に仕様を合わせる,という修正が入っていた。
最新版ソースを取得するべく,cvs コマンドを実行したが,うちの Firewall 設定が悪いからかうまく行かず,CVSWeb  からダウンロードしたり,日々バックアップされている CVS プロジェクトファイルをダウンロード&ローカルで co  したりして,なんとか最新版(開発版)のソースをそろえ,ビルドに成功した。

なお,最新版でも usb.h の生成がおかしい問題は修正されていないので,usb.h 中の問題の個所は,手で #if 0 に修正している。

optusb(その2)

エンディアン

libusb はうまくビルドできたようなので,早速コマンドを再作成して試してみるも,まだエラーになる。
コマンドのログ出力を見てみると,どうも,optusb の read_magic() のリターン値が変になっているように見えた(いわゆる「エンディアン」が反転しているように見えた)。
optusb が参考にしていると思われる btcons_usb コマンドのソース(piohost.c)を見てみると,magic 送信時はビッグエンディアン,結果受信時はリトルエン ディアンとなっているようにみえる。optusb も,x86 版 Linux を前提としているようで,結果受信部分は,リトルエンディアンな環境でないと動作しないようになっている。
Mac OS X は,ビッグエンディアンを採用しているので,magic の送受信部分を修正し,エンディアン独立コードにした。

後処理

上記のように試行錯誤していると,最初の1回はかなりのところまで動作しても,2回目はほとんど動作せず,通信の最初の段階でタイムアウトエラーになる, といった感じで動作が不安定だった。
一回,USB コネクタを抜き差ししてやれば,安定した。
どうも,エラー発生時に後処理が足りないように見えたので,エラー発生時は明示的に usb_close() してやることにした。これで少し安定したように思う。

まとめ

libusb

optusb

ダウンロード

optusb 1.0 に darwin パッチを当てたもの + libusb 開発版のバイナリ:
optusb-1.0darwin.tar.gz

libusb 開発版(2003/06/21版)のソース(libusb から再コンパイルしたい人用):
libusb-current.tar.gz

参考リンク


Copyright (C) 2003 by gbcube