Communitygithub.com

JoshRodd/86Box-tool

86Box 虚拟机操作与调试工具集

86Box-tool 是什么?

本技能提供了一套完整的 86Box 虚拟机操作工具,支持虚拟机的启动、配置、等待、重启、调试和检查等全生命周期管理。它特别适用于需要精确控制虚拟机状态、进行底层调试(如 GDB 存根)或处理复杂 BIOS/NVRAM 配置的场景。 技能的核心功能包括:通过 `86boxctl.sh` 脚本进行标准启动与控制;通过 RSP 存根实现内存转储、屏幕捕获和文本 VRAM 监控;以及通过内存转储服务器实现无暂停的实时屏幕差量监控。支持的平台涵盖 macOS、Linux 和 Windows,并提供了独立的 ROM 克隆与校验机制,确保实验的隔离性和安全性。 该技能严格遵循一套非协商安全规则(如禁止使用泛化信号、必须验证 PID 等),特别适合在多虚拟环境共存或需要与大型语言模型交互的场景中使用。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add JoshRodd/86Box-tool

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

86Box 虚拟机操作

每当任务要求启动、配置、等待、重启、调试或检查 86Box 虚拟机时,请使用本技能。

不可协商的安全规则

  1. 在启动前确定精确的虚拟机目录。
  2. 使用 --vmpath <虚拟机目录> --vmname <显示名称> 启动。
  3. 记录启动后返回的 PID 以及稳定的工具进程名。
  4. 在发送任何信号前,使用可执行文件和精确的 --vmpath 验证 PID 身份。
  5. 禁止使用 killall、宽泛的 pkill、宽泛的 pgrep 或未经验证的 PID。
  6. 假设其他人正在运行独立的 86Box 进程。
  7. 当 NVRAM 或配置更改较为重要时,优先使用干净的 UI 关闭。
  8. 切勿为了单虚拟机实验而覆盖共享的 ROM;应克隆完整的 ROM 集,并使用 --rompath 选择克隆后的路径。

前置检查

  1. 在平台虚拟机根目录下解析一个名称。在 macOS 上:

    ~/Library/Application Support/86Box/Virtual Machines/<名称>
    

    直接指定虚拟机路径也是有效的。

  2. 读取 <虚拟机>/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 <虚拟机> command
    
  5. 如果调试多个虚拟机,要求在每份配置中设置不同的 gdbstub_port,并设置 cpu_use_dynarec = 0。

启动

独立控制器:

./86boxctl.sh <虚拟机> start
./86boxctl.sh <虚拟机> start --gdb-stub

打过补丁的 IBM PS/2 Model 80 Type 2 BIOS:

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

虚拟机必须使用 machine = ibmps2_m80。控制器会探测平台默认的 ROM 根目录,将完整的 ROM 树克隆到 <虚拟机>/romsets/ 下,将镜像拆分为活跃的偶数/奇数通道文件,进行验证,然后通过 --rompath 使用生成的根目录启动。当探测有歧义时,请使用 --rom-source。使用 prepare-roms 可在不启动的前提下构建 ROM 集。

对于通过工具进行长时间 GUI 会话的情况,请通过工具进程管理器启动可执行文件,格式如下:

name        = 唯一的稳定名称,例如 86box-automatic-configuration
application = 选择的 86Box 二进制文件
args        = [--vmpath, <绝对虚拟机目录>, --vmname, <显示名称>]
pty         = false
persist     = true  (当交互跨越多个回合时)

记录返回的 PID。后续的 describe、logs、restart 和 stop 操作只能使用该稳定的进程名。重启会产生新的 PID,请重新记录。

不要将 86box.cfg 作为唯一的定位参数传递。那样只能选择配置,但不会设置 86Box 的虚拟机用户文件路径,因此相对路径的介质、NVRAM 和本地 ROM 可能解析到错误的目录。

确认就绪

仅创建进程并不代表客户机已就绪。

  • 正常版本:要求该精确进程在启动后存活,然后检查可见的虚拟机或具体的虚拟机工件。
  • GDB 版本:要求该虚拟机配置的 RSP 端口处于监听状态。
  • 切勿将其他 86Box 进程或端口作为该虚拟机的就绪证据。

