跳转到内容

超级任天堂编程/超级FX教程

来自维基教科书,为开放世界提供开放书籍

超级FX是一款为SNES设计的定制16位RISC处理器,具有特殊的位图模拟功能。它旨在为SNES带来基本的3D功能。它的编程是用特殊的超级FX汇编语言完成的。每个超级FX游戏都结合了标准的SNES汇编代码和专门编译的超级FX汇编例程,这些例程以二进制数据的形式编码在游戏卡中。它可以在某些条件下与SNES并行运行。每个超级FX游戏卡都有板载RAM,超级FX芯片使用它作为帧缓冲区以及用于它可以与SNES共享的通用操作。

现有标题

[编辑 | 编辑源代码]

超级FX芯片被用于8款已发布的SNES游戏中,在《星际火狐2》(未发布)以及多个技术演示中;其中有2款的二进制文件可供使用。

标题 超级FX版本 ROM大小 游戏卡RAM大小 存档RAM大小
《星际火狐》(PAL: 《星际之翼》) 马里奥芯片 8 MBit 256 KBit
越野赛车 GSU-1 4 MBit 256 KBit
尘土飞扬FX GSU-1 4 MBit 512 KBit
《特技赛车FX》(JP: 《狂野赛道》) GSU-1 8 MBit 512 KBit 64KBit
星际火狐2 GSU-1 8 MBit 512 KBit 64KBit
漩涡 GSU-1 4 MBit 256 KBit
SNES体素景观演示 GSU-1 3 MBit 512 KBit
飘移(演示) GSU-1 3 MBit 512 KBit
DOOM GSU-2 16 MBit 512 KBit
耀西岛 GSU-2-SP1 16 MBit 256 KBit 64KBit
冬日黄金 GSU-2 16 MBit 512 KBit 64KBit

工作原理

[编辑 | 编辑源代码]
超级FX协处理器。

超级FX是SNES CPU的协处理器。超级FX的任务是执行比SNES快得多的复杂数学计算,并为超级FX游戏的简单3D渲染生成位图。超级FX和SNES处理器共享对公共游戏卡RAM和ROM总线的访问。在任何时候,只有一个处理器,超级FX或SNES CPU,可以访问游戏卡RAM和/或ROM,由特殊寄存器控制。SNES和超级FX访问数据总线的流程是优化程序效率的一门艺术。

游戏卡RAM主要用于存储计算结果、超级FX程序、批量数据或超级FX正在生成的PLOT图像。可以有256 Kib(32KiB)或512 Kib(64 KiB)的RAM。一些超级FX游戏还使用此RAM来存储存档数据。

超级FX可以以3种方式处理指令:从游戏卡RAM中读取、从游戏卡ROM中读取(直接从ROM芯片读取),或通过特殊的512字节指令缓存读取。

当使用512字节指令缓存时,超级FX可以与SNES CPU并行运行。这涉及加载程序,然后设置超级FX以开始工作。与在游戏卡RAM或ROM中运行程序相比,512字节缓存通常快3倍。超级FX可以在处理完成后中断SNES CPU。

当使用超级FX的特殊位图功能时,可以快速将位图从游戏卡RAM加载到SNES视频RAM并显示在屏幕上。SNES默认是一个基于瓷砖和精灵的控制台 - 3D渲染游戏中使用的基于像素的场景构建对于库存的SNES硬件来说非常低效。在超级FX游戏中,例如DOOM、星际火狐/星际之翼等,超级FX快速将基于像素的场景位图绘制到游戏卡RAM上,然后将其扔到SNES VRAM中,以便每秒多次显示图形。

硬件版本

[编辑 | 编辑源代码]

超级FX有3个不同的硬件版本。所有版本在指令集方面功能上都是兼容的,但支持不同的ROM大小。

  • MARIO芯片 - 代表“数学阿格诺特旋转输入输出”。超级FX芯片的第一个版本,仅与星际火狐/星际之翼一起使用。芯片有两个版本 - 一个是直接PCB裸片粘合/环氧树脂设置,另一个是标准芯片载体封装。
  • GSU-1 - 用于大多数超级FX游戏的版本,采用标准芯片载体封装。在功能上与MARIO芯片相同。支持最大8兆位(1兆字节)的ROM大小。
  • GSU-2 - 用于最后3款超级FX游戏,支持完整的16兆位(2兆字节)ROM大小。

