Amiga DevBench——架构与参考指南
Commodore Amiga(68k)的跨开发环境,连接现代 通过串行将主机连接到模拟(或真实)Amiga, 内存检查、变量编辑、远程执行和完整的MCP集成 克劳德代码。
______________________________________________________________________
目录
______________________________________________________________________
概述
传统的Amiga开发是痛苦的:目标上没有源代码级调试器, 库存机器上没有网络堆栈,崩溃会导致整个操作系统崩溃。这 该项目通过弥合现代开发主机与 Amiga通过串行链路。
它能够实现:
- 在macOS上编写C代码,通过Docker交叉编译,在一个命令中部署到模拟器
- 实时检查正在运行的Amiga上的内存、寄存器、任务、库和卷
- 在Amiga应用程序中注册变量,并从主机实时读/写它们
- 定义“钩子”——主机可以远程调用正在运行的应用程序的函数
- 从主机启动、停止和中断Amiga程序
- 从主机在Amiga上执行任意AmigaDOS脚本
- 在Amiga文件系统上读写文件
- 源代码级调试器 --设置断点、介入/跳过、检查寄存器和调用堆栈
- 通过web仪表板或Claude Code MCP工具监控一切
- 在不接触Amiga的情况下管理文件、分配、处理和保护位
- 使用CRC32校验和、尾部日志文件实时验证部署
- 全流程生命周期:启动、跟踪、发出信号和停止异步流程
在我们继续之前。这个工具的目的是让令人惊叹的amiga社区通过人工智能变得富有成效。这是我在一个下午一起玩过的一些游戏的截图。它们被列为例子,截至出版时都很糟糕。继续让他们变得更好:
青蛙弗兰克
入侵
月亮kindalookaround
PacBro img_3.png
graph LR
subgraph Host ["Host Machine (macOS)"]
CC[Claude Code] -->|MCP Protocol| DB[amiga-devbench
Python Server]
Browser[Web Browser] -->|HTTP/SSE| DB
Docker[Docker
Cross-Compiler] -->|m68k binaries| Deploy[Deploy to
Shared Folder]
end
subgraph Amiga ["Amiga (FS-UAE Emulator)"]
Bridge[amiga-bridge
Daemon] -->|MsgPort IPC| App1[App 1
bouncing_ball]
Bridge -->|MsgPort IPC| App2[App 2
system_monitor]
Bridge -->|serial.device| Serial[Serial Port]
end
DB -->|Serial over TCP/PTY| Serial
Deploy -->|Shared Folder
DH2:Dev/| Bridge______________________________________________________________________
系统架构
高级数据流
sequenceDiagram
participant CC as Claude Code
participant MCP as MCP Server
participant WEB as Web API
participant SER as Serial Connection
participant BRG as amiga-bridge (Amiga)
participant APP as Client App (Amiga)
CC->>MCP: amiga_ping()
MCP->>SER: send("PING")
SER->>BRG: PING\n
BRG->>SER: PONG|2|1649344|6459000\n
SER->>MCP: event("pong", data)
MCP->>CC: "Amiga alive - clients: 2"
Note over BRG,APP: IPC via Exec MsgPort
CC->>MCP: amiga_get_var("ball_speed")
MCP->>SER: GETVAR|ball_speed
BRG->>APP: ABMSG_VAR_GET (IPC)
APP->>BRG: reply with value
BRG->>SER: VAR|ball_speed|i32|10
SER->>MCP: event("var", data)
MCP->>CC: "ball_speed = 10"组件层
graph TB
subgraph "Layer 4 — User Interfaces"
CC[Claude Code
MCP Client]
WEB[Web Dashboard
localhost:3000]
end
subgraph "Layer 3 — Host Server"
MCP_TOOLS[MCP Tools
45+ tools]
WEB_API[Web API
80+ endpoints]
SSE[SSE Event Stream]
BUILDER[Builder
Docker wrapper]
DEPLOYER[Deployer
Shared folder copy]
end
subgraph "Layer 2 — Transport"
PROTO[Protocol Parser
Line-based, pipe-delimited]
SERIAL[Serial Connection
TCP or PTY mode]
EVENTBUS[EventBus
Async pub/sub]
STATE[AmigaState
In-memory cache]
end
subgraph "Layer 1 — Amiga Side"
DAEMON[amiga-bridge daemon
Owns serial.device]
IPC[IPC Manager
MsgPort message routing]
SYSINFO[System Inspector
Tasks, libs, memory]
FS[Filesystem Access
Read, write, list]
PROC[Process Launcher
Launch, break, stop]
CLIENT_REG[Client Registry
Track connected apps]
end
subgraph "Layer 0 — Client Apps"
LIB[libbridge.a
Client library]
APP1[hello_world]
APP2[bouncing_ball]
APP3[system_monitor]
end
CC --> MCP_TOOLS
WEB --> WEB_API
WEB --> SSE
MCP_TOOLS --> EVENTBUS
WEB_API --> EVENTBUS
SSE --> EVENTBUS
MCP_TOOLS --> SERIAL
WEB_API --> SERIAL
EVENTBUS --> STATE
SERIAL --> PROTO
PROTO --> DAEMON
DAEMON --> IPC
DAEMON --> SYSINFO
DAEMON --> FS
DAEMON --> PROC
DAEMON --> CLIENT_REG
IPC --> LIB
LIB --> APP1
LIB --> APP2
LIB --> APP3Amiga侧IPC架构
graph LR
subgraph "amiga-bridge daemon"
MAIN[Main Loop
Wait on signals] --> SER_IO[Serial I/O
Async read/write]
MAIN --> IPC_MGR[IPC Manager
AMIGABRIDGE port]
MAIN --> WIN[Status Window
Diagnostic output]
end
subgraph "Client App 1"
C1[ab_init] -->|FindPort| IPC_MGR
C1_LOG[ab_log] -->|PutMsg| IPC_MGR
C1_VAR[ab_push_var] -->|PutMsg| IPC_MGR
C1_POLL[ab_poll] -->|GetMsg| IPC_MGR
end
subgraph "Client App 2"
C2[ab_init] -->|FindPort| IPC_MGR
end
SER_IO -->|serial.device| SERIAL_HW[Serial Port
TCP/PTY to Host]
style MAIN fill:#e07020,color:#fff
style SER_IO fill:#4a90d9,color:#fff
style IPC_MGR fill:#44cc44,color:#000守护进程独占串行端口。客户端应用程序从不接触串行-- 它们通过AmigaOS MsgPort IPC进行通信(FindPort("AMIGABRIDGE") + PutMsg/GetMsg).
______________________________________________________________________
组件深潜
阿米加大桥(阿米加大门)
阿米加队的核心。一个单一的过程:
- 打开serial.device 使用异步I/O(SendIO/CheckIO)进行非阻塞读取
- 创建消息端口“AMIGABRIDGE” 用于客户端应用程序注册
- 运行Wait()循环 串行+IPC+窗口信号
- 路由消息 串行(主机)和IPC(客户端应用程序)之间
- 提供系统检查 无需客户端应用程序(任务列表、内存等)
| 源文件 | 责任 |
|---|---|
main.c | 事件循环、状态窗口、信号处理 |
serial_io.c | serial.device打开/关闭,异步读/写 |
ipc_manager.c | MsgPort创建、消息路由 |
client_registry.c | 按名称/ID跟踪活动客户端 |
protocol_handler.c | 解析主机命令,格式化响应(约1400行) |
system_inspector.c | 任务/库/设备/卷列表,内存检查 |
fs_access.c | 目录列表、文件读/写、重命名、复制、保护、注释、校验和(CRC32)、追加 |
process_launcher.c | 启动进程(异步)、路径验证、CTRL-C、进程跟踪(最多16个)、信号传递 |
关键设计决策:
- 所有大型缓冲区
static为了避免4KB的默认堆栈溢出 - 用途
Forbid()/Permit()用于任务列表迭代(最小关键部分) - 用于内存检查的易失性逐字节读取(对于某些区域,CopyMem在FS-UAE中返回零)
- 进程启动器通过以下方式验证路径
Lock()在启动之前,使用以下命令抑制请求者pr_WindowPtr = -1 - 自定义芯片寄存器($DFF000)被阻止读取(字节访问会损坏仅字寄存器)
amiga devbench(主机服务器)
一个Python应用程序,它结合了:
graph TB
subgraph "amiga-devbench process"
UVICORN[Uvicorn ASGI Server
Port 3000]
STARLETTE[Starlette Routes
Web API + Static Files]
FASTMCP[FastMCP
MCP Tools]
SERIAL_CONN[SerialConnection
TCP or PTY]
EVENT_BUS[EventBus
Async pub/sub]
STATE_MGR[AmigaState
Logs, vars, clients]
BUILDER_MOD[Builder
Docker cross-compile]
DEPLOYER_MOD[Deployer
Copy to shared folder]
end
UVICORN --> STARLETTE
UVICORN --> FASTMCP
STARLETTE --> EVENT_BUS
FASTMCP --> EVENT_BUS
SERIAL_CONN --> EVENT_BUS
EVENT_BUS --> STATE_MGR
style UVICORN fill:#e07020,color:#fff用户界面
看 Web UI参考 有关所有8个选项卡的截图的详细文档。
| 模块 | 目的 |
|---|---|
server.py | Starlette应用程序,所有HTTP/SSE端点,PID文件单例 |
mcp_tools.py | 使用FastMCP的45+MCP工具定义 |
protocol.py | parse_message() 和 format_command() --协议编解码器 |
serial_conn.py | SerialConnection 类——PTY创建、TCP连接、自动重新连接 |
state.py | AmigaState (日志缓冲区、var缓存)+ EventBus (基于异步队列的发布/订阅) |
builder.py | Builder 类--包装 docker run 用于交叉编译 |
deployer.py | Deployer 类--将二进制文件复制到AmiKit共享文件夹 |
simulator.py | 使用桥接协议的假Amiga(用于无模拟器测试) |
__main__.py | 带有argparse的CLI入口点 |
连接方式:
- PTY模式 (默认):在以下位置创建伪终端
/tmp/amiga-serial,FS-UAE将其作为串行端口打开 - TCP模式 (
--serial-host):连接到FS-UAE的TCP串行端口(例如。,tcp://0.0.0.0:1234)
libbridge.a(客户端库)
Amiga应用程序链接的静态库。为以下内容提供一个简单的API:
- 向守护进程注册
- 日志记录(打印样式,4个严重级别)
- 注册变量以进行远程检查/修改
- 注册钩子(主机可以调用的函数)
- 注册内存区域(主机可以读取的命名区域)
- 轮询传入命令
- 发送心跳
每个客户端的资源限制: 32个变量,16个钩子,8个内存区域
消息池: 4预先分配 BridgeMsg 结构(每次调用无malloc)
______________________________________________________________________
构建工具链
通过Docker进行交叉编译
graph LR
SRC[C Source Code
macOS filesystem] -->|docker run -v| DOCKER[Docker Container
amigadev/crosstools:m68k-amigaos]
DOCKER -->|m68k-amigaos-gcc| BIN[68k Binary
.o, .a, executable]
BIN -->|make deploy / cp| SHARED[AmiKit Shared Folder
DH2:Dev/]
SHARED -->|FS-UAE mount| AMIGA[Amiga Filesystem
DH2:Dev/binary]Docker镜像: amigadev/crosstools:m68k-amigaos
- 基于Debian
m68k-amigaos-gcc交叉编译器 - 包括AmigaOS标头和amiga.lib
- 已安装项目根目录
/work
编译器标志:
| 标志 | 目的 |
|---|---|
-noixemul | 无Unix模拟——纯AmigaOS(强制) |
-m68020 | 目标68020 CPU(A1200默认) |
-O0 | 无需优化(更容易调试) |
-Wall | 所有警告 |
-Iinclude | 桥接头路径 |
-lbridge | 链接客户端库 |
-lamiga | 链接朋友.lib |
生成命令:
make all # Build everything (lib + bridge + examples)
make bridge # Build daemon + libbridge.a
make examples # Build hello_world, bouncing_ball, system_monitor
make clean # Clean all artifacts部署路径
主机路径:
/Applications/AmiKit.app/Contents/SharedSupport/prefix/drive_c/AmiKit/Dropbox/Dev/阿米加路径:
DH2:Dev/二进制文件被复制到主机路径,并通过以下方式在Amiga上立即可见 FS-UAE共享文件夹挂载。
______________________________________________________________________
FS-UAE仿真器设置
配置文件
地点: ~/Documents/FS-UAE/Configurations/AmiKit-Debug.fs-uae
[fs-uae]
# Kickstart ROM
kickstart_file = ~/Documents/FS-UAE/Kickstarts/kick.rom
# Hardware: A1200 with 68020+FPU, 2MB chip, 8MB fast
amiga_model = A1200
cpu = 68020
fpu = 68882
chip_memory = 2048
fast_memory = 8192
# Hard drives
hard_drive_0 = ~/Documents/FS-UAE/Hard Drives/System # DH0: (boot)
hard_drive_1 = .../AmiKit/RabbitHole/InstalledOS # DH1: (OS extras)
hard_drive_2 = .../AmiKit/Dropbox # DH2: (Dev binaries)
# Serial: TCP mode (devbench connects as client)
serial_port = tcp://0.0.0.0:1234
serial_on_demand = false
# Mouse: don't capture
mouse_integration = 1
automatic_input_grab = 0
initial_input_grab = 0
cursor_integration = 1
# Networking
bsdsocket_library = 1启动序列
地点: ~/Documents/FS-UAE/Hard Drives/System/S/Startup-Sequence
开发环境的主要新增内容:
; Suppress "Please insert Work" requester
Assign >NIL: Work: RAM:
; Auto-start bridge daemon
If EXISTS DH2:Dev/amiga-bridge
Run >NIL: DH2:Dev/amiga-bridge
EndIf连接模式
graph TB
subgraph PTY_Mode ["PTY Mode (default)"]
DB1["amiga-devbench"] -->|creates| PTY["PTY pseudo-terminal"]
PTY -->|"serial_port ="| FSUAE1["FS-UAE"]
end
subgraph TCP_Mode ["TCP Mode"]
FSUAE2["FS-UAE"] -->|"listens on :1234"| TCP["TCP socket"]
TCP -->|connects to| DB2["amiga-devbench
--serial-host"]
endPTY模式: devbench必须在FS-UAE(创建PTY文件)之前启动 TCP模式: FS-UAE必须在devbench之前启动(在端口上侦听)
______________________________________________________________________
桥接协议
基于串行的行文本协议。每条消息都是 \n-终止, 字段以管道分隔(|),每行最多1024个字符。
阿米加→ 主机消息
日志记录和状态
| 消息 | 格式 | 描述 | ||||
|---|---|---|---|---|---|---|
| 日志 | `LOG\ | level\ | tick\ | message` | 应用程序日志(级别:D/I/W/E) | |
| 堵塞 | `CLOG\ | client\ | level\ | tick\ | message` | 客户端归因日志 |
| HB | `HB\ | tick\ | freeChip\ | freeFast` | 心跳 | |
| 乒乓球 | `PONG\ | clientCount\ | freeChip\ | freeFast` | Ping响应 | |
| 准备好了 | `READY\ | version` | Daemon启动 |
变量
| 消息 | 格式 | 描述 | ||||
|---|---|---|---|---|---|---|
| VAR | `VAR\ | name\ | type\ | value` | 变量值(类型:i32/u32/str/f32/ptr) | |
| CVAR | `CVAR\ | client\ | name\ | type\ | value` | 客户端属性变量 |
记忆
| 消息 | 格式 | 描述 | |||
|---|---|---|---|---|---|
| MEM | `MEM\ | addr_hex\ | size\ | hex_data` | 内存转储响应 |
系统信息
| 消息 | 格式 | 描述 | ||
|---|---|---|---|---|
| 客户 | `CLIENTS\ | count\ | name1,name2,...` | 已连接的客户端 |
| 任务 | `TASKS\ | count\ | name(pri,state,type),...` | 任务列表 |
| LIBS | `LIBS\ | count\ | name(v.r),...` | 图书馆列表 |
| 设备 | `DEVICES\ | count\ | name(v.r),...` | 设备列表 |
| 体积 | `VOLUMES\ | count\ | name1,name2,...` | 卷列表 |
文件
| 消息 | 格式 | 描述 | ||||
|---|---|---|---|---|---|---|
| DIR | `DIR\ | path\ | count\ | name(size,type),...` | 目录列表 | |
| 文件 | `FILE\ | path\ | size\ | offset\ | hex_data` | 文件内容 |
| 文件信息 | `FILEINFO\ | path\ | size\ | date\ | protbits` | 文件元数据 |
流程和命令
| 消息 | 格式 | 描述 | |||
|---|---|---|---|---|---|
| PROC | `PROC\ | id\ | status\ | output` | 流程完成 |
| CMD | `CMD\ | id\ | status\ | response` | 命令响应 |
客户反思
| 消息 | 格式 | 描述 | ||||||
|---|---|---|---|---|---|---|---|---|
| 钩子 | `HOOKS\ | client\ | count\ | name:desc,...` | 钩列表 | |||
| 内存 | `MEMREGS\ | client\ | count\ | name:addr:size:desc,...` | 内存区域 | |||
| CINFO | `CINFO\ | name\ | id\ | msgs\ | vars:...\ | hooks:...\ | memregs:...` | 完整的客户信息 |
硬件和检查
| 消息 | 格式 | 描述 | |||||||
|---|---|---|---|---|---|---|---|---|---|
| 内存映射 | `MEMMAP\ | count\ | name:attr:lower:upper:free:largest,...` | 内存区域图 | |||||
| 堆栈信息 | `STACKINFO\ | task\ | spLower\ | spUpper\ | spReg\ | size\ | used\ | free` | 任务堆栈信息 |
| 芯片 | `CHIPREGS\ | count\ | name:addr:value\ | ...` | 自定义芯片寄存器值 | ||||
| REGS。 `REGS\ | D0=val\ | D1=val\ | ...\ | SP=val\ | SR=val` | CPU寄存器快照 | |||
| 搜索 | `SEARCH\ | count\ | addr1,addr2,...` | 内存搜索结果 |
致谢
| 消息 | 格式 | 描述 | ||
|---|---|---|---|---|
| 好的 `OK\ | context\ | detail` | 成功 | |
| ERR | `ERR\ | context\ | detail` | 错误 |
Host → Amiga命令
连接
| 命令 | 格式 | 描述 |
|---|---|---|
| PING | PING | 请求状态 |
| 关机 | SHUTDOWN | 终止守护进程 |
变量
| 命令 | 格式 | 描述 | ||
|---|---|---|---|---|
| 获取 | `GETVAR\ | name` | 获取变量值 | |
| 设置 | `SETVAR\ | name\ | value` | 设置变量值 |
记忆
| 命令 | 格式 | 描述 | ||
|---|---|---|---|---|
| 检查 | `INSPECT\ | addr_hex\ | size` | 请求内存转储 |
| 作家 | `WRITEMEM\ | addr_hex\ | hex_data` | 写入内存 |
系统查询
| 命令 | 格式 | 描述 |
|---|---|---|
| 列出客户 | LISTCLIENTS | 列出客户 |
| 任务列表 | LISTTASKS | 列出任务 |
| LISTLIBS | LISTLIBS | 列出库 |
| listdevs | LISTDEVS | 列出设备 |
| 列表 | LISTVOLUMES | 列出卷 |
文件系统
| 命令 | 格式 | 描述 | |||
|---|---|---|---|---|---|
| LISTDIR | `LISTDIR\ | path` | 列表目录 | ||
| 读取文件 | `READFILE\ | path\ | offset\ | size` | 读取文件 |
| 写文件 | `WRITEFILE\ | path\ | offset\ | hex_data` | 写入文件 |
| 文件信息 | `FILEINFO\ | path` | 获取文件信息 | ||
| 删除文件 | `DELETEFILE\ | path` | 删除文件 | ||
| MAKEDIR | `MAKEDIR\ | path` | 创建目录 |
过程控制
| 命令 | 格式 | 描述 | ||
|---|---|---|---|---|
| 发射 | `LAUNCH\ | id\ | command` | 快跑,等待 |
| 奔跑 | `RUN\ | id\ | command` | 异步运行 |
| DOSCOMMAND | `DOSCOMMAND\ | id\ | command` | 运行AmigaDOS命令 |
| 休息 | `BREAK\ | task_name` | 发送CTRL-C | |
| 脚本 | `SCRIPT\ | id\ | script_text` | 执行脚本(换行→ ;) |
| 停止 | `STOP\ | client_name` | 停止客户端(CTRL-C+IPC关闭) |
硬件和检查
| 命令 | 格式 | 描述 | |||
|---|---|---|---|---|---|
| 内存映射 | MEMMAP | 请求内存区域映射 | |||
| 堆栈信息 | `STACKINFO\ | taskname` | 请求任务的堆栈信息 | ||
| 芯片 | CHIPREGS | 读取安全的自定义芯片寄存器 | |||
| READREGS | READREGS | 捕获CPU寄存器 | |||
| 搜索 | `SEARCH\ | addr_hex\ | size\ | pattern_hex` | 在内存中搜索字节模式 |
挂钩和内存区域
| 命令 | 格式 | 描述 | ||||
|---|---|---|---|---|---|---|
| 挂钩 | `LISTHOOKS\ | client` | 列表挂钩 | |||
| CALLHOOK | `CALLHOOK\ | id\ | client\ | hook\ | args` | 呼叫挂钩 |
| 列表规则 | `LISTMEMREGS\ | client` | 列出内存区域 | |||
| READMEMREG | `READMEMREG\ | client\ | region` | 读取区域 | ||
| 客户信息 | `CLIENTINFO\ | client` | 获取客户详细信息 |
能力和流程管理
| 命令 | 格式 | 描述 | ||
|---|---|---|---|---|
| 能力 | CAPABILITIES | 查询守护程序版本、协议级别、支持的命令 | ||
| 接近 | PROCLIST | 列出跟踪的异步进程 | ||
| ProcStat | `PROCSTAT\ | id` | 获取被跟踪流程的状态 | |
| 信号 | `SIGNAL\ | id\ | sigType` | 向被跟踪进程发送信号(0=CTRL-C,1=CTRL-D,2=CTRL-E,3=CTRL-F) |
扩展文件系统操作
| 命令 | 格式 | 描述 | ||
|---|---|---|---|---|
| 重命名 | `RENAME\ | oldPath\ | newPath` | 重命名或移动文件 |
| 复制 | `COPY\ | src\ | dst` | 在服务器端复制文件(无需主机往返) |
| 附加 | `APPEND\ | path\ | hexData` | 将十六进制编码的数据附加到文件中 |
| 校验和 | `CHECKSUM\ | path` | 计算CRC32校验和和和文件大小 | |
| 保护 | `PROTECT\ | path` | 获取保护位 | |
| 保护 | `PROTECT\ | path\ | bits` | 设置保护位(十六进制) |
| SETCOMMENT | `SETCOMMENT\ | path\ | comment` | 设置文件注释(filenote) |
分配管理
| 命令 | 格式 | 描述 | |||
|---|---|---|---|---|---|
| 指派 | ASSIGNS | 列出所有DOS分配 | |||
| 分配 | `ASSIGN\ | name\ | path` | 创建/替换分配 | |
| 分配 | `ASSIGN\ | name\ | path\ | ADD` | 向多分配添加路径 |
| 分配 | `ASSIGN\ | name\ | \ | REMOVE` | 删除分配 |
文件尾部(实时流媒体)
| 命令 | 格式 | 描述 | |
|---|---|---|---|
| 尾巴 | `TAIL\ | path` | 开始跟踪文件以获取新数据 |
| 止动尾 | STOPTAIL | 停止尾随 |
阿米加→ 主机(新邮件)
| 消息 | 格式 | 描述 | ||||
|---|---|---|---|---|---|---|
| 能力 | `CAPABILITIES\ | version\ | protocolLevel\ | maxLine\ | cmd1,cmd2,...` | Daemon功能 |
| 接近 | `PROCLIST\ | count\ | id:cmd:status,...` | 跟踪流程列表 | ||
| ProcStat | `PROCSTAT\ | id\ | command\ | status` | 单进程状态 | |
| 尾部数据 | `TAILDATA\ | path\ | hexData` | 附加到尾部文件的新数据 | ||
| 校验和 | `CHECKSUM\ | path\ | crc32\ | size` | 文件CRC32和大小 | |
| 指派 | `ASSIGNS\ | count\ | name:path:type,...` | 分配列表(类型:A=分配,L=延迟,N=非约束) | ||
| 保护 | `PROTECT\ | path\ | bits` | 文件保护位(十六进制) |
______________________________________________________________________
客户端库API
头球 bridge_client.h
#include "bridge_client.h"变量类型
#define AB_TYPE_I32 0 /* signed 32-bit integer */
#define AB_TYPE_U32 1 /* unsigned 32-bit integer */
#define AB_TYPE_STR 2 /* null-terminated string */
#define AB_TYPE_F32 3 /* 32-bit float */
#define AB_TYPE_PTR 4 /* pointer (displayed as hex) */函数
初始化
int ab_init(const char *appName); /* Returns 0 on success, -1 on failure */
void ab_cleanup(void); /* Unregister from daemon */
BOOL ab_is_connected(void); /* Check daemon connection */日志记录
void ab_log(int level, const char *fmt, ...); /* Printf-style */
/* Convenience macros */
AB_D(fmt, ...) /* DEBUG */
AB_I(fmt, ...) /* INFO */
AB_W(fmt, ...) /* WARN */
AB_E(fmt, ...) /* ERROR */变量
void ab_register_var(const char *name, int type, void *ptr);
void ab_unregister_var(const char *name);
void ab_push_var(const char *name); /* Send current value to host */心跳与记忆
void ab_heartbeat(void); /* Send status pulse */
void ab_send_mem(APTR addr, ULONG size); /* Dump memory to host */命令处理
typedef void (*ab_cmd_handler_t)(ULONG id, const char *data);
void ab_set_cmd_handler(ab_cmd_handler_t handler);
void ab_poll(void); /* Check for commands (non-blocking) */
void ab_cmd_respond(ULONG id, const char *status, const char *data);钩子(主机可调用函数)
typedef int (*ab_hook_fn_t)(const char *args, char *resultBuf, int bufSize);
void ab_register_hook(const char *name, const char *description, ab_hook_fn_t fn);
void ab_unregister_hook(const char *name);存储器区域
void ab_register_memregion(const char *name, APTR addr, ULONG size,
const char *description);
void ab_unregister_memregion(const char *name);______________________________________________________________________
编程示例
最小应用程序——Hello World
#include
#include
#include "bridge_client.h"
int main(void)
{
if (ab_init("hello") != 0) {
printf("Bridge not running\n");
return 1;
}
AB_I("Hello from Amiga!");
Delay(50);
ab_cleanup();
return 0;
}构建: 与链接 -lbridge -lamiga
变量——远程监控
#include
#include
#include "bridge_client.h"
static LONG score = 0;
static LONG lives = 3;
static char player_name[32] = "Player1";
int main(void)
{
ab_init("game");
/* Register variables — host can read and write these */
ab_register_var("score", AB_TYPE_I32, &score);
ab_register_var("lives", AB_TYPE_I32, &lives);
ab_register_var("player_name", AB_TYPE_STR, player_name);
while (lives > 0) {
score += 10;
/* Push updated values to host every 50 frames */
if (score % 500 == 0) {
ab_push_var("score");
ab_push_var("lives");
ab_heartbeat();
}
/* Check for host commands (GETVAR, SETVAR, etc.) */
ab_poll();
Delay(1);
}
AB_I("Game over! Score: %ld", (long)score);
ab_cleanup();
return 0;
}主机现在可以:
- 阅读
score随着GETVAR|score - 集
lives随着SETVAR|lives|99 - 在web仪表板或通过MCP工具查看值
Hooks——远程函数调用
#include
#include
#include "bridge_client.h"
static LONG difficulty = 1;
/* Hook: called by the host, runs on the Amiga */
static int hook_set_difficulty(const char *args, char *result, int bufSize)
{
if (args && args[0]) {
difficulty = strtol(args, NULL, 10);
sprintf(result, "Difficulty set to %ld", (long)difficulty);
} else {
sprintf(result, "Current difficulty: %ld", (long)difficulty);
}
return 0; /* 0 = success */
}
static int hook_reset(const char *args, char *result, int bufSize)
{
difficulty = 1;
strncpy(result, "Reset complete", bufSize - 1);
return 0;
}
int main(void)
{
BOOL running = TRUE;
ab_init("game");
ab_register_var("difficulty", AB_TYPE_I32, &difficulty);
/* Register hooks — host can call these by name */
ab_register_hook("set_difficulty",
"Set game difficulty (1-10)",
hook_set_difficulty);
ab_register_hook("reset",
"Reset all settings",
hook_reset);
while (running) {
/* IMPORTANT: Do NOT call ab_log inside hooks!
* The daemon is waiting for the hook reply. */
ab_poll();
if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
running = FALSE;
Delay(5);
}
ab_cleanup();
return 0;
}来自克劳德代码: amiga_call_hook("game", "set_difficulty", "5") 从Web UI:挂钩面板→ Call
内存区域--命名内存区域
#include
#include "bridge_client.h"
struct GameState {
LONG x, y;
LONG vx, vy;
LONG score;
LONG level;
};
static struct GameState state = {100, 50, 2, 1, 0, 1};
int main(void)
{
ab_init("game");
/* Register a named memory region the host can inspect */
ab_register_memregion("gamestate",
&state, sizeof(state),
"Player position, velocity, score, level");
/* ... game loop ... */
ab_cleanup();
return 0;
}主机可以读取以下内容的原始字节 gamestate 随时进行低级检查。
完整示例——弹跳球(节选)
/* Register settable variables */
static LONG ball_speed = 1;
static LONG ball_color = 3;
ab_register_var("ball_speed", AB_TYPE_I32, &ball_speed);
ab_register_var("ball_color", AB_TYPE_I32, &ball_color);
/* Main loop uses the variables */
while (running) {
draw_ball(rp, ball_x, ball_y, (UBYTE)ball_color);
ball_x += dx;
ball_y += dy;
/* Push updates periodically */
if (frame_count % 60 == 0) {
ab_push_var("ball_speed");
ab_push_var("ball_color");
ab_heartbeat();
}
ab_poll(); /* Always poll! */
Delay(ball_speed 检查>字体浏览器)访问。枚举已安装的Amiga
字体通过 `diskfont.library` `AvailFonts()`,按可用尺寸按家庭分组。
单击字体查看指标:基线、x/y大小、样式标志、字体类型。
协议命令: `LISTFONTS` → `FONTS|count|name:sizes|...`, `FONTINFO|name|size` → `FONTINFO|name|size|ysize|xsize|style|flags|baseline`.
### 区域设置/目录检查器
可通过web UI(工具>检查>区域设置/目录检查器)访问。浏览
已安装的区域设置目录 `LOCALE:Catalogs/` 使用 `SCRIPT` 运行命令
友好的 `list` 命令。单击目录目录以查看其内容。
### 指派经理
可通过web UI(工具>系统>分配管理器)访问。列出、创建、修改、,
并删除AmigaOS逻辑分配(SYS:、LIBS:、FONTS:等)。支持ADD
多目录分配标志。使用 `SCRIPT` 运行命令 `assign` 在Amiga上。
### 启动序列编辑器
可通过web UI(工具>系统>启动序列编辑器)访问。远程编辑
`S:Startup-Sequence`, `S:User-Startup`,或 `S:Shell-Startup`.用途 `READFILE`/`WRITEFILE`
协议命令。更改将在下次启动时生效。
### 首选项编辑器
可通过web UI(工具>系统>首选项编辑器)访问。可用列表
工作台首选项文件来自 `ENV:sys/` 并读取其内容。前置文件
是IFF二进制格式。
### 自定义芯片寄存器记录器
可通过web UI(工具>调试>自定义芯片记录器)访问。监视器13可读
定制芯片注册费用为$DFF000,用于更改:DMACONR、VPOSR、VHPOSR、JOY0DAT,
JOY1DAT,POT0DAT,POT1DAT,POTGOR,INTENAR,INTREQR,DSKBYTR,DENISEID,ADKCONR。
- **开始** --拍摄初始快照并从网桥主循环开始轮询(间隔200ms)
- **停止** --停止监控
- **快照** --一次性读取所有寄存器
通过以下方式实时报告注册更改 `CHIPLOGCHANGE|tick|reg:old:new|...` 事件。
协议命令: `CHIPLOGSTART`, `CHIPLOGSTOP`, `CHIPLOGSNAPSHOT` → `CHIPLOG|reg:val|...`.
### 内存池跟踪器
可通过web UI(工具>调试>内存池跟踪器)访问。基于轨迹池
通过修补进行内存分配 `exec.library` 池功能通过 `SetFunction()`:
`CreatePool`, `DeletePool`, `AllocPooled`, `FreePooled`.
- **开始** --安装补丁,开始跟踪(最多32个池)
- **停止** --恢复原始函数向量
- **刷新** --列出具有分配计数和总大小的活动池
用途 `Forbid()`/`Permit()` 保护跟踪数据和 `Disable()`/`Enable()` 大约
`SetFunction()` 电话。
协议命令: `POOLSTART`, `POOLSTOP`, `POOLS` → `POOLS|count|addr:puddle:thresh:allocs:total|...`.
### 屏幕截图的视觉差异
可通过web UI(工具>图形>视觉差异)访问。像素级比较
两张Amiga屏幕截图,用于可视化回归测试。
1. **捕获A** --拍摄基线截图
1. 在Amiga上进行更改
1. **捕获B** --进行比较截图
1. **比较** --生成具有可配置阈值(0-255)的差异图像
生成差异图像(调暗背景+品红色更改像素+黄色边界框)。
使用16x16块报告更改百分比、像素计数和检测到的更改区域
网格与洪水填充连通分量分析。需要枕头(`pip install Pillow`).
### 剪贴板桥
可通过web UI(工具>控件>剪贴板桥)访问。共享剪贴板文本
在主人和阿米加之间。
- **从Amiga出发** --通过以下方式读取FTXT/CHS剪贴板数据 `clipboard.device` + `iffparse.library`
- **设定在阿米加** --以IFF FTXT格式将文本写入Amiga剪贴板
- **复制到主机** --通过以下方式将显示的文本复制到主机系统剪贴板 `navigator.clipboard`
协议命令: `CLIPGET` → `CLIPBOARD|length|text`, `CLIPSET|text` → `OK|CLIPBOARD|set N bytes`.
### CLI历史和别名
在web UI Shell选项卡中可用。使用箭头键提供持久的命令历史记录
导航和命名别名(例如。, `ll` = `list LFORMAT "%n %l"`).历史和别名
跨会话在服务器端维护。
### 项目脚手架
|工具|参数|说明|
|---|---|---|
| `amiga_create_project` | `name`, `template?` |创建新的示例项目(窗口/屏幕/无头)|
| `amiga_run` | `project`, `command?` |部署和启动(跳过构建)|
______________________________________________________________________
## 用Claude代码开发Amiga软件
本节介绍了MCP工具、REST API和web UI如何协同工作,为Amiga创建现代开发工作流程-所有这些都是从Mac上的Claude Code驱动的。
### 发展循环
使用Claude Code构建Amiga软件的典型循环:
1. **编写代码** --Claude在macOS上编辑C源文件
1. **构建** — `amiga_build("myproject")` 通过Docker进行交叉编译
1. **部署** — `amiga_deploy("myproject")` 将二进制文件复制到共享文件夹
1. **跑** — `amiga_launch("DH2:Dev/myproject")` 在Amiga上开始
1. **观察** — `amiga_watch_logs()` 流输出, `amiga_get_var()` 读取状态
1. **调试** — `amiga_inspect_memory()`, `amiga_last_crash()`, `amiga_disassemble()`
1. **迭代** — `amiga_stop_client()`,修复代码,从步骤2开始重复
或者在一个镜头中: `amiga_build_deploy_run("myproject")` 一起执行步骤2-4。
### 每种工具类别如何帮助
#### 构建和部署工具
Claude可以编写C代码、编译和部署,而无需您接触终端。持久的Docker容器使重建速度很快(约1-2秒)。 `amiga_checksum()` 验证部署的二进制文件是否与构建的二进制文件匹配——这在调试“为什么我的更改没有显示?”问题时至关重要。
#### 流程管理
启动程序后,Claude可以使用 `amiga_proc_list()` 和 `amiga_proc_stat()`如果程序挂起, `amiga_signal()` 无需Amiga键盘即可发送CTRL-C/D/E/F。 `amiga_stop_client()` 优雅地关闭桥感知应用程序。这使得Amiga就像一个无头构建目标——在正常开发过程中,您永远不需要与模拟器窗口交互。
#### 文件操作
Claude可以直接管理Amiga文件系统:
- **`amiga_rename`/`amiga_copy`** --不使用AmigaDOS命令重新组织项目文件
- **`amiga_protect`** --部署后设置可执行/脚本位
- **`amiga_set_comment`** --使用版本信息或构建时间戳标记文件
- **`amiga_append_file`** --增量写入日志文件或配置文件
- **`amiga_tail`** --实时查看日志文件(如 `tail -f` 在Unix上)
这些在Amiga上运行服务器端,避免了批量操作的缓慢串行往返。
#### 系统检查
当出现问题时,克劳德可以全面查询阿米加的状态:
- **`amiga_list_tasks`** --查看所有正在运行的进程,查找失控的任务
- **`amiga_list_libs`** / **`amiga_lib_info`** --检查库版本,验证已加载的库
- **`amiga_list_assigns`** / **`amiga_assign`** --管理逻辑分配(对AmigaOS路径解析至关重要)
- **`amiga_capabilities`** --验证守护进程支持哪些协议命令
- **`amiga_inspect_memory`** --读取任何内存地址(芯片RAM、快速RAM、ROM)
#### 调试
追踪bug最强大的工具:
- **`amiga_last_crash`** --当可怕的古鲁冥想来袭时,克劳德会读取警报代码、所有寄存器和堆栈数据
- **`amiga_load_symbols`** + **`amiga_lookup_symbol`** --将崩溃地址映射回C源代码行
- **`amiga_disassemble`** --使用LVO注释检查生成的68k代码
- **`amiga_watch_logs`** --实时流式应用程序调试输出
- **`amiga_get_var`** / **`amiga_set_var`** --在应用程序运行时读取和写入插入指令的变量
#### 遥控器
Claude可以在没有屏幕访问的情况下与Amiga的GUI交互:
- **`amiga_input_key`/`amiga_input_click`/`amiga_input_mouse_move`** --模拟用户输入
- **`amiga_screenshot`** --查看屏幕上的内容
- **`amiga_list_screens`/`amiga_list_screen_windows`** --了解当前UI状态
### REST API端点(新增)
web UI和外部工具可以直接调用这些HTTP端点:
#### 能力和流程管理
|端点|方法|描述|
|---|---|---|
| `/api/tools/capabilities` |GET|查询守护进程版本和支持的命令|
| `/api/tools/proclist` |GET |列出跟踪的异步进程|
| `/api/tools/signal` |POST |向被跟踪进程发送信号(`id`, `sigType`) |
#### 扩展文件操作
|端点|方法|描述|
|---|---|---|
| `/api/tools/checksum` |GET|CRC32+文件大小(`path`) |
| `/api/tools/protect` |GET/POST |获取或设置保护位(`path`, `bits?`) |
| `/api/tools/rename` |POST |重命名文件(`oldPath`, `newPath`) |
| `/api/tools/copy` |POST |在服务器端复制文件(`src`, `dst`) |
| `/api/tools/tail` |GET(SSE)|流式实时文件附加(`path`) |
#### 分配管理(本机协议)
|端点|方法|描述|
|---|---|---|
| `/api/tools/assigns` |GET |列出所有DOS分配(本机assigns命令)|
| `/api/tools/assign/set` |POST |创建/替换/添加分配(本机assign命令)|
### 示例:完整调试会话
You: "My bouncing_ball app crashes after a few seconds"
Claude: [builds and deploys the project] amiga_build_deploy_run("bouncing_ball")
Claude: [watches the crash happen] amiga_watch_logs(duration_ms=30000) → CLOG|bouncing_ball|I|1234|Starting... → CLOG|bouncing_ball|I|1567|Frame 100 → [crash]
Claude: [reads the crash report] amiga_last_crash() → Alert: 80000004 (Access Fault) → PC: 0040A2B8, SR: 0000 → D0=00000000 A0=DEADBEEF ...
Claude: [maps the crash address to source] amiga_load_symbols("bouncing_ball") amiga_lookup_symbol("0040A2B8") → bouncing_ball.c:142 in draw_ball()
Claude: [inspects the source, finds the bug, fixes it, rebuilds] amiga_build_deploy_run("bouncing_ball") → Build OK → Deploy OK → Running
### 示例:文件验证工作流
You: "Deploy my app and verify it's correct"
Claude: amiga_build("myapp") amiga_deploy("myapp") amiga_checksum("DH2:Dev/myapp") → CRC32: a1b2c3d4, Size: 12340 bytes
# Compare with local build # CRC matches → deployment verified
amiga_protect("DH2:Dev/myapp", "00000000") # Ensure rwed bits set amiga_launch("DH2:Dev/myapp") amiga_tail("T:myapp.log", duration_ms=5000) # Watch the log file
______________________________________________________________________
## Web UI参考
web仪表板位于 `http://localhost:3000/` 提供实时视图
Amiga系统有8个主选项卡。
### 仪表盘
连接状态、系统信息、快速操作和模拟器控制。

- **连接卡** --串行链路状态、主机、端口、缓冲区计数
- **系统状态** --心跳,芯片/快速存储器,桥接版本
- **客户** --已连接网桥客户端列表
- **桥梁能力** --查询守护进程以获取支持的命令
- **快捷操作** --Ping、列出客户、任务、Lib、屏幕等。
- **仿真器控件** --从web UI启动、重新启动、停止FS-UAE
- **发送命令** --原始协议命令输入
### 日志
来自所有Amiga网桥客户端的实时日志流。

- 按级别筛选:调试、信息、警告、错误(可切换按钮)
- 按客户名称筛选(下拉菜单)
- 文本搜索(子字符串匹配)
- 自动滚动切换
- 按严重程度进行颜色编码(蓝色=调试,绿色=信息,橙色=警告,红色=错误)
### 文件
Amiga文件系统浏览器和主机↔Amiga文件传输。

- **浏览器子选项卡** --卷浏览器(左窗格)、文件列表(右窗格)、面包屑导航
- **传输子选项卡** --上传/下载文件,通过CRC32验证传输历史记录
### 工具
内存、变量、shell和任务的四个子选项卡。
#### 记忆

- 地址输入(十六进制)+大小输入(十进制)
- 硬件/系统书签:CIA-A、CIA-B、ExecBase、ROM、矢量
- 带ASCII注释的十六进制转储显示
- **写入控件** --地址输入、十六进制数据输入、写入按钮
#### 变量

- 来自所有客户端的所有已注册变量
- 内联编辑--单击“编辑”,键入新值,按Enter键或单击“设置”
- 自动刷新切换(间隔3秒)
#### 外壳

通过远程AmigaDOS shell `shell_proxy` 桥接客户端。
- **启动Shell代理** 按钮--在Amiga上构建、部署和启动shell代理
- 带有滚动输出的终端风格界面(深色背景上的绿色文本)
- 键入AmigaDOS命令(`dir`, `type`, `list`, `assign`等)并实时查看输出
- 箭头键(向上/向下)导航命令历史记录
- 别名:定义命名快捷方式,持久化服务器端
#### 任务

- 所有具有名称、优先级、状态、类型列的正在运行的任务/进程
- 刷新按钮+自动刷新切换(间隔5秒)
- 已启动程序的跟踪流程面板
### 检查
图形、系统和调试工具的三个子选项卡。



#### 检查工具
视觉检查和开发工具排列成网格。每个工具都有一个 `?` 带有详细帮助的工具提示。
**截图** --将Amiga显示捕获为PNG。从下拉列表中选择一个窗口,或为最前面的屏幕选择“全屏”。从芯片RAM读取平面位平面数据,并将其转换为主机上的块状像素。屏幕截图保存到 `/tmp/amiga-screenshots/` 带有可点击的预览链接和历史记录。
**调色板** --通过以下方式从最前面屏幕的ColorMap读取OCS/ECS 12位调色板 `GetRGB4()`。显示具有十六进制值的色样。工作台使用4种颜色;自定义屏幕最多32个(5个位平面)或256个(AGA)。
**铜列表** --读取并解码铜列表 `GfxBase->ActiView->LOFCprList`.显示每条4字节指令:MOVE(用指定寄存器写入自定义芯片寄存器)、WAIT(等待光束位置)或SKIP。跨越2个网格列以提高可读性。
**雪碧检查员** --通过扫描铜列表中的SPRxPT寄存器写入并检查来读取8个硬件子画面通道 `GfxBase->SimpleSprites[]` 用于Intuition管理的精灵(鼠标指针)。显示位置、大小和连接模式。
**反汇编器** --从Amiga读取内存并反汇编68000机器代码。输入十六进制地址和指令计数。支持所有68k寻址模式,并注释已知的Exec/DOS/InIntuition/Graphics库调用(LVO)。跨越2个网格柱。尝试 `$FC0000` Kickstart ROM。
**崩溃报告** --通过补丁拦截大师冥想 `exec.library Alert()` 通过 `SetFunction()`。默认情况下未安装--单击 **启用** 为了激活, **禁用** 移除。当发生崩溃时,捕获警报代码、警报名称、所有16个寄存器(D0-D7、A0-A7)、堆栈指针和64个字节的堆栈数据。点击 **测试** 以触发可恢复警报。
**资源跟踪器** --查询网桥客户端的跟踪资源。从下拉列表中选择一个客户端。应用程序使用 `ab_track_alloc()`/`ab_track_free()` 和 `ab_track_open()`/`ab_track_close()` 报告分配和打开句柄。显示泄漏的资源。
**性能剖析器** --查询网桥客户端的性能数据。从下拉列表中选择一个客户端。 `ab_perf_frame_start()`/`ab_perf_frame_end()` 跟踪帧定时(avg/min/max)。 `ab_perf_section_start()`/`ab_perf_section_end()` 以代码段命名的度量值。用途 `VHPOSR ($DFF006)` 精度约为64us。
**记忆搜索** --在Amiga内存中搜索十六进制字节模式。输入起始地址(十六进制)、搜索长度(字节)和十六进制模式(例如。, `4AFC` 查找非法指示)。最多返回32个匹配的地址。扫描前验证起始地址是否在可访问的RAM中。
**位图查看器** --将Amiga内存区域渲染为位图图像。指定地址、宽度、高度和位深度(1-8个平面)。将数据解释为Amiga平面位平面格式,并使用当前或默认调色板进行渲染。可用于检查芯片RAM中的图形数据、子画面或屏幕缓冲区。
**内存映射** --显示以下所有内存区域 `ExecBase->MemList`。对于每个区域:名称、属性(CHIP/FAST)、地址范围(上下)、总可用字节数和最大连续块。步行 `MemChunk` 免费列表,用于准确报告可用空间。对于跟踪内存碎片至关重要。
**堆栈监视器** --检查任何正在运行的任务的堆栈使用情况。从下拉列表中选择一个任务(从任务列表中自动填充),然后单击检查。显示SP寄存器值、堆栈边界($SPLower–$SPUpper)、总堆栈大小、已使用字节和空闲字节。颜色编码的进度条突出显示危险级别:绿色(使用率\80%)。Amiga的默认4KB堆栈是一个常见的崩溃源。
**注册查看器** --捕获网桥守护进程的CPU寄存器状态。将所有16个数据/地址寄存器(D0-D7、A0-A6)和堆栈指针(SP)显示为32位十六进制值。注意:值反映了处理程序函数中捕获时的寄存器状态,而不是调用者的确切状态。SR(状态寄存器)需要68010+上的监督模式,无法从用户模式读取。
**芯片寄存器查看器** --以$DFF000读取所有安全(只读)自定义芯片寄存器。显示一个包含寄存器名称、地址、原始十六进制值和解码位字段的表。包括:DMACONR、VPOSR、VHPOSR、JOY0DAT、JOY1DAT、CLXDAT、ADKCONR、POT0DAT/POT1DAT、POTGOR、SERDATR、DSKBYTR、INTENAR、INTREQR和DENISEID。为了避免副作用,只写寄存器被排除在外。跨越2个网格柱。
**IFF图像查看器** --查看存储在Amiga文件系统上的IFF ILBM图像。使用内置的文件浏览器小部件浏览文件(与“文件”选项卡相同的导航)。单击IFF/ILBM文件从Amiga读取它,解码主机上的FORM/BMHD/CMAP/BODY块(包括ByteRun1解压缩),将平面数据转换为PNG,并内联显示。IFF文件在浏览器中以绿色突出显示。
**差异/快照** --比较随时间变化的内存状态。为内存区域拍摄一个命名快照,然后稍后拍摄另一个快照并比较它们以查看发生了什么变化。行动: **拿** (将地址+大小保存为命名快照), **差异** (逐字节比较两个快照,显示更改的偏移量), **列表** (显示所有保存的快照), **清除** (删除所有快照)。可用于跟踪内存损坏或了解游戏状态如何演变。
**启动日志** --显示此devbench会话期间捕获的最早日志消息。显示通过串行链路接收到的前N个日志条目,通常包括网桥守护进程启动消息和早期客户端注册。如果devbench在桥之前启动,则这些代表了真正的启动顺序。
**库/设备检查器** --浏览Amiga上加载的所有库和设备。两个选项卡(库/设备)分别显示一个可点击的列表,该列表由以下内容填充 `exec.library`s `LibList` 和 `DeviceList`。单击任何条目以查看详细信息:名称、版本、打开计数、标志、负大小(跳转表)、正大小(数据区域)、基址和ID字符串。从详细视图中:
- **显示跳转表** --列出库跳转表中的每个LVO条目及其目标地址,分页(每页60个)。每个LVO都是一个6字节的JMP指令,与库基偏移量为负。
- **转储基础内存** --读取库基址处的原始内存,并在“反汇编程序”面板中打开它进行检查。
- **倾倒跳台** --读取负偏移区域(实际跳转表字节),并在反汇编程序中打开它。
可用于查找库版本、检查库是否已加载以及逆向工程库入口点。
**SnoopDos** --实时系统调用监控,灵感来自经典的SnoopDos实用程序。用途 `SetFunction()` 修补中的10个功能 `exec.library` 和 `dos.library`:
- **高级图书馆**: `OpenLibrary`, `CloseLibrary`, `OpenDevice`, `CloseDevice`
- **dos.图书馆**: `Open`, `Close`, `Lock`, `UnLock`, `LoadSeg`, `UnLoadSeg`
点击 **开始** 安装补丁, **停止** 移除它们。当处于活动状态时,对修补函数的每次调用都会记录到Amiga侧的环形缓冲区中,并以200ms的间隔流式传输到主机。日志表显示:函数名、调用方地址、arg1(文件路径、库名或BPTR地址)、arg2(模式、版本等)、结果(OK/FAIL)和勾号计数。状态栏显示总事件计数、删除计数(环形缓冲区溢出)和缓冲计数。日志的记录上限为500条,渲染性能受到限制。
**指派经理** --查看、创建、修改和删除AmigaOS逻辑分配。该列表显示了所有当前分配及其目标路径。使用输入字段创建新分配或单击红色 `x` 删除一个。支持多目录分配的ADD复选框。使用 `SCRIPT` 运行命令 `assign` 在Amiga上。
**启动序列编辑器** --远程编辑 `S:Startup-Sequence`, `S:User-Startup`,或 `S:Shell-Startup`。从下拉列表中选择一个文件,单击 **负载** 要将其读入编辑器,进行更改,然后单击 **保存** 把它写回去。更改将在下次Amiga启动时生效。
**首选项编辑器** --浏览存储在中的工作台首选项文件 `ENV:sys/`。单击 **列表前言** 查看可用 `.prefs` 文件大小,然后单击任何条目查看其内容(IFF二进制格式显示为十六进制)。
**自定义芯片记录器** --监控可读自定义芯片寄存器的变化。点击 **开始** 以200ms的间隔开始轮询13个寄存器(DMACONR、INTENAR、INTREQR、JOY/POT数据等)。注册更改实时显示。点击 **快照** 读一读。点击 **停止** 结束监控。
**内存池跟踪器** --跟踪基于池的内存分配。 **开始** 补丁 `CreatePool`/`DeletePool`/`AllocPooled`/`FreePooled` 在 `exec.library` 通过 `SetFunction()`. **刷新** 显示具有分配计数、空闲计数和总大小的活动池。 **停止** 恢复原始函数向量。最多可追踪32个游泳池。
**视觉差异** --比较两张Amiga屏幕截图,找出像素差异。点击 **捕获A** 对于基线,请在Amiga上进行更改,单击 **捕获B**那么 **比较**。生成一个差异图像,用黄色边界框突出显示品红色的变化区域。可调阈值(0-255)控制灵敏度。报告更改区域的百分比和数量。
**字体浏览** --枚举已安装的Amiga字体。点击 **列出字体** 询问 `diskfont.library` 通过 `AvailFonts()`。显示按可用大小分组的字体族。单击任何字体条目以查看详细指标:基线、x/y大小、样式标志和字体类型。位于“检查”子选项卡中。
**区域设置/目录检查器** --在以下位置浏览已安装的区域设置目录 `LOCALE:Catalogs/`。单击 **列出目录** 查看可用的目录目录。单击目录以查看其内容(带大小的目录文件)。位于“检查”子选项卡中。
**剪贴板桥** --在主机和Amiga之间共享剪贴板文本。 **从Amiga出发** 从以下位置读取IFF FTXT数据 `clipboard.device`. **设定在阿米加** 将文本写入Amiga剪贴板。 **复制到主机** 将显示的文本复制到主机系统剪贴板。位于“控制”子选项卡中。
**系统信息仪表板** --结合多个查询的一键式系统概述。显示空闲芯片RAM、空闲快速RAM、连接的网桥客户端数量、加载的库计数、运行任务计数和装载的卷计数。提供Amiga系统状态的快速健康检查。
### 开发
从浏览器构建、部署和运行Amiga程序。

**构建与运行** --一键完成整个开发周期:通过Docker交叉编译(使用持久容器进行约10倍的加速),将二进制文件部署到AmiKit共享文件夹,停止任何正在运行的实例(CTRL-C),然后启动。从下拉列表中选择一个项目(从 `examples/` 目录)。
**新项目** --使用Makefile和main.c构建一个新的示例项目。三个模板:
- **窗口** --Workbench屏幕上的直观窗口与桥接器集成
- **屏幕** --带有桥接集成的自定义屏幕(320x256,5位平面)
- **无头** --仅CLI程序,带桥挂钩,无GUI
**测试用具** --实时测试结果来自 `AB_ASSERT()` 客户端代码中的宏。
### 设置
串行、仿真器、服务器配置和MCP/REST流量记录。

- **配置子选项卡** --串行模式(TCP/PTY)、主机、端口、仿真器二进制/配置路径、自动启动、部署目录。全部可编辑并保存到 `devbench.toml`.
- **流量子选项卡** --请求使用过滤器(MCP/REST)进行日志记录、搜索、时序分析,以调试MCP工具性能。
### 关于对话框

点击徽标或“关于”按钮,查看对Amiga团队、萨克拉门托Amiga计算机俱乐部(SACC)和项目学分的致敬。

“关于”对话框包括对 [萨克拉门托Amiga计算机俱乐部](https://sacc.org/) --Amiga社区40年,每月举行会议,经典游戏,音乐制作和3D建模。
### 选项卡组织
web UI分为8个主选项卡,其中几个带有子选项卡:
|选项卡|子选项卡|目的|
|-----|----------|---------|
| **仪表盘** |--|连接状态、系统信息、快速操作、仿真器控制|
| **日志** |--|具有级别/客户端/文本过滤的实时日志流|
| **文件** |浏览器、传输|Amiga文件系统导航、主机↔Amiga文件传输|
| **工具** |内存、变量、Shell、任务|内存检查、变量编辑、AmigaDOS Shell、任务列表|
| **检查** |图形、系统、调试|截图、调色板、铜列表、精灵、SnoopDos、输入注入|
| **开发** |--|构建和运行、新项目脚手架、测试线束|
| **调试器** |--|使用断点、步进、寄存器、调用堆栈进行源代码级调试|
| **设置** |配置、流量|串行/仿真器/服务器配置、MCP/REST请求日志记录|
### 调试器选项卡

调试器选项卡为Amiga程序提供源代码级调试,用于通信
使用网桥守护进程的内置调试器,该调试器使用68k个异常处理程序。
#### 目标和发射控制
- **目标** 下拉菜单--从中选择一个项目 `examples/` 调试
- **构建与发布** --在加载调试符号的情况下进行交叉编译、部署和启动
- **负载符号** --解析ELF/Hunk二进制文件以提取函数名和源代码行映射
- **附着/分离** --连接到正在运行的程序的调试会话或从中断开连接
#### 执行控制
当目标停止时(断点命中、步进或手动中断):
|按钮|操作|描述|
|--------|--------|-------------|
| **继续** |恢复|运行到下一个断点或手动中断|
| **休息** |停止|暂停执行当前指令|
| **步入** |单步|执行一条指令,输入函数调用|
| **单步跳过** |跨步|执行一条指令,跨步函数调用|
#### 源查看器
- 显示与当前程序计数器对应的C源文件
- **排水沟断点** --单击行号槽以切换断点(红点)
- **当前行高亮显示** --执行行以黄色/绿色突出显示
- **滚动到PC** --自动将视图居中显示在当前执行点上
- 使用调试符号行映射从宿主项目目录读取源文件
#### 寄存器面板
显示目标停止时的所有68020 CPU寄存器:
- **资料暂存器**:D0–D7(32位十六进制值)
- **地址寄存器**:A0-A6(32位十六进制值)
- **栈指针**:SP/A7
- **程序计数器**:具有当前地址的PC
- **状态寄存器**:带有条件代码标志的SR
#### 调用堆栈(回溯)
- 显示从当前PC返回的函数调用链 `main()`
- 每一帧显示:函数名、源文件、行号和返回地址
- 单击框架将源查看器导航到该位置
- 使用帧指针(A5)链式遍历+符号表查找
#### 断点面板
- 列出所有设置的断点,包括源文件、行号和地址
- 按断点切换启用/禁用
- 删除单个断点或清除所有断点
- 断点在继续/步骤操作中持续存在
- 通过代码中修补的68k TRAP指令实现
#### 变量面板(调试上下文)
- 停止时,显示局部变量和函数参数
- 使用调试符号信息从Amiga内存中读取的值
- 自上次停车以来突出显示的更改值
#### 运作原理
网桥守护进程的调试器模块(`debugger.c`)安装68k个异常处理程序:
1. **陷阱#0** --断点异常。当断点地址被命中时,CPU会陷阱,寄存器会被保存,网桥会通知主机。
1. **跟踪位** --对于单步。设置SR中的T位,以便在每条指令后生成跟踪异常。
1. 主机发送 **中断**, **继续**, **步**, **跨步** 通过串行协议发送命令。
1. 寄存器状态在异常处理程序中捕获,并作为 **DBGSTOP** 事件。
1. **单步跳过** 检测:将停止的PC与已知的函数入口点进行比较,以确定我们是否输入了调用,并在返回地址设置一个临时断点。
### SSE事件流
web UI连接到 `/api/events` 实时更新:
|事件|数据|更新|
|---|---|---|
| `log` | `{level, tick, message, client}` |日志面板|
| `heartbeat` | `{tick, freeChip, freeFast}` |状态标题|
| `var` | `{name, varType, value, client}` |变量面板|
| `status` | `{connected, logCount, varCount}` |连接状态|
| `clients` | `{names: [...]}` |客户列表|
| `tasks` | `{tasks: [...]}` |任务面板|
| `snoop` | `{func, caller, arg1, arg2, result, tick}` |SnoopDos事件日志|
| `snoopstate` | `{active, eventCount, dropCount, buffered}` |SnoopDos状态|
| `fonts` | `{count, fonts: [...]}` |字体枚举响应|
| `fontinfo` | `{name, size, ysize, xsize, style, flags, baseline}` |字体度量响应|
| `chiplog` | `{registers: {name: value, ...}}` |芯片寄存器快照|
| `chiplogchange` | `{tick, changes: {reg: {old, new}, ...}}` |芯片寄存器变更通知|
| `pools` | `{count, pools: [...]}` |池跟踪器数据|
| `clipboard` | `{length, text}` |剪贴板内容响应|
| `libinfo` | `{name, version, revision, openCnt, ...}` |图书馆详细回复|
| `devinfo` | `{name, version, revision, openCnt, ...}` |设备详细信息响应|
| `libfuncs` | `{name, page, totalPages, entries: [...]}` |库跳转表条目|
| `capabilities` | `{version, protocolLevel, maxLine, commands}` |Daemon功能响应|
| `proclist` | `{count, processes: [{id, command, status}]}` |跟踪流程列表|
| `procstat` | `{id, command, status}` |单进程状态|
| `taildata` | `{path, data}` |附加到尾部文件的新数据|
| `checksum` | `{path, crc32, size}` |文件校验和响应|
| `assigns` | `{count, assigns: [{name, path, assignType}]}` |分配列表响应|
| `protect` | `{path, bits}` |保护位响应|
| `connected` | `{}` |状态指示器→ 绿色|
| `disconnected` | `{}` |状态指示器→ red |
______________________________________________________________________
## 脚本和实用程序
### `scripts/devbench-start.sh` --全环境启动器
./scripts/devbench-start.sh # Start devbench + FS-UAE ./scripts/devbench-start.sh --sim # Simulator mode (no emulator needed) ./scripts/devbench-start.sh --restart # Restart FS-UAE only ./scripts/devbench-start.sh --stop # Stop everything ./scripts/devbench-start.sh --status # Show running status
管理PID文件 `/tmp/amiga-dev/`,在等待HTTP健康检查之前
启动FS-UAE,清理过时的进程。
### 其他脚本
|脚本|目的|
|---|---|
| `scripts/start-all.sh` |传统启动(旧的TypeScript MCP服务器)|
| `scripts/amiga-serial.py` |串行端口实用程序|
| `scripts/amiga-serial-bridge.py` |独立TCP到串行网桥(已过时)|
| `scripts/create-pty.py` |创建PTY对进行测试|
### MCP客户端配置
**`.mcp.json`** (以项目根为单位):
{ "mcpServers": { "amiga-dev": { "type": "streamable-http", "url": "http://localhost:3000/mcp" } } }
当发生以下情况时,此功能会自动配置Claude Code以连接到MCP服务器
在这个项目目录中工作。
______________________________________________________________________
## 未来改进
### 调试与检查
- **源代码级调试**:使用来自交叉编译器的DWARF/STABS调试信息将地址映射到C源代码行。在内存检查器中显示源上下文。
- **断点支持**:使用68k TRAP指令或非法操作码来实现软件断点。网桥守护进程可以在运行时修补/取消修补代码。
- **堆栈跟踪**:当应用程序崩溃或遇到断点时,遍历68k堆栈帧以生成符号回溯。
- **观察点**:监视内存地址的更改,并在值更改时通知主机(轮询或通过自定义异常处理程序)。
### 构建和工作流
- **增量构建**:~~缓存Docker层或使用持久容器~~ *(完成——持久容器,约10倍加速)*。进一步:查看源文件以进行自动重建。
- **构建错误分析**:解析GCC错误输出并映射到主机上的源文件,以便进行可点击的错误导航。
- **保存时自动重建**:查看源文件并自动触发构建+部署+重新启动。
- **多目标配置**:支持不同的CPU目标(68000、68020、68040)和内存配置。
- **单元测试框架**:~~在Amiga上运行并通过桥接器报告结果的轻量级测试线束~~ *(完成-- `ab_test_begin`/`AB_ASSERT`/`ab_test_end` + `amiga_run_tests` MCP工具)*.
### 协议与通信
- **二进制协议选项**:将文本协议替换为紧凑的二进制格式,以获得更高的吞吐量(特别是对于大型内存转储)。
- **压缩**:压缩大传输(文件读取、内存转储)以减少串行带宽。
- **流量控制**:实施适当的XON/XOFF或硬件流控制,以确保真实硬件的可靠性。
- **校验和/CRC**:~~添加串行数据的完整性检查~~ *(已完成——CRC32文件校验和通过 `amiga_checksum`)*仍然需要:每条消息的CRC用于串行链路的完整性。
- **多串口**:支持多个串行连接,用于并行调试联网的Amiga设置。
### Web用户界面
- **可变图形**:绘制随时间变化的变量值(例如,图表空闲内存或CPU使用率)。
- **Sprite编辑器**:使用内存写入的可视化精灵数据编辑器。
- **声音寄存器查看器**:Paula芯片寄存器检查,用于音频调试。
- **暗/亮主题切换**:目前只有黑暗。
### 客户端库
- **自动变量推送**:无需手动即可在每次心跳时推送所有注册变量的选项 `ab_push_var()` 电话。
- **结构化日志记录**:使用键=值对进行日志记录,以便更容易在主机上进行过滤和搜索。
- **C++支持**:使用RAII包装类以进行自动清理。
- **Lua/REXX脚本**:在Amiga上执行与注册变量和钩子交互的脚本。
### 基础设施
- **真正的硬件支持**:测试和优化真正的Amiga串行端口(在9600-115200波特下活动),而不是模拟器TCP。
- **网络传输**:可选的TCP/IP传输,使用网卡的Amigas的bsdsocket.library(比串行更快)。
- **多客户端web UI**:在具有独立变量视图的单独选项卡/面板中显示不同的客户端。
- **会话录制**:记录所有网桥流量,以便以后回放和分析。
- **CI/CD管道**:git推送触发的自动构建+部署+测试周期。
- **VS代码扩展**:将web UI和MCP工具作为内联诊断的扩展引入VS Code。
- **基于ROM的网桥**:将网桥守护进程刻录到自定义Kickstart ROM模块中,以便进行零设置调试。
### AmigaOS集成
- **直觉事件转发**:~~将鼠标点击和键盘事件从主机转发到Amiga~~ *(完成-- `amiga_input_key`, `amiga_input_mouse_move`, `amiga_input_click`)*.
- **剪贴板桥**:~~在主机和Amiga之间共享剪贴板~~ *(已完成——web UI中的剪贴板桥+CLIPGET/CLIPSET协议)*.
- **分配管理**:~~在主机中创建/修改/删除Amiga分配~~ *(完成-- `amiga_list_assigns`, `amiga_assign` +分配协议+web UI分配管理器)*.
- **首选项编辑**:~~从主机读取和写入AmigaOS首选项文件~~ *(已完成--web UI中的首选项编辑器)*.
- **包管理器**:通过网桥安装/删除Amiga软件的简单系统。