Communitygithub.com

JoshRodd/86Box-tool

86Box 仮想マシンの起動、構成、監視、デバッグ、停止を行うためのツールです。

86Box-tool とは?

このスキルは、86Box エミュレータ上で仮想マシン(VM)を操作するための包括的なツールセットです。主な機能は、安全な VM 起動、GDB スタブを使ったゲストOSのデバッグ、シリアルコンソールや画面ダンプによるゲスト状態の監視、およびクリーンなシャットダウン制御です。対応プラットフォームは macOS(主)、Linux、Windows を含みます。特に重視されるのは非妥協の安全ルールで、複数VMの同時運用を前提に PID の厳密な検証を行い、killall や未検証の PID によるシグナル送信を禁止します。また、ROMセットの完全なクローン作成、モデル80 Type 2 BIOSの特殊なインターリーブ処理、メモリダンプサーバーによる非侵入的モニタリングなど、実践的なCPUエミュレーション研究や古いOS/ソフトウェアのテスト自動化に必要な高度な操作をサポートします。このスキルは、CI/CD パイプラインでの VM 操作や、複数のVMを同時に管理する開発環境での使用に適しています。

対応~Claude Code~Codex CLI✓Cursor
npx skills add JoshRodd/86Box-tool

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

86Box VM 操作スキル

このスキルは、86Box 仮想マシンの起動、設定、待機、再起動、デバッグ、検査が必要なタスクで使用します。

不可譲の安全ルール

  1. VM ディレクトリは起動前に必ず解決する。
  2. --vmpath <VMディレクトリ> --vmname <表示名> で起動する。
  3. 起動時に返される PID と、安定したハーネスプロセス名を記録する。
  4. シグナルを送る前に、実行ファイルと正確な --vmpath を使って PID の同一性を確認する。
  5. killall、ブロードな pkill、ブロードな pgrep、または未検証の PID を決して使用しない。
  6. 他の人が独立した 86Box プロセスを実行していることを想定する。
  7. NVRAM や設定の変更が重要な場合は、クリーンな UI シャットダウンを優先する。
  8. 1つの VM 実験のために共有 ROM を上書きしない。完全な ROM セットをクローンし、--rompath でそれを選択する。

事前準備

  1. プラットフォームの VM ルート下で名前を解決する。macOS の場合:

    ~/Library/Application Support/86Box/Virtual Machines/<NAME>
    

    直接 VM パスも有効。

  2. <VM>/86box.cfg を読み込む。以下を記録する:

    • machine
    • cpu_use_dynarec
    • オプションの gdbstub_port
    • 設定されたメディアおよびアダプタデバイス
  3. バイナリを選択する:

    • 通常操作: /Applications/86Box.app/Contents/MacOS/86Box
    • ゲストデバッグ: -DGDBSTUB=ON でローカルビルドしたもの
  4. コマンドを確認する(86Box-tool プロジェクトルートから実行するか、インストールする):

    cd ~/src/86Box-tool && uv run ./86boxctl.sh <VM> command
    
  5. 複数の VM をデバッグする場合、各設定で個別の gdbstub_port と cpu_use_dynarec = 0 が必要。

起動

スタンドアロンコントローラー:

./86boxctl.sh <VM> start
./86boxctl.sh <VM> start --gdb-stub

パッチ適用済み IBM PS/2 Model 80 Type 2 BIOS:

./86boxctl.sh <VM> command \
  --model-80-type-2-rom /path/to/sequential-128k.bin
./86boxctl.sh <VM> start \
  --model-80-type-2-rom /path/to/sequential-128k.bin

VM は machine = ibmps2_m80 を使用する必要があります。コントローラーはプラットフォームの標準 ROM ルートを検出し、完全なツリーを <VM>/romsets/ 下にクローンし、イメージをアクティブな偶数/奇数レーンファイルに分割し、検証して、生成されたルートを --rompath で起動します。検出が曖昧な場合は --rom-source を使用します。起動せずに ROM を準備するには prepare-roms を使用します。

長時間のハーネス仲介 GUI セッションの場合は、ハーネスプロセスマネージャー経由で実行ファイルを以下のように起動します:

name        = 86box-automatic-configuration のような一意で安定した名前
application = 選択した 86Box バイナリ
args        = [--vmpath, <絶対 VM ディレクトリ>, --vmname, <表示名>]
pty         = false
persist     = ターンまたぎで対話が必要な場合は true