寄存器

[编辑 | 编辑源代码]

超级FX芯片有16个通用16位寄存器,标记为R0R15,以及11个控制寄存器。此外,从$3100-$32FF的内存空间构成指令缓存。

通用寄存器

寄存器 地址 描述 从SNES访问
R0 $3000 默认源/目标寄存器 R/W
R1 $3002 像素绘图X位置寄存器 R/W
R2 $3004 像素绘图Y位置寄存器 R/W
R3 $3006 用于一般用途 R/W
R4 $3008 lmult 的低16位结果 R/W
R5 $300A 用于一般用途 R/W
R6 $300C fmult 和 lmult 的乘数 R/W
R7 $300E 用于合并的定点纹素X位置 R/W
R8 $3010 用于合并的定点纹素Y位置 R/W
R9 $3012 用于一般用途 R/W
R10 $3014 用于一般用途 R/W
R11 $3016 由 link 设置的返回地址 R/W
R12 $3018 循环计数器 R/W
R13 $301A 循环点地址 R/W
R14 $301C 用于GETBGETBHGETBLGETBS的rom地址 R/W
R15 $301E 程序计数器 R/W

控制寄存器

名称 地址 描述 大小 从SNES访问
SFR $3030 状态标志寄存器 16位 R/W
$3032 未使用
BRAMR $3033 备份RAM寄存器 8位 W
PBR $3034 程序库寄存器 8位 R/W
$3035 未使用
ROMBR $3036 rom库寄存器 8位 R
CFGR $3037 控制标志寄存器 8位 W
SCBR $3038 屏幕基址寄存器 8位 W
CLSR $3039 时钟速度寄存器 8位 W
SCMR $303A 屏幕模式寄存器 8位 W
VCR $303B 版本代码寄存器(只读) 8位 R
RAMBR $303C RAM库寄存器 8位 R
$303D 未使用
CBR $303E 缓存基址寄存器 16位 R

指令缓存

名称 地址 描述 大小 从SNES访问
1 $3100 指令缓存的第一个字节 8位 R/W
2 $3101 指令缓存的第二个字节 8位 R/W
... ... ... 8位 R/W
... ... ... 8位 R/W
512 $32FF 指令缓存的第512个字节 8位 R/W

SFR 状态标志寄存器

[编辑 | 编辑源代码]

SFR 是一个非常重要的寄存器。它在评估计算后控制 Super FX 内部的分支,并且可以在从 SNES CPU 访问时确定 Super FX 的状态。

描述
0 -
1 Z 零标志
2 CY 进位标志
3 S 符号标志
4 OV 溢出标志
5 G Go 标志(当 GSU 运行时设置为 1)
6 R 使用 R14 地址读取 ROM 时设置为 1
7 -
8 ALT1 下一条指令的模式设置标志
9 ALT2 下一条指令的模式设置标志
10 IL 立即较低 8 位标志
11 IH 立即较高 8 位标志
12 B 当执行 WITH 指令时设置为 1
13 -
14 -
15 IRQ 当 GSU 引起中断时设置为 1。当被 658c16 读取时设置为 0

BRAMBR 备份 RAM 寄存器

[编辑 | 编辑源代码]

用于允许保护游戏卡内备份 RAM(不要与游戏卡 RAM 混淆)。位 0 可以设置为 0 以禁用写入备份 RAM,设置为 1 以启用写入。

描述
0 BRAM 标志(0 = 写入禁用,1 = 写入启用)
1 未使用
2 未使用
3 未使用
4 未使用
5 未使用
6 未使用
7 未使用

PBR 程序库寄存器

[编辑 | 编辑源代码]

当 Super FX 加载代码时,它引用 PBR 寄存器来指定正在使用的库。LJMP 指令是用于更改此寄存器的常用方法。

