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

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

我开始在空闲时间为一个潜在的 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 读取将返回 b0 中移位寄存器的最低有效位并导致寄存器移位;
  • 对于控制器 2,$4017 执行等效的读取和移位。

输入按 A、B、选择、开始、向上、向下、向左、向右的顺序返回。

因此,该合同的第一部分不能真正整理太多。您不可避免地会看到以下内容:

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

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

此外,不幸的是,第 1 位到第 7 位不是 0。所以例如您不能只从 4016 美元起 ORA 并一次获得一点结果。在这种情况下,没有一个非官方的操作码在进行方便的加载和与操作时似乎有用。

因此,如果您想将结果累积到 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,8
    nextBit $4016 controller1State
    nextBit $4017 controller2State
NEXT

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?