通过 8086 汇编中的硬件端口 201h 进行操纵杆编程

Joystick programming via hardware port 201h in 8086 assembly

我刚在 eBay 上买了一个旧的 2 轴 6 键游戏手柄,我打算在我正在为 8086 汇编语言的 MS-DOS 编写的游戏中添加支持。

在等待它交付的同时,我一直在研究操纵杆和基于游戏端口的控制器的低级编程。我找不到任何专门针对游戏手柄编程的文档,只有操纵杆。我假设它们在硬件级别上的处理方式与操纵杆相同,但我可能错了。

这里有一张 link 游戏手柄的图片,只是为了表明它与操纵杆完全不同。
https://i.ebayimg.com/images/g/9xsAAOSwBjdaOHFo/s-l1600.jpg

据我所知,您可以通过硬件端口 201h 访问游戏端口,但就输入位的实际含义而言,我无法理解文档的内容。

这个link描述了位:http://docs.huihoo.com/help-pc/hw-game_port.html

首先它只提到了2个按钮。如果控制器有 6 个按钮怎么办?另外,"joystick a, x coord (0 = timing active)" 是位 0 的描述。好的,但是您实际上在哪里收集 X 坐标?这似乎只是告诉你计时是活跃的还是不活跃的。 是脉冲的时间长短决定X坐标吗?

这个 link 提到 int 15h 函数 84 提供了一种更简单的访问操纵杆的方法,但我认为它只有 returns 4 个按钮输入,每个操纵杆 2 个。

http://www.fysnet.net/joystick.htm

我宁愿直接从端口 201h 收集输入,也不愿使用 BIOS 服务。只是为了了解它是如何工作的。

From what I can find, you access the game port via hardware port 201h, but I can't understand what the documentation is getting at as far as what the input bits actually represent.

我假设操纵杆使用 RC ("resistor/capacitor") 电路,其中操纵杆的 X 或 Y 控件的位置会影响电阻,从而影响电容器充电所需的时间.当电容器的电荷达到一定水平时,它会设置 "timing active" 位,当电容器充满电时,下一次会设置 drained/discharged 位。最终结果是,通过定期重复读取(例如)"joystick a, x coord" 并测量 "bit first became set" 到 "bit became unset again" 之间的时间,它会告诉您操纵杆(可变)电阻器的位置英寸

不要忘记这些事情是出了名的不准确。您必须在使用前校准操纵杆(使用通常涉及测量 "dead center" X 和 Y 值的序列,然后测量 "top right" X 和 Y 值以及 "bottom left" X 和 Y 值,然后在中间附近定义某种死区;在完成这个痛苦的校准程序后,您将玩 15 分钟的游戏,导致可变电阻器稍微升温并停止校准;通常(由于 dust/wear 在通常 cheap/low 质量可变电阻器内的碳轨道上)使用几天后,操纵杆会变得不稳定。当然,这一切都假设可变电阻器实际上与 PC 操纵杆端口兼容(例如具有相同曲线的相同电阻范围),并且没有理由假设游戏手柄中的可变电阻器完全兼容。

另请注意,(当时)大多数人并没有使用游戏杆端口(只是使用了没有准确性或可靠性问题的鼠标),并且最初提供游戏杆端口的少数制造商停止了几十年前就很麻烦(每个人都转而使用 USB),因此现在很难找到任何真正具有可用操纵杆端口的硬件。我假设 "BIOS int 15h function 84" 也会发生同样的情况(BIOS 制造商三十年来一直没有费心去实现它,而功能只是 returns "carry flag set" 或 "everything always zeros") .

First of all it only mentions 2 buttons. What if the controller has 6 buttons?

原本只打算支持每个摇杆 2 个按钮;但也旨在支持 2 个操纵杆。这意味着您应该能够连接 4 个按钮(2 个按钮作为 "joystick a buttons",另外 2 个按钮作为 "joystick b buttons");只要您自己编写软件并且不要期望任何现有的旧游戏都支持它。对于超过 4 个按钮,操纵杆端口将不起作用,但也许您可以将按钮连接到其他东西(例如,使用合适的缓冲逻辑和上拉电阻;将它们连接到并行端口或串行端口中的控制线)。