描述
0 A16 地址选择
1 A17 地址选择
2 A18 地址选择
3 A19 地址选择
4 A20 地址选择
5 A21 地址选择
6 A22 地址选择
7 A23 地址选择

ROMBR 游戏卡 ROM 库寄存器

[编辑 | 编辑源代码]

当使用 ROM 缓冲系统时,此寄存器指定要复制到缓冲区的游戏卡 ROM 的库。ROMB 指令是用于更改此寄存器的常用方法。

描述
0 A16 ROM 地址选择
1 A17 ROM 地址选择
2 A18 ROM 地址选择
3 A19 ROM 地址选择
4 A20 ROM 地址选择
5 A21 ROM 地址选择
6 A22 ROM 地址选择
7 A23 ROM 地址选择

CFGR 配置寄存器

[编辑 | 编辑源代码]

控制时钟倍频器和中断屏蔽。

描述
0 未使用
1 未使用
2 未使用
3 未使用
4 未使用
5 MS0(0 = 标准,1 = 高速)
6 未使用
7 IRQ(0 = 正常,1 = 屏蔽)

注意:如果通过 CLSR 标志(1)设置为以 21.477 MHz 运行,MS0 标志应设置为 0。

SCBR 屏幕基址寄存器

[编辑 | 编辑源代码]

此寄存器设置图形存储区域的起始地址。它直接写入,而不是通过特定的指令。

描述
0 A10 屏幕基址选择
1 A11 屏幕基址选择
2 A12 屏幕基址选择
3 A13 屏幕基址选择
4 A14 屏幕基址选择
5 A15 屏幕基址选择
6 A16 屏幕基址选择
7 A17 屏幕基址选择

CLSR 时钟寄存器

[编辑 | 编辑源代码]

控制 Super FX 芯片的时钟频率。

描述
0 CLSR,0 = 10.738 MHz,1 = 21.477 MHz
1 未使用
2 未使用
3 未使用
4 未使用
5 未使用
6 未使用
7 未使用

SCMR 屏幕模式寄存器

[编辑 | 编辑源代码]

此寄存器为 PLOT 图形加速例程设置颜色数量和屏幕高度,并另外控制 Super FX 或 SNES 是否控制游戏卡 RAM 和 ROM。

描述
0 颜色模式 MD0
1 颜色模式 MD1
2 屏幕高度 HT0
3 游戏卡 RAM 访问 - RAN(0 = SNES,1 = Super FX)
4 游戏卡 ROM 访问 - RON(0 = SNES,1 = Super FX)
5 屏幕高度 HT1
6 未使用
7 未使用

屏幕高度真值表

HT1 HT0 模式
0 0 128 像素
0 1 160 像素
1 0 192 像素
1 1 OBJ 模式

颜色模式真值表

MD1 MD0 模式
0 0 4 色
0 1 16 色
1 0 未使用
1 1 256 色

VCR 版本寄存器

[编辑 | 编辑源代码]

可以使用此寄存器读取正在使用的 Super FX 芯片的版本。

描述
0 VC0
1 VC1
2 VC2
3 VC3
4 VC4
5 VC5
6 VC6
7 VC7

RAMBR 游戏卡 RAM 库寄存器

[编辑 | 编辑源代码]

在游戏卡 RAM 和 Super FX 寄存器之间写入时,此寄存器指定正在使用的游戏卡 RAM 的库。RAMB 指令是用于更改此寄存器的常用方法。位 0 用于将 RAM 库设置为 $70$71

