超級任天堂程式設計/手柄輸入
手柄是 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,因為讀取過程需要一些時間才能完成。