返された PID を記録します。後続の describe、logs、restart、stop 操作にはその安定したプロセス名のみを使用します。再起動すると新しい PID が生成されるので、それを記録します。

86box.cfg を単独の位置引数として渡さないでください。それにより設定は選択されますが、86Box の VM ユーザーファイルパスが設定されないため、相対メディア、NVRAM、ローカル ROM が間違ったディレクトリに対して解決される可能性があります。

準備完了の確認

プロセス生成だけではゲストの準備完了とはなりません。

  • 通常ビルド: 正確なプロセスが起動を生き残ることを確認し、その後、可視の VM または具体的な VM アーティファクトを検査します。
  • GDB ビルド: この VM の設定された RSP ポートがリッスンしていることを要求します。
  • 別の 86Box プロセスやポートをこの VM の証拠として解釈しないでください。

以下を使用:

./86boxctl.sh <VM> status
./86boxctl.sh <VM> logs --lines 100

ユーザー待機

ユーザーがハーネス割り込みまで待機するよう指示した場合は、正確にそれを行います。ユーザーが終了トリガーの作業を要求しない限り、VM が終了しても進めません。ハーネスジョブウェイターは管理対象 GUI プロセスをバックグラウンドジョブとして扱わないため、長時間の有限非同期待機センチネルを作成し、そのジョブを無期限のハーネスタイムアウトで待機し、ユーザーの割り込み後にキャンセルします。

VM プロセスは、安定したプロセス名と PID で個別に追跡し続けます。

観測

ホストライフサイクル

./86boxctl.sh <VM> status
./86boxctl.sh <VM> wait
./86boxctl.sh <VM> logs --lines 100

ゲスト画面、コンソール、メモリ

2つの独立したパス:

  1. RSP スタブ(GDB スタブビルドが必要。接続するとゲストが一時停止します):

    RSP_PORT=<port> ./rsp.py probe
    RSP_PORT=<port> ./rsp.py video-mode
    RSP_PORT=<port> ./rsp.py screen
    RSP_PORT=<port> ./rsp.py wait-screen "expected text" --wait-timeout 600
    RSP_PORT=<port> ./rsp.py dump b8000 fa0
    

    テキストモード 0、1、2、3、7 では、screen は 40x25 または 80x25 を選択し、カラーは B8000h、モノクロは B0000h を使用し、アクティブビデオページに従います。グラフィックスモード 11h では、A0000h のパックされた 640x480 1bpp フレームバッファを読み取り、ゲストを再開し、ハーネスの設定された @vision モデルに生成された PNG を解釈するよう要求します。omp が PATH にある必要があります。プロンプトをカスタマイズするには --vision-question を使用します。スナップショットコマンドは検査のためにのみ一時停止し、モデル推論の前にデタッチします。

  2. メモリダンプサーバー(GDB スタブなし、CPU 一時停止なし): VM 設定で memdump_port を設定します。ライブデルタビューでテキストフレームバッファをポーリングします:

    ./screenmon.py --memdump-port 12348            # インタラクティブ TTY: ANSI デルタ
    ./screenmon.py --memdump-port 12348 --plain   # パイプ: 全フレーム + 変更行
    ./screenmon.py --memdump-port 12348 --count 30 --interval 0.1
    

    screenmon.py はポーリング間で変更された部分のみをレンダリングします。モードは isatty() によって選択されますが、--full/--plain で上書きできます。デフォルト間隔は 0.1 秒です。

連続双方向操作用:

# インタラクティブ ANSI ミラー; Ctrl-] でデタッチ
RSP_PORT=<port> ./guest_console.py

# 処理可能な画面およびデルタイベント
RSP_PORT=<port> ./guest_console.py \
  --format jsonl --no-input --duration 10

# BIOS リング経由で DOS コマンドを入力
RSP_PORT=<port> ./guest_console.py \
  --send "DIR" --enter --duration 10

# 初期 POST にはハードウェアスキャンコード注入が必要
RSP_PORT=<port> ./guest_console.py \
  --input-mode hardware --key F1 --duration 5

コンソールは 70 Hz でサンプリングし、完全な文字/属性バッファを保持し、結合された変更ランだけを出力します。TTY は ANSI カーソル更新を取得します。リダイレクトされた出力はデフォルトで JSONL になります。入力は、起動後に検証された BIOS キーボードリングをデフォルトとします。ハードウェアモードは、エミュレートされた 8042 を介してペース調整されたセット1スキャンバイトを POST に注入します。Ctrl-] をデタッチ用に残しておき、ゲストの Ctrl-C が使用可能になるようにします。