描述
0 A16(当为 0 时为 $70,当为 1 时为 $71
1 未使用
2 未使用
3 未使用
4 未使用
5 未使用
6 未使用
7 未使用

CBR 缓存基址寄存器

[编辑 | 编辑源代码]

此寄存器指定游戏卡 RAM 或 ROM 的地址,数据将从该地址加载到缓存中。LJMPCACHE 指令都是更改此寄存器的可接受方法。

描述
0 -(读取时始终为 0)
1 -(读取时始终为 0)
2 -(读取时始终为 0)
3 -(读取时始终为 0)
4 A4
5 A5
6 A6
7 A7
8 A8
9 A9
10 A10
11 A11
12 A12
13 A13
14 A14
15 A15

内存映射

[编辑 | 编辑源代码]

从 SNES CPU 的角度来看

[编辑 | 编辑源代码]

Super FX 接口:映射到 $3000-$32FF,在库 $00-$3F$80-$BF
游戏 ROM:映射到 2 MiB,在库 $00-$3F 中从 $8000-$FFFF 开始。从库 $40-$5F 开始的 2 MiB 镜像映射。
游戏卡 RAM:映射到 128 KiB,从库 $70:$0000 开始。前 8 KiB 镜像到库 $00-$3F$80-$BF 中的每个 $6000
游戏备份 RAM:映射到 128 KiB,从库 $78:$0000 开始
SNES CPU ROM:可以使用一个额外的 6 MiB ROM,该 ROM 仅对 SNES CPU 可访问,但没有 Super FX 游戏超过 2 MiB。额外的 ROM 将映射在库 $80-$BF 中从 $8000-$FFFF 开始,以及在库 $C0-$FF 中从 $0000-$FFFF 开始

从 Super FX 的角度来看

[编辑 | 编辑源代码]

游戏 ROM:映射到 2 MiB,在库 $00-$3F 中从 $8000-$FFFF 开始。从库 $40-$5F 开始的 2 MiB 镜像映射。
游戏卡 RAM:映射到 128 KiB,从库 $70:$0000 开始。不应访问 SNES 可以看到的其他内存位置。
注意:Super FX 通过三个库控制寄存器访问内存:程序库寄存器 (PBR)、ROM 库寄存器 (ROMBR) 和 RAM 库寄存器 (RAMBR)

指令集

[编辑 | 编辑源代码]

Super FX 指令集不同于 Super Nintendo 的原生指令集。它允许更快的、更复杂的 16 位数学运算,并包含一些特定的图形操作功能。

一些指令可以组装成单个字节。这是指令(半字节)和参数(半字节)合并到同一个存储字节中的地方。这使得执行速度更快,指令密度也更高。这些是在设计协处理器时要考虑的重要目标。其中一个指令是 ADC,它以 $5 开头,并接收 16 个通用 Super FX 寄存器之一($0-$F)的参数。

相当多的指令需要在执行操作码之前执行 ALT 指令。这会修改相同操作码的行为,使其执行略微不同的操作。有 3 种可能的 ALT 代码——ALT1$3D)、ALT2$3E)和 ALT1+ALT2$3F)。在下表中,每个指令都列出了具体的 ALT 代码。

大多数指令依赖于预定义的指针来定位计算变量。这些是 FROMTOWITH 指令。TOFROM 命令分别指定作为变量的通用寄存器和计算结果WITH 在同一个命令中定义了变量和结果。变量和结果分别被称为目标寄存器。

指令集表格

