跳至內容

超級任天堂程式設計/手柄輸入

來自華夏公益教科書,開放世界開放書籍

手柄是 SNES 從使用者處獲取輸入的方式。最多可以連線四個手柄到系統,並且還支援特殊控制器(滑鼠超級瞄準鏡 等)。

注意:本教程正在進行中。我對 SNES 還比較陌生,所以請隨時糾正本文件中的任何錯誤。

手柄暫存器

[編輯 | 編輯原始碼]

首先,我們將列出我們將要使用的暫存器

大小 地址 官方名稱 描述
位元組 $4200 NMITIMEN 計數器使能
位元組 $4212 HVBJOY 狀態暫存器
$4218 CNTRL1L & -H 手柄 #1 狀態
$421a CNTRL2L & -H 手柄 #2 狀態
$421c CNTRL3L & -H 手柄 #3 狀態
$421e CNTRL4L & -H 手柄 #4 狀態
位元組 $4016 手柄 #1 舊式狀態
位元組 $4017 手柄 #2 舊式狀態

現在,讓我們更深入地瞭解一下它們

$4200 - NMITIMEN - 計數器使能 n-vh---j

這個暫存器你可能很熟悉。如果你之前做過任何 SNES 編碼,你會發現你可能已經使用過這個暫存器來啟用 VSync 中斷。對於手柄輸入,我們必須確保位 0 ("j") 設定。這告訴 SNES 我們將輪詢其他手柄暫存器。

作為參考,構成我們將在暫存器 $4200 中載入的位元組其餘部分的 n-vh---j 位如下

位名稱 位置 描述
n 7 啟用/停用 NMI
v 5 啟用/停用垂直觸發時的 IRQ
h 4 啟用/停用水平觸發時的 IRQ
j 0 手柄輪詢位

$4212 - HVBJOY - SNES 狀態暫存器 vh-----j

此暫存器用於檢視某些資料是否已準備好從 SNES 中輪詢。在這種情況下,我們只關心位 0 ("j")。如果我們輪詢 $4212 並且位 0 設定,那麼我們知道其他 SNES 手柄暫存器將包含相關資料。但是,如果省略此步驟,通常不會太糟糕。在我將在後面展示的演算法中,跳過了此檢查,但此解釋仍然存在以完整性。

$4218/9 到 $421e/f - 手柄狀態暫存器 hi:bystudlr lo:axlriiii

這些是 16 位暫存器,它們返回連線到 SNES 的每個手柄的按鈕和/或型別狀態。$4218 和 $4219 包含手柄 1 的資料,手柄 2、3 和 4 緊隨其後。位按如下方式排列

位(s) 描述
$4219/b/d/f (hi)
b B 按鈕
y Y 按鈕
s 選擇按鈕
t 開始按鈕
u 向上方向鍵按鈕
d 向下方向鍵按鈕
l 向左方向鍵按鈕
r 向右方向鍵按鈕
$4218/a/c/e (lo)
a A 按鈕
x X 按鈕
l L 按鈕
r R 按鈕
iiii 控制器型別 ID

大多數這些都是不言自明的。如果對應按鈕的位設定,則該按鈕被按下。唯一有點令人困惑的是神秘的 "iiii" 位 - 它們確定連線到埠的控制器型別。基本上,如果它們讀取 0000,則它是一個標準的 SNES 控制器。否則,它是自定義控制器型別或損壞資料。

$4016 和 $4017 - 手柄 1 和 2 舊式狀態

對於這些,你會注意到我省略了每個暫存器的特定位。基本上,這些工作方式與從 NES 讀取狀態的方式完全相同。因此,我認為在此處包含這些資訊是多餘的,除了 $4200 的位 0 必須清除才能以這種方式使用它們。但是,這些暫存器仍然很有用。如果你將 0 寫入 $4016,那麼這兩個暫存器可以用來檢查手柄 1 和 2 是否已連線。在寫入 0 之後(你只需要寫入 $4016,而不是兩個),如果未連線,則從暫存器讀取將返回 0,如果已連線,則返回其他內容。

基本手柄讀取演算法

[編輯 | 編輯原始碼]

當你初始化時

.ENUM $80

	Joy1A	db	;B, Y, Select, Start, Up, Down, Left, Right
	Joy1B	db	;A, X, L, R, iiii-ID
.ENDE

	lda #%10000001	; Enable NMI and Auto Joypad read
	sta NMITIMEN   	; Interrupt Enable Flags

在你的主遊戲迴圈中(或在合適的地方)無需檢查

	lda CNTRL1L     ; $4218
	sta Joy1A
	lda CNTRL1H     ; $4219
	sta Joy1B

但是,在從自動手柄讀取暫存器讀取之前,應測試 HVBJOY 的最低位是否為 0,因為讀取過程需要一些時間才能完成。

華夏公益教科書