NES 上的控制器是串行设备,每个都包含一个内部移位寄存器。要读取控制器:
- 将 1 到 b0 设置为 4016 美元;这将导致控制器开始连续对其输入进行采样并重新加载其 8 位移位寄存器;
- 将 0 设置为 b0 为 4016 美元;这将导致控制器停止对其输入进行采样,并停止重新加载其移位寄存器;
- 对于控制器 1,每次读取 $4016 都会从 b0 中的移位寄存器返回最低有效位并导致寄存器移位;
- 对于控制器 2,4017 美元执行等效的读取和移位。
输入按 A、B、选择、开始、上、下、左、右的顺序返回。
因此,该合同的第一部分并不能真正进行太多整理。你不可避免地会看到类似的东西:
; Get current controller inputs into their shift registers.
LDA #1
STA $4016
LDA #0
STA $4016
假设您对所有 8 个输入感兴趣,并且仅对控制器 1 感兴趣,那么从 4016 美元起肯定会有至少 8 个读取。由于它也是重置移位寄存器中的内容的选通脉冲,因此它们最好是只读的——没有写入或读取-修改-写入。
同样不幸的是,位 1 到 7 为 0 是不正确的。因此,例如,您不能只ORA
从 4016 美元开始一次获得一点结果。在这种情况下,似乎没有任何非官方的操作码在进行方便的加载和与操作时有用。
因此,如果您想将结果累积到 A 中,那么事情就不会那么优雅了。
您提供的链接中:
vbforums.com 的建议是从 $4016 加载八次,每次测试最低位,并在该循环中做出适当的反应。它使用AND #1
(设置 Z)和BEQ
(测试它)在加载后测试位,而LSR
(将位 0 移动到进位)和BCC
(测试进位)可能会更优雅,因为它更紧凑。
NesDev Wiki 链接将手柄输入的每一位通过进位滚动到另一个字节中,因此您最终会在内存中得到一个 8 位值,该值等于控制器移位寄存器中的值,您可以测试和操作在你的空闲时间。
如果您的担忧只是“重复和冗长”,那么我认为问题可能出在您的工具上,而不是硬件上——寻找宏汇编程序。其中许多比 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 $4016
lda #0
sta $4016
; Copy shift registers to local memory.
FOR n, 0, 8
nextBit $4016 controller1State
nextBit $4017 controller2State
NEXT
这是 BBC Micro 的特定实际汇编程序使用的宏语法,几乎可以肯定不是您的汇编程序使用的宏语法,因为几乎没有标准化。但是NES会有一个很好的宏编译器,宏编译器的工作是让你在不复制和粘贴的情况下拼出重复的部分。