使用:

./86boxctl.sh <虚拟机> status
./86boxctl.sh <虚拟机> logs --lines 100

等待用户

当用户要求等待到工具中断时,请完全照做。除非用户明确要求做退出触发的工作,否则不要在虚拟机退出时继续执行。工具的任务等待器不会将托管的 GUI 进程视为后台任务,因此请创建一个长时间运行的有限异步等待哨兵,以无限的工具超时等待该任务,并在用户中断后取消它。

请使用稳定的进程名和 PID 分别跟踪虚拟机进程。

观察

宿主机生命周期

./86boxctl.sh <虚拟机> status
./86boxctl.sh <虚拟机> wait
./86boxctl.sh <虚拟机> logs --lines 100

客户机屏幕、控制台和内存

两个独立的路径:

  1. RSP 存根(需要 GDB-stub 版本;连接后会暂停客户机):

    RSP_PORT=<端口> ./rsp.py probe
    RSP_PORT=<端口> ./rsp.py video-mode
    RSP_PORT=<端口> ./rsp.py screen
    RSP_PORT=<端口> ./rsp.py wait-screen "期望文本" --wait-timeout 600
    RSP_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. Memdump 服务器(无 GDB 存根,不暂停 CPU):在虚拟机配置中设置 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=<端口> ./guest_console.py

# 可处理的屏幕和差量事件
RSP_PORT=<端口> ./guest_console.py \
  --format jsonl --no-input --duration 10

# 通过 BIOS 键盘环输入 DOS 命令
RSP_PORT=<端口> ./guest_console.py \
  --send "DIR" --enter --duration 10

# 早期 POST 需要硬件扫描码注入
RSP_PORT=<端口> ./guest_console.py \
  --input-mode hardware --key F1 --duration 5

控制台以 70 Hz 采样,保留完整的字符/属性缓冲区,仅输出合并后的变更运行。TTY 获得 ANSI 光标更新;重定向输出默认为 JSONL。输入在启动后默认为经过验证的 BIOS 键盘环。硬件模式通过模拟的 8042 注入速度化的 Set-1 扫描字节用于 POST。保留 Ctrl-] 用于分离,以便客户机的 Ctrl-C 保持可用。

切勿仅凭注入的按键就推断成功。必须观察所产生的屏幕差量或明确的客户机输出。

持久虚拟机配置

在干净关闭后,仅检查解析后的虚拟机目录:

<虚拟机>/86box.cfg
<虚拟机>/nvr/<machine>.nvr
<虚拟机>/nvr/<machine>_sec.nvr

对于此仓库:

uv run --project . refdisk-view-config --vm <名称> --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 可以回退到其他搜索根目录,但完整性可以使运行自包含,并防止静默混合。不要将其指向仅包含一台机器的目录。

对于原始的连续 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 <虚拟机> prepare-roms \
  --model-80-type-2-rom /path/to/sequential-128k.bin
./86boxctl.sh <虚拟机> 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-stub 功能的 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 <虚拟机> stop
./86boxctl.sh <虚拟机> restart

stop 仅向经过身份验证的 PID 发送 SIGTERM,并且不会静默强制终止它。仅在接受可能的 NVRAM 或配置丢失后使用 --kill-after-timeout。

发生崩溃时:

  1. 捕获 status 和 logs;
  2. 确认记录属于目标虚拟机;
  3. 仅重启该记录;
  4. 记录新的 PID;
  5. 返回到之前的等待或观察步骤。

完成证据

在报告成功之前,请提供与任务相符的证据:

  • 精确的虚拟机路径和机器标识符;
  • 二进制文件和精确的启动命令;
  • 稳定的进程名和当前 PID;
  • 就绪证据;
  • 干净退出或崩溃状态;
  • 相关的配置/NVRAM 路径和大小;
  • 客户机屏幕、寄存器、内存或解码后的配置输出。

关于实现细节、GDB 存根问题、ROM 查找和故障诊断,请参阅 README.md。

相关技能