[编辑 | 编辑源代码]
指令 描述 ALT(十六进制) CODE(十六进制) ARG 长度(字节) 字节 ATL1 ALT2 O/V S CY Z ROM RAM 缓存 分类 备注
ADC 带进位的加法 3D 0x5 Rn 2 0 0 0 * * * * 6 6 2 算术运算指令
ADC 带进位的加法 3F 0x5 #n 2 0 0 0 * * * * 6 6 2 算术运算指令
ADD 加法 0x5 Rn 1 0 0 0 * * * * 3 3 1 算术运算指令
ADD 加法 3E 0x5 #n 2 0 0 0 * * * * 6 6 2 算术运算指令
ALT1 设置 ALT1 模式 0x3D / 1 / 1 / / / / / 3 3 1 前缀标志指令
ALT2 设置 ALT2 模式 0x3E / 1 / / 1 / / / / 3 3 1 前缀标志指令
ALT3 设置 ALT3 模式 0x3F / 1 / 1 1 / / / / 3 3 1 前缀标志指令
AND 逻辑与 0x7 Rn 1 0 0 0 / * / * 3 3 1 逻辑运算指令
AND 逻辑与 3E 0x7 #n 2 0 0 0 / * / * 6 6 2 逻辑运算指令
ASR 算术右移 0x96 / 1 0 0 0 / * * * 3 3 1 移位指令
BCC 进位清零时跳转 0x0C e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BCS 进位置位时跳转 0x0D e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BEQ 相等时跳转 0x09 e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BGE 大于等于零时跳转 0x06 e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BIC 位清零掩码 3D 0x7 Rn 2 0 0 0 / * / * 6 6 2 逻辑运算指令
BIC 位清零掩码 3F 0x7 #n 2 0 0 0 / * / * 6 6 2 逻辑运算指令
BLT 小于零时跳转 0x07 e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BMI 负数时跳转 0x0B e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BNE 不相等时跳转 0x08 e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BPL 正数时跳转 0x0A e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BRA 始终跳转 0x05 e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BVC 溢出清零时跳转 0x0E e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
BVS 溢出置位时跳转 0x0F e 2 / / / / / / / 6 6 2 "跳转、分支和循环指令"
CACHE 设置缓存基址寄存器 0x02 / 1 0 0 0 / / / / 3-4 3-4 1 GSU 控制指令
CMODE 设置绘图模式 3D 0x4E / 2 0 0 0 / / / / 6 6 2 绘图/相关指令
CMP 比较 3F 0x6 Rn 2 0 0 0 * * * * 6 6 2 算术运算指令
COLOR 设置绘图颜色 0x4E / 1 0 0 0 / / / / 3 3 1 绘图/相关指令
DEC 递减 0xE Rn 1 0 0 0 / * / * 3 3 1 算术运算指令
DIV2 除以 2 3D 0x96 / 2 0 0 0 / * * * 6 6 2 算术运算指令
FMULT 分数有符号乘法 0x9F / 1 0 0 0 / * * * 11 或 7 11 或 7 8 或 4 算术运算指令 周期取决于 CFGR 寄存器
FROM 设置 Sreg 0xB Rn 1 / / / / / / / 3 3 1 前缀寄存器指令
GETB 从 ROM 缓冲区获取字节 0xEF / 1 0 0 0 / / / / 3-8 3-8 1-6 数据从游戏卡 ROM 传输到寄存器 周期因 ROM 缓冲区而异
GETBH 从 ROM 缓冲区获取高字节 3D 0xEF / 2 0 0 0 / / / / 6-10 6-9 2-6 数据从游戏卡 ROM 传输到寄存器 周期因 ROM 缓冲区而异
GETBL 从 ROM 缓冲区获取低字节 3E 0xEF / 2 0 0 0 / / / / 6-10 6-9 2-6 数据从游戏卡 ROM 传输到寄存器 周期因 ROM 缓冲区而异
GETBS 从 ROM 缓冲区获取有符号字节 3F 0xEF / 2 0 0 0 / / / / 6-10 6-9 2-6 数据从游戏卡 ROM 传输到寄存器 周期因 ROM 缓冲区而异
GETC 从 ROM 获取字节到颜色寄存器 0xDF / 1 0 0 0 / / / / 3-10 3-9 1-6 数据从游戏卡 ROM 传输到寄存器 周期因 ROM 缓冲区而异
HIB 寄存器高字节的值 0xC0 / 1 0 0 0 / * / * 3 3 1 字节传输指令
IBT 加载立即字节数据 0xA "Rn, #pp" 2 0 0 0 / / / / 6 6 2 数据传输/立即数据到寄存器
INC 递增 0xD Rn 1 0 0 0 / * / * 3 3 1 算术运算指令
IWT 加载立即字数据 0xF "Rn, #xx" 3 0 0 0 / / / / 9 9 3 数据传输/立即数据到寄存器
JMP 跳转 0x9 Rn 1 0 0 0 / / / / 3 3 1 "跳转、分支和循环指令"
LDB 从 RAM 加载字节数据 3D 0x4 Rm 1 0 0 0 / / / / 11 13 6 数据从游戏卡 RAM 传输到寄存器
LDW 从 RAM 加载字数据 0x4 Rm 1 0 0 0 / / / / 10 12 7 数据从游戏卡 RAM 传输到寄存器
LEA 加载有效地址 0xF "Rn, xx" 3 0 0 0 / / / / 9 9 3 宏指令
LINK 链接返回地址 0x9 #n 1 0 0 0 / / / / 3 3 1 "跳转、分支和循环指令"
LJMP 长跳转 3D 0x9 Rn 2 0 0 0 / / / / 6 6 2 "跳转、分支和循环指令"
LM "从 RAM 加载字数据,使用 16 位" 3D 0xF "Rn, (xx)" 2 0 0 0 / / / / 20 21 11 数据从游戏卡 RAM 传输到寄存器
LMS "从 RAM 加载字数据,短地址" 3D 0xA "Rn, (yy)" 2 0 0 0 / / / / 17 17 10 数据从游戏卡 RAM 传输到寄存器
LMULT 16x16 有符号乘法 3D 0x9F / 2 0 0 0 / * * * 10 或 14 10 或 14 5 或 9 算术运算指令 周期取决于 CFGR 寄存器
LOB 寄存器低字节的值 0x9E / 1 0 0 0 / * / * 3 3 1 字节传输指令
LOOP 循环 0x3C / 1 0 0 0 / * / * 3 3 1 "跳转、分支和循环指令"
LSR 逻辑右移 0x03 / 1 0 0 0 / 0 * * 3 3 1 移位指令
MERGE 合并 R8R7 的高字节 0x70 / 1 0 0 0 / / / / 6 6 2 字节传输指令
MOVE 将字数据从 Rn' 移动到 Rn 0x2n1n' "Rn, Rn'" 2 0 0 0 / / / / 6 6 2 数据从寄存器到寄存器的传输
MOVES 将字数据从 Rn' 移动到 Rn 并设置标志 0x2nBn' "Rn, Rn'" 2 0 0 0 / / / / 6 6 2 数据从寄存器到寄存器的传输
MULT 有符号乘法 0x8 Rn 1 0 0 0 / * / * 3 或 5 3 或 5 1 或 2 算术运算指令 周期取决于 CFGR 寄存器
MULT 有符号乘法 3E 0x8 #n 2 0 0 0 / * / * 6 或 8 6 或 8 2 或 3 算术运算指令 周期取决于 CFGR 寄存器
NOP 无操作 0x01 / 1 0 0 0 / / / / 3 3 1 GSU 控制指令
NOT 反转所有位 0x4F / 1 0 0 0 / / / / 3 3 1 位操作指令
OR 位或 0xC Rn 1 0 0 0 / / / / 3 3 1 位操作指令
OR 位或 3E 0xC #n 2 0 0 0 / / / / 6 6 2 位操作指令
PLOT 绘制像素 0x4C / 1 0 0 0 / / / / 3-48 3-51 1-48 绘图/相关指令 周期因 RAM 缓冲区和程序而异
RAMB 设置 RAM 数据库 3E 0xDF / 2 0 0 0 / / / / 6 6 2 库设置指令
ROL 带进位的左旋 0x04 / 1 0 0 0 / * * * 3 3 1 移位指令
ROMB 设置 ROM 数据库 3F 0xDF / 2 0 0 0 / / / / 6 6 2 库设置指令
ROR 带进位的右旋 0x97 / 1 0 0 0 / * * * 3 3 1 移位指令
RPIX 读取像素颜色 3D 0x4C / 2 0 0 0 / * / * 24-80 24-78 20-74 绘图/相关指令
SBC 带进位的减法 3D 0x6 Rn 2 0 0 0 * * * * 6 6 2 算术运算指令
SBK "存储字数据,上次使用的 RAM 地址" 0x9 / 1 0 0 0 / / / / 3-8 7-11 1-6 数据从寄存器传输到游戏卡 RAM
SEX 符号扩展寄存器 0x95 / 1 0 0 0 / * / * 3 3 1 字节传输指令
SM 使用 16 位将字数据存储到 RAM 3E 0xF "Rn, (xx)" 3 0 0 0 / / / / 12-17 16-20 4-9 数据从寄存器传输到游戏卡 RAM 周期因 RAM 缓冲区和程序而异
SMS "将字数据存储到 RAM,短地址" 3E 0xA "Rn, (yy)" 3 0 0 0 / / / / 9-14 13-17 3-8 数据从寄存器传输到游戏卡 RAM 周期因 RAM 缓冲区和程序而异
STB 将字节数据存储到 RAM 3D 0x3 Rm 2 0 0 0 / / / / 6-9 8-14 2-5 数据从寄存器传输到游戏卡 RAM 周期因 RAM 缓冲区和程序而异
STOP 停止处理器 0x00 / 1 0 0 0 / / / / 3 3 1 GSU 控制指令
STW 将字数据存储到 RAM 0x3 Rm 1 0 0 0 / / / / 3-8 7-11 1-6 数据从寄存器传输到游戏卡 RAM 周期因 RAM 缓冲区和程序而异
SUB 减法 0x6 Rn 1 0 0 0 * * * * 3 3 1 算术运算指令
SUB 减法 3E 0x6 #n 2 0 0 0 * * * * 6 6 2 算术运算指令
SWAP 交换低字节和高字节 0x4D / 1 0 0 0 / * / * 3 3 1 字节传输指令
TO 设置 Dreg 0x1 Rn 1 / / / / / / / 3 3 1 前缀寄存器指令
UMULT 无符号乘法 3D 0x8 Rn 2 0 0 0 / * / * 6 或 8 6 或 8 2 或 3 算术运算指令 周期数取决于 CONFIG 寄存器
UMULT 无符号乘法 3F 0x8 #n 2 0 0 0 / * / * 6 或 8 6 或 8 2 或 3 算术运算指令 ?
WITH 设置 Sreg 和 Dreg 0x2 "Rn, ?" ? 1 ? ? ? ? ? ? ? ? ? 前缀寄存器指令 ?
XOR 位异或 3D 0xC Rn 2 ? ? ? ? ? ? ? ? ? ? 位操作指令 ?
XOR 位异或 3F 0xC #n 2 ? ? ? ? ? ? ? ? ? ? 位操作指令 ?

