超級任天堂程式設計/SPC700 參考資料

SPC700 是索尼的協處理器,用於協調超級任天堂音訊。一旦它被超級任天堂 CPU 傳送的資料和程式碼初始化,它就會操作其附帶的數字訊號處理器 (DSP) 的狀態,該處理器會產生輸出音訊。
SPC700 擁有 64KB 的記憶體,用於儲存程式碼和資料。在這個記憶體空間中,還包含記憶體對映暫存器,用於與超級任天堂 CPU、DSP 和三個可用的定時器進行通訊。
SPC700 有 6 個暫存器:
- A - 一個 8 位累加器
- X & Y - 8 位索引暫存器
- SP - 8 位堆疊指標
- PC - 16 位程式計數器
- PSW - 8 位“程式狀態字”,用於儲存狀態標誌
Y 和 A 暫存器可以組合成一個 16 位暫存器,其中 Y 是高位元組,用於某些操作。
DSP 有 8 個通道,每個通道可以播放 16 位聲音。所有 8 個通道都具有獨立的左右立體聲音量,可以在不同的音高下播放,並且可以應用攻擊-衰減-持續-釋放 (ADSR) 包絡。可以將一個白噪聲源設定為替換任何 8 個通道上的取樣資料。此外,DSP 可以對音訊應用回聲。16 位音訊樣本從 SPC700 的 64KB 記憶體空間中讀取,它們以壓縮的 4 位有損格式儲存。
$0000-$00EF- 直接頁 0$00F0-$00FF- 記憶體對映硬體暫存器$0100-$01FF- 直接頁 1$0100-$01FF- 潛在的堆疊記憶體$FFC0-$FFFF- IPL ROM
許多指令提供一種定址模式,用於訪問“直接頁”中的 1 位元組記憶體地址。這種定址模式會生成更短的位元組碼,這可能導致執行速度更快。直接頁的高位元組是 $00 或 $01,對應於 PSW 暫存器中的 P 位。
堆疊指標的低位元組由 SP 暫存器指定;高位元組始終是 $01。堆疊指標在 IPL ROM 重啟時設定為 $01EF,並向下增長。
重啟時,64KB RAM 末尾的 64 位元組記憶體塊被初始化為 IPL ROM 的內容,這是執行開始的地方。IPL ROM 中的程式碼將堆疊指標設定為 $01EF,將記憶體從 $0000 清零到 $00EF,然後等待來自超級任天堂的透過輸入埠的資料。
| 地址 | 描述 | 讀/寫 |
|---|---|---|
$00F0 |
未知 | ? |
$00F1 |
控制 | 寫 |
$00F2 |
DSP 讀/寫地址 | 讀/寫 |
$00F3 |
DSP 讀/寫資料 | 讀/寫 |
$00F4 |
埠 0 | 讀/寫 |
$00F5 |
埠 1 | 讀/寫 |
$00F6 |
埠 2 | 讀/寫 |
$00F7 |
埠 3 | 讀/寫 |
$00FA |
定時器設定 0 | 寫 |
$00FB |
定時器設定 1 | 寫 |
$00FC |
定時器設定 2 | 寫 |
$00FA |
定時器計數器 0 | 讀 |
$00FB |
定時器計數器 1 | 讀 |
$00FC |
定時器計數器 2 | 讀 |
Anomie 對此暫存器進行了一些測試。romhacking.net 上的一份文件對此進行了描述。
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| X | X | PC32 | PC10 | X | ST2 | ST1 | ST0 |
- PC32 - 在此位寫入 1 將使埠 2 和 3 的輸入歸零
- PC10 - 在此位寫入 1 將使埠 1 和 0 的輸入歸零
- ST0-2 - 這些用於啟動定時器。
Warning: Writing to this register will always restart/stop all of the timers.
寫入 $00F2 會設定要訪問的 DSP 暫存器的地址。寫入 $00F3 會更改指向的暫存器的值。從 $00F3 讀取將返回指向的暫存器的值。允許向 $00F2 寫入一個字,它可以用於同時設定地址和向暫存器寫入一個值。
從這些埠讀取將為您提供超級任天堂在 $2140-$2143 設定的值。寫入這些暫存器的值可以透過超級任天堂使用相同的 $2140-$2143 檢視。可以使用控制暫存器清除這些埠的輸入。
暫存器 $00FA-$00FC 用於設定定時器速率。定時器 0 和 1 的解析度為 125 微秒。定時器 2 的解析度更精細,約為 15.6 微秒。$00FD-$00FF 是包含定時器溢位計數的 4 位暫存器。以下是定時器的工作方式。
每個定時器都有一個內部計數器,它在每個時鐘輸入時遞增。如果它等於 $00FA-$00FC 中的數字(取決於您使用的是哪個定時器),相應的計數器暫存器將遞增,內部計數器將復位。計數器暫存器 ($00FD-$00FF) 是 4 位暫存器,只能讀取。從它們讀取會導致它們復位為零。如果您沒有在有限的時間範圍內讀取計數器,它們也會溢位並被清除為零。必須在設定 $00FA-$00FC 暫存器之前停止定時器。要啟動定時器,請寫入控制暫存器位 0-2。要停止定時器,請復位這些位。請注意,寫入控制暫存器將重新啟動現有的定時器。
DSP 使用一種特殊的 ADPCM 編碼聲音格式。樣本由一系列 9 位元組的壓縮塊組成。每個塊包含 16 個 4 位樣本和一個 1 位元組的頭部。16 位樣本將獲得 9/32 的壓縮比,但 8 位樣本必須在壓縮之前膨脹為 16 位(使其僅獲得 9/16 的壓縮比)。每個塊的第一個位元組包含頭部。
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| 範圍 | 濾波器 | 迴圈 | 結束 | ||||
- 範圍 - 這是資料的移位值。它可以是 0-12。
- 濾波器 - 這選擇解碼過程中使用的濾波器係數。(見下表)
- 迴圈 - 此位將塊標記為迴圈內的塊。此位的確切功能未知,但我檢查過的某些商業 SPC 樣本將此位設定為樣本中的所有塊。
- 結束 - 此位將塊標記為樣本中的最後一個塊。如果 DSP 通道到達此塊,它將終止或跳轉到迴圈點。
每個塊包含 8 位元組的樣本資料(16 個帶符號的 4 位樣本)。每個位元組中的較高 nibble 包含在較低 nibble 中解碼的樣本之前要解碼的樣本。
以下公式用於估計 DSP 的 16 位輸出。設 y 和 z 為最後兩個先前解碼的樣本。'a' 和 'b' 是由頭部位元組的第 2-3 位選擇的濾波器係數。
sample = S + ay + bz S is the shifted data: S = (4-bit sample) << Range
DSP 使用最少的移位操作執行此過程;輸出精度不會很完美。它還將高斯插值應用於輸出。
| 濾波器# | a | b |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 15/16 | 0 |
| 2 | 61/32 | -15/16 |
| 3 | 115/64 | -13/16 |