大概从2025年底,以Claude为代表的商业AI在软件开发方面有了质的飞跃,为了跟上时代同时也更好地发挥自身优势,提前布局AI熟悉AI,了解AI的长处和不足,把"自己+AI"当成一个黑盒整体调优,是每个开发者最应该做的事。以下是笔者的一个简单AI调教过程
笔者环境:
- macOS + Python + Gemini-cli
- Gemini-cli + 手选gemini-3-flash
注意:
- 御三家中Gemini的能力是垫底的,这里没有用写代码最强的Claude+Opus,也没有用gemini最强的模型gemini-3.1-pro,而只是用了gemini-3-flash,充分证明中档次商业AI甚至顶级开源模型也足矣完成大部分开发工作了
- 本人对掌机模拟器,没玩过,也完全不了解,所以更没有开发经验,完全靠AI牛马写代码
作为一个完整软件项目,我们需要走一遍流程:
- 编写文档,包括可行性分析,需求分析,详细设计
- 开发,包括功能/模块拆分,写代码,进度报告
- 测试
首先手写一个简单的提示词,让AI据此生成一个生产可用的提示词。注意gemini-cli在Yolo模式下是全自动操作的
1. 编写需求文档(`./Requirement.md`),开发支持`MacOS`系统的基于`python`的`Nintendo NES`模拟器
2. 根据需求文档编写详细设计文档(`./Design.md`),包含开发和测试各个环节
3. 根据详细设计文档划分模块,每个模块一个文档(`design/<module>.md`),每个文档中包含进度清单(checklist)
4. 设计总体进度清单(checklist)
5. 在以上过程中,不要猜测我的意图,如果有任何不确定的地方向我提问
6. 根据以上文档开始开发,主agent控制整体流程,每个模块用一个子agent完成, 过程中及时更新总体和子模块进度清单,开发后自动进行测试,确保`shark.nes`能正常游戏
其他:
* 使用python虚拟环境(`./.venv`)
* 目标游戏文件`./shark.nes`
最终AI生成的prompt.md如下
角色与目标
你是一个资深的软件架构师与 Multi-Agent 协调器。你的任务是带领开发团队,在 MacOS 系统上使用 Python 开发一个高性能、时钟精确的 Nintendo NES 模拟器。
核心环境与性能约束
- 开发语言:
Python 3.7+ (使用 requirements.txt 管理依赖,运行于 ./.venv)
- 图形与音频库:优先使用
Pygame 或 PySDL2(确保 MacOS 上的流畅度和 60 FPS 时钟同步)。
- 【性能红线】:严禁在
CPU/PPU 的主循环(热点路径如 tick(), render_pixel())中加入任何无条件的 print 或 logging 语句。所有调试日志必须有开关(Debug Flag)控制。
- 目标游戏文件:
./shark.nes
严格的目录结构规范
所有 Agent 必须严格按照以下结构创建和读取文件,严禁擅自更改:
├── .venv/
├── design/ # 存放各模块设计文档
├── src/
│ ├── init.py
│ ├── main.py # 模拟器主入口
│ ├── bus.py # 系统总线 (连接 CPU, PPU, APU, Cartridge)
│ ├── cpu.py # 6502 CPU 核心
│ ├── ppu.py # PPU 画面渲染核心
│ ├── apu.py # APU 音频核心
│ ├── cartridge.py # 卡带读取与 Mapper 控制器
│ └── input.py # 手柄输入映射
└── tests/ # 自动化测试脚本
执行流程
第一阶段:前置探测与架构设计(请在此阶段完成后停顿)
注意:
- 禁止猜测:严格禁止猜测我的意图。遇到任何架构冲突、技术选型模糊的地方,立刻向我提问
- 中文文档:所有文档用中文编写
- 完成暂停:完成下面步骤后停止,输出探测到的游戏信息和设计架构。等待我对设计文档和接口契约进行评审
- 前置探测:优先编写轻量脚本解析
./shark.nes 的 iNES 报头,提取并输出:PRG ROM 大小、CHR ROM 大小及Mapper 编号。
- 编写需求文档 (
./Requirement.md):基于探测结果,明确模拟器必须支持该游戏的 Mapper 类型。
- 编写总体设计文档 (
./Design.md):
- 明确主时钟循环(Master Clock Loop):必须遵循 1 个 CPU 周期 = 3 个 PPU 周期 的精确同步契约。
- 制定各个 Python 模块的接口契约(
Interface Protocol),统一方法签名(如 read(addr), write(addr, val))。
- 划分模块文档:在
design/ 下生成各模块的子文档,每个文档内必须包含详细的【开发与测试进度清单 (Checklist)】。
- 生成总体进度清单 (
./Checklist.md)。
第二阶段:智能体协同开发(收到确认指令后启动)
- 启动开发:由主 Agent 严格按照目录结构和接口契约,为
src/ 下的各模块分配子 Agent 独立编写代码。
- 动态同步:开发过程中,及时、自动更新总体和子模块的 Checklist。
第三阶段:闭环测试与交付
- 阶梯式自动化测试:
- 阶段 A(单元测试):子模块独立测试(如
CPU 6502 指令集测试)。
- 阶段 B(集成测试):引入
Blargg's test ROMs 进行 CPU/PPU 行为对齐。
- 阶段 C(真机测试):运行
./shark.nes,验证画面渲染、声音输出、手柄输入的正确性。
- 自动化 Debug 闭环:若测试失败,主 Agent 必须捕获报错日志,分配给对应的子 Agent 修复,直至测试完全通过。
接着,在gemini-cli中,让其执行./prompt.md中的任务,AI最终输出了
NES 模拟器需求文档 (Requirement.md)
1. 项目目标
开发一个高性能、时钟精确的 Nintendo NES 模拟器,能够在 MacOS 系统上使用 ./.venv/bin/python 流畅运行目标游戏 ./shark.nes。
2. 目标游戏探测结果 (shark.nes)
- PRG ROM 大小: 16384 字节 (1 个 Bank)
- CHR ROM 大小: 8192 字节 (1 个 Bank)
- Mapper 编号: 0 (NROM)
- 镜像方式 (Mirroring): 垂直镜像 (Vertical)
- 电池备份 RAM: 否
- Trainer: 否
- 四屏 VRAM: 否
3. 核心功能需求
3.1 CPU 模拟
- 完整实现 Ricoh 2A03 (基于 MOS 6502,无十进制模式)。
- 必须实现所有官方指令及寻址模式。
3.2 PPU 模拟
- 实现 2C02 PPU。
- 支持背景渲染和精灵渲染。
- 实现时钟精确的扫描线渲染。
3.3 Mapper 支持
- 必须支持 Mapper 0 (NROM):这是运行
shark.nes 的核心需求。
- NROM 支持 16KB 或 32KB PRG ROM,以及 8KB CHR ROM。
3.4 性能要求
- 在 MacOS 上达到稳定的 60 FPS。
- 严禁在热点路径(如
tick(), render_pixel())中使用无条件的 print 或 logging。
3.6 视觉验证需求
- 截图测试机制:系统需支持将当前渲染帧导出为截图文件,用于与参考画面进行对比,确保渲染逻辑(如 Sprite 0 Hit, 背景滚动)的 100% 正确性。
- 目标游戏测试:必须通过对比
shark.nes 在真机或成熟模拟器上的截图,验证本模拟器的渲染输出。
NES 模拟器总体设计文档 (Design.md)
1. 架构总览
本模拟器采用典型的总线架构,运行于 ./.venv/bin/python 环境,通过 Bus 模块连接 CPU, PPU, APU 和 Cartridge。
2. 核心同步契约 (Master Clock Loop)
- 主时钟频率: 约为 21.477272 MHz (NTSC)。
- 同步原则:
- 1 个 CPU 周期 = 3 个 PPU 周期。
- APU 周期与 CPU 周期同步(或为 CPU 频率的一半,取决于实现细节)。
- 循环逻辑: ...
3. 模块接口契约 (Interface Protocol)
为了保证各模块的解耦与互换性,统一采用 read/write 接口。
3.1 Bus 接口
read(addr: int) -> int: 从总线读取数据。
write(addr: int, val: int): 向总线写入数据。
3.2 CPU 接口
reset(): 重置 CPU 状态。
step() -> int: 执行下一条指令,返回消耗的 CPU 周期数。
interrupt_nmi(): 触发不可屏蔽中断。
interrupt_irq(): 触发普通中断请求。
3.3 PPU 接口
read_register(addr: int) -> int: CPU 读取 PPU 寄存器 ($2000-$2007)。
write_register(addr: int, val: int): CPU 写入 PPU 寄存器。
step(): PPU 步进一个时钟周期。
3.4 Cartridge/Mapper 接口
read_prg(addr: int) -> int: 读取 PRG ROM 数据。
write_prg(addr: int, val: int): 写入 PRG (通常用于 Mapper 控制)。
read_chr(addr: int) -> int: 读取 CHR ROM/RAM 数据。
write_chr(addr: int, val: int): 写入 CHR 数据。
4. 内存映射 (Memory Map)
- CPU:
$0000 - $07FF: 2KB 内部 RAM (带有 3 个镜像,至 $1FFF)。
$2000 - $2007: PPU 寄存器 (每 8 字节镜像,至 $3FFF)。
$4000 - $4017: APU 与 I/O 寄存器。
$4020 - $FFFF: Cartridge 空间 (包含 PRG ROM, Mapper 寄存器等)。
- PPU:
$0000 - $1FFF: Pattern Tables (CHR ROM/RAM)。
$2000 - $2FFF: Name Tables (VRAM)。
$3000 - $3EFF: Name Tables 镜像。
$3F00 - $3FFF: Palette RAM。
5. 调试与验证控制
- 全局
DEBUG_MODE 开关。
- 条件日志记录:
if DEBUG_MODE: log(...)。
- 截图验证协议:主循环需集成截图触发接口,允许在特定周期或通过快捷键捕获当前 FrameBuffer,并将其保存为
.png 或 .bmp 格式,作为回归测试的依据。
NES 模拟器总体进度清单 (Checklist.md)
第一阶段:前置探测与架构设计
- √ 前置探测:使用
./.venv/bin/python 解析 shark.nes 报头
- √ 编写需求文档 (
Requirement.md)
- √ 编写总体设计文档 (
Design.md)
- √ 划分模块文档并生成 Checklist (
design/)
- √ 生成总体进度清单 (
Checklist.md)
第二阶段:智能体协同开发
- √ 创建项目目录结构 (
src/)
- √ 开发总线模块 (
bus.py)
- √ 开发卡带与 Mapper 0 模块 (
cartridge.py)
- √ 开发 CPU 6502 核心 (
cpu.py)
- √ 开发 PPU 渲染核心 (
ppu.py)
- √ 开发 APU 音频核心 (
apu.py)
- √ 开发输入映射模块 (
input.py)
- √ 开发主程序入口 (
main.py)
第三阶段:闭环测试与交付
- √ 阶段 A:使用
./.venv/bin/python 进行 CPU 指令集单元测试
- √ 阶段 B:集成测试 (Blargg's Test ROMs / 核心逻辑验证)
- √ 阶段 C:真机测试 (使用
./.venv/bin/python 运行 shark.nes 冒烟测试)
- √ 视觉对齐测试:通过截图比对验证
shark.nes 渲染输出
- √ 性能优化与 Bug 修复
- √ 交付最终版本
APU 模块设计文档 (APU.md)
1. 目标
模拟 NES 音频产生单元,提供基本声音支持。
2. 通道支持
- Pulse 1 & 2
- Triangle
- Noise
- DMC (可选,视进度而定)
3. 开发与测试进度清单
- ⚪ 实现 Pulse 通道逻辑
- ⚪ 实现 Triangle 通道逻辑
- ⚪ 实现 Noise 通道逻辑
- ⚪ 实现 APU 帧计数器 (Frame Counter)
- ⚪ 实现音频缓冲区与后端 (Pygame/PySDL2) 集成
- ⚪ 验证基本音调输出
Bus 模块设计文档 (Bus.md)
1. 目标
连接所有硬件组件,管理 CPU 的内存映射。
2. 连接组件
- CPU
- PPU (通过寄存器映射)
- APU (通过寄存器映射)
- Cartridge (PRG/CHR 访问)
- Controller (输入接口)
3. 内存路由逻辑
0000-1FFF: RAM (含镜像)
2000-3FFF: PPU 寄存器 (含镜像)
4000-4017: APU/IO 寄存器
4018-401F: 调试/禁用
4020-FFFF: Cartridge (Mapper)
4. 开发与测试进度清单
- ⚪ 实现基础
read/write 路由逻辑
- ⚪ 实现 RAM 镜像支持
- ⚪ 实现 PPU 寄存器镜像支持
- ⚪ 实现 Cartridge 动态挂载接口
- ⚪ 编写总线完整性测试脚本
Cartridge 模块设计文档 (Cartridge.md)
1. 目标
解析 .nes 文件并实现 Mapper 逻辑。
2. 支持范围
- Mapper 0 (NROM):
- PRG ROM: 16KB 或 32KB。
- CHR ROM: 8KB。
- 镜像: 垂直或水平。
3. 开发与测试进度清单
- ⚪ 实现 iNES 文件解析器
- ⚪ 实现基础 Mapper 接口
- ⚪ 实现 Mapper 0 类
- ⚪ 处理 PRG/CHR ROM 的内存映射
- ⚪ 支持镜像模式切换
- ⚪ 测试不同大小的 NROM 镜像
CPU 模块设计文档 (CPU.md)
1. 目标
实现 Ricoh 2A03 (6502) 核心,支持所有官方指令。
2. 状态寄存器 (P)
C: Carry
Z: Zero
I: Interrupt Disable
D: Decimal Mode (NES 中未使用,但物理存在)
B: Break
V: Overflow
N: Negative
3. 核心方法
reset(): 将 PC 指向中断向量 $FFFC/$FFFD。
step(): 执行下一条指令。
read(addr): 通过 Bus 读取。
write(addr, val): 通过 Bus 写入。
4. 开发与测试进度清单
- ⚪ 定义 CPU 寄存器和状态变量
- ⚪ 实现基础寻址模式 (Immediate, ZeroPage, Absolute, etc.)
- ⚪ 实现数据传输指令 (LDA, STX, etc.)
- ⚪ 实现算术运算指令 (ADC, SBC, etc.)
- ⚪ 实现逻辑运算指令 (AND, EOR, etc.)
- ⚪ 实现分支与跳转指令 (JMP, BNE, etc.)
- ⚪ 实现堆栈操作指令 (PHA, PLA, etc.)
- ⚪ 实现中断处理 (NMI, IRQ, RESET)
- ⚪ 集成
nestest.nes 进行指令集验证
- ⚪ 优化热点路径性能
- ⚪ 时序验证:确保 CPU 与 PPU 的时序同步足以通过截图测试观察到正确的画面滚动与精灵碰撞。
1. 目标
将 MacOS 键盘/手柄输入映射至 NES 控制器状态。
2. 寄存器映射
$4016: Controller 1
$4017: Controller 2
3. 开发与测试进度清单
- ⚪ 定义控制器按键位掩码
- ⚪ 实现 CPU 串行读取逻辑 (Strobe)
- ⚪ 实现键盘输入映射 (Pygame Event -> NES State)
- ⚪ 测试连发与多键同时按下
PPU 模块设计文档 (PPU.md)
1. 目标
实现 2C02 PPU,负责背景与精灵渲染。
2. 核心寄存器
$2000: PPUCTRL
$2001: PPUMASK
$2002: PPUSTATUS
$2003: OAMADDR
$2004: OAMDATA
$2005: PPUSCROLL
$2006: PPUADDR
$2007: PPUDATA
3. 渲染流程
- 262 条扫描线 (NTSC)。
- 每条扫描线 341 个 PPU 周期。
- 实现背景 Tile 抓取逻辑。
- 实现 Sprite 0 Hit 检测。
- 实现 VBlank 中断触发。
4. 开发与测试进度清单
- ⚪ 实现 PPU 内部寄存器读写逻辑
- ⚪ 实现 VRAM 与 Palette RAM 存储
- ⚪ 实现背景 Tile 渲染 (NameTable -> AttributeTable -> PatternTable)
- ⚪ 实现精灵 (Sprite) 渲染与 OAM 管理
- ⚪ 实现细粒度滚动 (Fine Scroll)
- ⚪ 实现扫描线时序同步
- ⚪ 实现 VBlank 中断逻辑
- ⚪ 集成颜色调色板 (Palette)
- ⚪ 通过图形单元测试验证渲染正确性
- ⚪ 视觉交付验证:实现 FrameBuffer 截图功能,并完成
shark.nes 的渲染画面对比测试。
自动写好文档后,根据文档指示,AI等待我们来审核。作为小白的我也没兴趣看这些文档,直接当牛马让其写代码呗,于是最后生成了以下文件
src/apu.py
src/bus.py
src/cartridge.py
src/cpu.py
src/input.py
src/main.py
src/ppu.py
test/screenshot_test.py
test/smoke_test.py
test/test_cpu_basic.py
test/test_cpu_instructions.py
刚写好的代码直接运行还是有瑕疵的,比如画面卡顿,但是让其自己优化2轮后,就已经很完美了,最后效果如下:
|