在 ca65 上读取 NES (6502) 组件的控制器输入的优雅方法是什么?

What's an elegant way to read controller input for NES (6502) assembly on ca65?

我开始在业余时间为一个潜在的 NES 游戏项目学习 6502 汇编,但我在设置读取控制器输入时遇到了一些问题。我的背景是C,所以我熟悉内存和它的工作原理,但汇编中的流程控制仍然逃避我。

因为我是新手,所以我想我应该从简单开始,使用 https://www.vbforums.com/showthread.php?858965-NES-6502-Programming-Tutorial-Part-5-Controller-Commands 中描述的逐个按钮方法。这工作正常,但它确实是重复和冗长的。

是否有更优雅的方法来完成这项工作,而且不完全超出我的能力范围?如果没有一些帮助,我不知道如何集成其他来源的代码。

https://wiki.nesdev.com/w/index.php/Controller_reading_code 看起来很有前途,但我对它的了解还不够多,无法使用它。

感谢您的宝贵时间。

NES 上的控制器是串行设备,每个都包含一个内部移位寄存器。阅读控制器:

  • 将 1 设置为 $4016 的 b0;这将导致控制器开始连续对其输入进行采样并重新加载其 8 位移位寄存器;
  • 将 0 设置为 $4016 的 b0;这将导致控制器停止对其输入进行采样,并停止重新加载其移位寄存器;
  • 对于控制器 1,每次从 $4016 读取都会 return b0 中移位寄存器的最低有效位,并导致寄存器移位;
  • 对于控制器 2,$4017 执行等效的读取和移位操作。

输入 return 的顺序为 A、B、Select、开始、上、下、左、右。

因此,该合同的第一部分真的不能整理太多。你不可避免地会看到类似的东西:

; Get current controller inputs into their shift registers.
LDA #1
STA 16
LDA #0
STA 16

假设您对所有八个输入都感兴趣,并且为了示例只对控制器 1 感兴趣,那么肯定会从 4016 美元中至少读取八个。由于它也是用于重置移位寄存器中的内容的选通信号,因此它们最好是只读的——不能写入或读取-修改-写入。

此外,不幸的是,第 1 位到第 7 位不是 0。例如您不能仅从 4016 美元起 ORA 并一次获得一点结果。在这种情况下,none 的非官方操作码似乎有助于进行方便的加载与运算。

因此,如果您想将结果累加到 A 中,那么事情不会变得那么优雅。

在您提供的 link 中:

vbforums.com的建议是从$4016加载八次,每次测试最低位,并在该循环中做出适当的反应。它使用 AND #1(设置 Z)和 BEQ(测试它)来测试加载后的位,而 LSR(将位 0 ​​移动到进位)和 BCC (测试携带)可能会更优雅,因为它更紧凑。

NesDev Wiki link 相反,通过进位将游戏手柄输入的每一位滚动到另一个字节,因此您最终在内存中得到一个 8 位值,该值等于曾经在控制器中的值移位寄存器,您可以在闲暇时对其进行测试和操作。

如果您只是担心 'repetitive and wordy' 那么我认为问题可能出在您的工具上,而不是硬件上 — 寻找宏汇编器。它们中的许多都比 C 的预处理器高出一两步,因此您最终可能会编写与更类似的步骤序列相同的步骤:

MACRO nextBit source destination {
    lda source        ; Read next bit from controller.
    lsr               ; Move bit to carry.
    ror destination   ; Roll bit from carry to top of local state.
} ENDMACRO

; Get controllers to reload their shift registers.
lda #1
sta 16
lda #0
sta 16

; Copy shift registers to local memory.
FOR n, 0, 8
    nextBit 16 controller1State
    nextBit 17 controller2State
NEXT

这是 BBC Micro 的特定现实汇编器使用的宏语法,几乎可以肯定不是您的汇编器使用的宏语法,因为几乎没有标准化。但是NES会有一个很好的宏编译器,宏编译器的工作就是让你拼出重复的部分而不用复制和粘贴。