注入されたキーだけで成功を推測しないでください。結果の画面デルタまたは明示的なゲスト出力を観測してください。

永続的な VM 構成

クリーンシャットダウン後、解決された VM ディレクトリのみを検査します:

<VM>/86box.cfg
<VM>/nvr/<machine>.nvr
<VM>/nvr/<machine>_sec.nvr

このリポジトリでは:

uv run --project . refdisk-view-config --vm <NAME> --adf-source rf7080a/disk

86Box UI でカードを追加しても、それだけでゲストの MCA NVRAM が設定されるわけではありません。ゲストのリファレンスディスクが POS 状態を設定し、86Box がそれをクリーンに保存する必要があります。

ROM 検証

machine = ... が必要な ROM ファイル名を決定します。以下を確認:

  1. 86boxctl status が記録した正確な --rompath(存在する場合)
  2. 生成されたセットの .86boxctl-romset.json
  3. 86Box マシン定義からの正確なアクティブファイル名
  4. それらのアクティブファイルのハッシュまたはバイト比較

このワークフローでは、明示的な --rompath に完全な 86Box ROM セットが含まれている必要があります。86Box は他の検索ルートにフォールバックできますが、完全性により実行が自己完結し、サイレント混在を防ぎます。1つのマシンのみを含むディレクトリを指定しないでください。

生のシーケンシャル 128 KiB Model 80 Type 2 イメージの場合は、--model-80-type-2-rom を使用します。コントローラーは以下を書き込みます:

machines/ibmps2_m80/15f6637.bin = input[0::2]  # 低/偶数レーン
machines/ibmps2_m80/15f6639.bin = input[1::2]  # 高/奇数レーン

両方のファイルは 65,536 バイトです。それらをインタリーブすると入力が再現されます。start と restart は自動的に分離クローンを作成または検証します:

./86boxctl.sh <VM> prepare-roms \
  --model-80-type-2-rom /path/to/sequential-128k.bin
./86boxctl.sh <VM> status

デフォルトは標準の 86Box ROM ルートです: macOS では Application Support、Unix では XDG_DATA_HOME/XDG_DATA_DIRS、Windows では Local/Program/AppData。--rom-source PATH または 86BOX_ROM_ROOT で上書きします。--refresh-rom-set は認識された生成ディレクトリのみを再構築します。

.orig や .altered などのバックアップサフィックスは自動的に選択されません。共有オリジナルを保存してください。

実際の GDB スタブ対応 86Box プロセスを使用したエンドツーエンドの証明:

./model80_rom_smoke.py <MODEL80_VM>

machine = ibmps2_m80、cpu_use_dynarec = 0、および一意の gdbstub_port が必要です。ハーネスはストックレーンからシーケンシャルイメージを導出し、KB OK を OKBMR に変更し、64 KiB チェックサムを修復し、分離された完全な ROM クローン経由で起動し、ゲストテキスト VRAM で OKBMR を観測し、記録された PID のみを停止します。手動検査が必要な場合のみ --keep-running を使用します。

停止または復旧

クリーンな UI シャットダウンを優先し、追跡対象のプロセスが終了したことを確認します。制御が必要な場合:

./86boxctl.sh <VM> stop
./86boxctl.sh <VM> restart

stop は、同一性確認済み PID にのみ SIGTERM を送信し、サイレントに強制終了することはありません。--kill-after-timeout は、NVRAM または構成の損失を受け入れた後にのみ使用します。

クラッシュ時:

  1. status と logs をキャプチャする。
  2. レコードが対象の VM に属することを確認する。
  3. そのレコードのみを再起動する。
  4. 新しい PID を記録する。
  5. 以前の待機または観測ステップに戻る。

完了の証拠

成功を報告する前に、タスクに適した証拠を提供してください:

  • 正確な VM パスとマシン識別子
  • バイナリと正確な起動コマンド
  • 安定したプロセス名と現在の PID
  • 準備完了の証拠
  • クリーン終了またはクラッシュステータス
  • 関連する設定/NVRAM のパスとサイズ
  • ゲスト画面、レジスタ、メモリ、またはデコードされた設定出力

実装の詳細、GDB スタブの癖、ROM ルックアップ、障害診断については README.md を参照してください。

関連スキル