$4016 是 手柄1 的选通 ...
此 IO端口 在读写时候有着不同的行为 ...
首先读手柄的状态 ... 要先向 $4016 写 1 此时内部的计数器开始工作并且会为数据流上锁... 表示已经做好准备 ... 此时在往$4016 写0 解锁 数据才能正确读取出来 ...
数据流一共有 24 bit 如图
[img]http://dl.iteye.com/upload/picture/pic/133143/abb4c867-23db-3415-8e75-3776e0f89706.png[/img]
信号用来检测是4端口的接入状态:
%0000:没有连接设备
%0001:只有$4016手柄
%0010:只有$4017手柄 (此段话摘自任天堂产品文件)
对于一般的输入 ... 只要 获取0 - 7 位即可 ...
NES的输入设备流还有一个十分古怪的之处 ... 每次读取只能读取 1 Bit 也就是想要完整的获取手柄的输入必须要读取8次 $4016 ...
6502 伪代码 ...
有心的朋友 看过 NES模拟器的源代码就知道 ... $4016内部有一个计数器 ... 复位之后此计数器被初始化为0 ... 在初始化之后每一次读取计数器都会自增 之后左移 计数器值 ...
高级语言伪代码就是 ...
$4017 同理
此 IO端口 在读写时候有着不同的行为 ...
首先读手柄的状态 ... 要先向 $4016 写 1 此时内部的计数器开始工作并且会为数据流上锁... 表示已经做好准备 ... 此时在往$4016 写0 解锁 数据才能正确读取出来 ...
数据流一共有 24 bit 如图
[img]http://dl.iteye.com/upload/picture/pic/133143/abb4c867-23db-3415-8e75-3776e0f89706.png[/img]
信号用来检测是4端口的接入状态:
%0000:没有连接设备
%0001:只有$4016手柄
%0010:只有$4017手柄 (此段话摘自任天堂产品文件)
对于一般的输入 ... 只要 获取0 - 7 位即可 ...
NES的输入设备流还有一个十分古怪的之处 ... 每次读取只能读取 1 Bit 也就是想要完整的获取手柄的输入必须要读取8次 $4016 ...
6502 伪代码 ...
LDA #$1
STA $4016 ; 写 1 复位设备 此时设备以及准备好并且上锁
LDA #$0
STA $4016 ; 解锁 获取输入设备数据流 此时可以开始获取数据流
LDA $4016 ; 第1次读 获取 A键 的状态
LDA $4016 ; 第2次读 获取 B键 的状态
LDA $4016 ; 第3次读 获取 Select键 的状态
LDA $4016 ; 第4次读 获取 Start键 的状态
LDA $4016 ; 第5次读 获取 上键 的状态
LDA $4016 ; 第6次读 获取 下键 的状态
LDA $4016 ; 第7次读 获取 左键 的状态
LDA $4016 ; 第8次读 获取 右键 的状态
有心的朋友 看过 NES模拟器的源代码就知道 ... $4016内部有一个计数器 ... 复位之后此计数器被初始化为0 ... 在初始化之后每一次读取计数器都会自增 之后左移 计数器值 ...
高级语言伪代码就是 ...
bool isLocked = TRUE ; 数据流锁
uint Counter4016 = 0 ; 移位计数器
UINT InputData ; 输入数据 可以来自 IDirectInput8 也可以来自Win消息回调
BYTE ReadAddr4016 () {
if(isLocked == TRUE)
return 0 ; 如被锁定什么也读不到 直接返回一个无意义的值
else {
return (InputData >> Counter4016) & 1
++Counter4016 ; 每次读取后自增 1 访问下一位数据
}
}
VOID WriteAddr4016(BYTE val){
if(val == 0)
isLocked = FALSE ; 解锁
else (val == 1) {
Counter4016 = 0 ; 初始化计数器 从 第一位开始读取数据流
isLocked = TRUE ; 锁定
}
}
}
$4017 同理