0

我开始在我的休息时间为一个潜在的 NES 游戏项目学习 6502 组装,我在设置读取控制器输入时遇到了一些麻烦。我的背景是 C,所以我熟悉内存及其工作原理,但汇编中的流控制仍然让我无法理解。

因为我是新手,所以我想我应该从简单开始并使用https://www.vbforums.com/showthread.php?858965-NES-6502-Programming-Tutorial-Part-5中描述的逐个按钮方法-控制器命令。这很好用,但它确实是重复和罗嗦的。

有没有更优雅的方式来做这不完全超出我的能力?在没有帮助的情况下,我对集成其他来源的代码知之甚少。

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

感谢您的时间。

4

1 回答 1

2

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会有一个很好的宏编译器,宏编译器的工作是让你在不复制和粘贴的情况下拼出重复的部分。

于 2021-02-28T19:15:02.723 回答