Sreg 和 Dreg

[编辑 | 编辑源代码]

对于某些指令,必须在运行指令之前指定 Sreg 和 Dreg。Sreg 是“源寄存器”,Dreg 是“目标寄存器”,每个都指定为 16 个通用寄存器之一。使用 TOFROMWITH 指令指定 Sreg 和 Dreg。

位图模拟

[编辑 | 编辑源代码]

位图模拟功能是 Super FX 的主要加速功能之一。它允许在帧缓冲区中使用基于像素的着色方法,而不是 SNES VRAM 中基于图块的方法。对于 3D 渲染操作,需要一个快速的逐像素着色器。Super FX 提供了框架,可以快速将单个像素绘制到帧缓冲区,然后将绘制的图像传输到 SNES VRAM。

快速乘法

[编辑 | 编辑源代码]

Super FX 有 4 个乘法指令。

  • MULT - 有符号 8 位 x 有符号 8 位,结果为有符号 16 位,存储在 Dreg 中。
  • UMULT - 无符号 8 位 x 无符号 8 位,结果为无符号 16 位,存储在 Dreg 中。
  • LMULT - 有符号 16 位 x 有符号 16 位,结果为有符号 32 位,MSB 存储在 Dreg 中,LSB 存储在 R4 中
  • FMULT - 有符号 16 位 x 有符号 16 位,结果为有符号 32 位。

