让Codex修复了8年前写的NES游戏模拟器的Bugs

陪她去流浪 桃子 阅读次数:24

两个问题:图形处理器有奇怪的显示问题、没有音乐处理器。

图形处理器奇怪的形变

当我看到下面这个形变的鸭子时还是很震惊的。

那时候还没有代码编码助手,只是不停地看手册堆表,完全不知道错在哪里。没想到是抄错了指令表?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
taones (master) → git diff
diff --git a/cpu.go b/cpu.go
index 6fecf45..77f692c 100644
--- a/cpu.go
+++ b/cpu.go
@@ -42,7 +42,7 @@ type OpCode struct {
 
 var opcodesTable = [...]OpCode{
        // adc
-       {0x69, "ADC", 2, 3, 0, amImmediate},
+       {0x69, "ADC", 2, 2, 0, amImmediate},
        {0x65, "ADC", 2, 3, 0, amZero},
        {0x75, "ADC", 2, 4, 0, amZeroX},
        {0x6D, "ADC", 3, 4, 0, amAbsolute},
@@ -57,12 +57,12 @@ var opcodesTable = [...]OpCode{
        {0x35, "AND", 2, 4, 0, amZeroX},
        {0x2D, "AND", 3, 4, 0, amAbsolute},
        {0x3D, "AND", 3, 4, 1, amAbsoluteX},
-       {0x39, "AND", 2, 4, 1, amAbsoluteY},
+       {0x39, "AND", 3, 4, 1, amAbsoluteY},
        {0x21, "AND", 2, 6, 0, amIndexedIndirect},
        {0x31, "AND", 2, 5, 1, amIndirectIndexed},
 
        // asl
-       {0x0A, "ASL", 1, 3, 0, amAccumulator},
+       {0x0A, "ASL", 1, 2, 0, amAccumulator},
        {0x06, "ASL", 2, 5, 0, amZero},
        {0x16, "ASL", 2, 6, 0, amZeroX},
        {0x0E, "ASL", 3, 6, 0, amAbsolute},

问题主要不在 PPU sprite 位序,而在 CPU 指令表。

我修了 cpu.go 里的三个错误表项:

  • ADC #imm 周期从 3 改成 2
  • AND $addr,Y 长度从 2 改成 3
  • ASL A 周期从 3 改成 2

其中 AND $addr,Y 长度错最危险,会让 PC 少前进 1 字节,后续执行流可能跑偏,间接导致 OAM/图形数据异常;两个周期错会让 CPU/PPU 时序偏移,也容易出现 sprite 或画面更新时机问题。

错了3️⃣条指令,但是问题居然并不是特别明显:

  • 其中两条只是影响了指令周期,问题不大。
  • 而指令长度会完全影响指令指针(PC)后续的所有指令,CPU直接跑飞……

增加音乐处理器

不然的话,音乐的模拟怎么也不应该缺席。不会只写了个开头就八年没再动过了。当然,现在更不会有时间去研究了。

前几天1才报怨自己没时间再去研究,没想到反手就让Codex给写了一个。代码全部是Codex写的,我一行没写,全程不到🔟️分钟。

结语

太好了,现在终于勉强算得上是一个没有遗憾的NES模拟器了。