MULT/UMULT 指令比 LMULT/FMULT 指令更快。

编译 Super FX 例程

[编辑 | 编辑源代码]

虽然 SNES 汇编语言程序可以使用常规的 65c816 编译器进行编译,但 Super FX 汇编语言需要自定义编译器。现有的 Super FX 游戏中使用的原始编译器没有在封闭的开发社区之外发布。

一个名为 sfxasm 的开源编译器可用于编译 Super FX 程序。

编译后,Super FX 程序将作为二进制库包含在 SNES 汇编语言程序中。然后,SNES 程序指示 Super FX 使用打包在 ROM 中的预编译程序。

在 SNES 程序中使用 Super FX

[编辑 | 编辑源代码]

当 SNES 启动带有 Super FX 游戏时,Super FX 芯片处于闲置状态,您无需执行任何操作即可启动正常的 SNES 加载 ROM 和执行代码的程序。当 SNES 启动并执行了一些启动例程,并且通常已准备好后,您可以在程序中激活 Super FX。注意,为了使模拟器支持 Super FX 指令,标题中的 $FFD6 字节必须为 $13$14$15$1A$FFD5 字节应为 $20

初始化

[编辑 | 编辑源代码]

在运行代码之前应初始化 Super FX 芯片。这包括设置基本配置寄存器。

  • SCBR
  • SCMR
  • CFGR
  • CLSR

选择执行模式

[编辑 | 编辑源代码]

如前所述,代码可以通过三种不同的方式加载到 Super FX 中 - 来自游戏卡 ROM、RAM 和 512 字节缓存。根据您想要使用哪种方式,程序略有不同。

  • ROM 模式的好处是简单,但代价是 Super FX 处理时会停止 SNES CPU。
  • RAM 模式的优势是能够在 SNES CPU 已经忙碌的情况下运行一个大型 Super FX 程序,但代价是必须在运行之前将程序写入游戏卡 RAM 中。
  • 缓存模式的优势是在 SNES 同时忙于游戏卡 ROM 和 RAM 的情况下,运行一个小程序的速度比 ROM 或 RAM 模式快三倍,但代价是必须在执行过程之前将程序加载到缓存内存中。

设置 - ROM 模式

[编辑 | 编辑源代码]

1. 设置程序库寄存器 (PBR) 用于 SFX 程序开始的位置。
2. 编程 Super FX 中的程序计数器 (R15)。
3. 通过在 SFR 寄存器中设置 RON 标志,使 Super FX 独占访问 ROM。

设置 - RAM 模式

[编辑 | 编辑源代码]

1. 使用复制例程将程序从 ROM 传输到游戏卡 RAM 中。
2. 设置程序基址寄存器 (PBR) 用于 SFX 程序开始的位置。
3. 写入 Super FX 程序计数器 (R15)。

设置 - 缓存模式

[编辑 | 编辑源代码]

1. 使用复制例程将程序从 ROM 传输到缓存 RAM ($3100-$31FF) 及以后。程序需要以每 16 字节为一个块的方式排列,否则 Super FX 将不会执行超出 16 字节段的指令。这对小于 16 字节的小程序也适用 - 要解决这个问题,请在第 16 个字节 ($310F) 中写入一些内容。
2. 写入 Super FX 程序计数器 (R15),这通常为 0。
3. Super FX 程序将独立于 SNES 执行,直到它遇到 STOP 指令。当它完成时,根据 SFR 配置中断是否设置,它将在 SNES 上生成一个中断 (RTI 指令)。如果中断被屏蔽,则 Super FX 将进入空闲模式,并等待 SNES 的下一个命令开始执行。

开始处理

[编辑 | 编辑源代码]

当 Super FX 发现 SNES 已经写入其程序计数器寄存器 (R15) 时,处理开始。

停止处理

[编辑 | 编辑源代码]

Super FX 可以通过两种方式之一停止 - 通过在 Super FX 的程序中执行 STOP 指令,或者通过 SNES 将 "0" 写入 Super FX 的 SFR 寄存器中的 GO 标志。

停止时中断

[编辑 | 编辑源代码]

当 Super FX 读取 Super FX STOP 指令时,它会调用 RTI 指令。可以通过在 SFR 寄存器中设置 IRQ 位来屏蔽中断。如果中断没有被屏蔽,要确定它是屏幕消隐中断还是 Super FX,请检查 SFR 寄存器中的 IRQ 标志位。

华夏公益教科书