超级任天堂编程/初始化教程
颜色 00000000 11100000
在本教程中,我们将介绍如何初始化超级任天堂并将背景更改为美丽的绿色。
- WLA-65816 宏汇编程序。有适用于 Linux 32 位的二进制文件
- 一个 SNES 模拟器,例如 bsnes、Zsnes 或Geiger 的 Snes9x 调试版本,适用于 Windows。
- 一个初始化例程和一个头文件。初始化例程顾名思义;它是一段代码,用于清除/重置系统值并设置 SNES 以供使用。头文件包含用于 WLA 的汇编指令,这些指令执行定义 ROM 的名称、大小、向量等操作。
如果您决定将初始化例程和头文件放在单独的文件中,则需要告诉汇编器包含它们。
.include "Header.inc" .include "Snes_Init.asm" VBlank: ; Needed to satisfy interrupt definition in "header.inc" RTI
通过将头文件和初始化代码放在您的主文件中,可以跳过此部分。
您可以在 维基教科书上找到 Snes_Init.asm 的 ASM 代码,您还可以找到头文件。
虽然对于此项目正常工作并非必需,但需要注意的是,为了使 VBlank 子例程实际被调用,您需要按如下所示启用 NMI 中断。
lda #$80 ; Set NMI enable bit sta #$4200
在头文件中,标签“Start”被声明为重置向量,因此程序将从那里开始执行。
Start:
大多数演示都会将 SNES 重置到已知状态。由于模拟器可能以已知状态启动,因此对于模拟的 ROM,重置状态可能没有必要。但是,重置 SNES 对于演示在实际的 SNES 硬件上运行可能是必需的。
要重置 SNES,我们将许多硬件寄存器设置为零,并将 WRAM 中的所有字节清零。在这里,我们使用初始化宏Snes_Init来自文件“Snes_Init.asm”,来自 SNES Devkit,它为我们执行此操作。
; Initialize the SNES. Snes_Init
首先,我们将累加器设置为 8 位,以修改 RAM 的单个字节。我们通过在 CPU 状态寄存器中设置适当的位来做到这一点。
sep #$20 ; Set the A register to 8-bit.
SNES 刷新其屏幕以匹配输出到电视机的信号,因此了解电视机如何更新其图像可以帮助您了解 SNES 中某些特殊效果是如何执行的。
电视机使用电子束在屏幕上显示图像,电子束从左到右扫描屏幕,一次扫描一行,从上到下。此外,电视图像为隔行扫描,这意味着电视机交替显示所有偶数扫描线和所有奇数扫描线;每个偶数或奇数扫描线屏幕称为一个场。NTSC 电视机(在美国和日本使用)每秒显示大约 30 帧,而 PAL 电视机(在其他地方使用)每秒显示 25 帧。因此,NTSC 电视机每秒显示约 60 场,而 PAL 电视机每秒显示 50 场。
在行与行之间,当电子束从一行最右边移到下一行最左边时,电子束将关闭;这被称为水平消隐或HBlank。某些特殊效果 - 例如最终幻想 VI 飞船的透视效果 - 可以通过在 HBlank 期间更改图形设置来在 SNES 上执行。
同样,在场与场之间,当电子束从屏幕底部移到屏幕顶部时,电子束将关闭;这被称为垂直消隐或VBlank。如果您在电子束打开时更新屏幕,则显示给用户的结果是不可预测的;它们可能会出现剪切或其他伪像。因此,您希望在 HBlank 或 VBlank 期间对屏幕进行所有修改。由于 VBlank 比 HBlank 长得多,并且覆盖整个屏幕,因此大多数更新应在 VBlank 期间完成。VBlank 每场发生一次,或在 NTSC 机器上每秒约 60 次,在 PAL 机器上每秒约 50 次。
有两种方法可以确保您的代码在 VBlank 期间执行
- 等待 VBlank 非屏蔽中断 (NMI)。
- 通过设置屏幕显示寄存器 ($2100) 的第八位来关闭屏幕。
在这里,我们通过以下代码关闭屏幕来强制 VBlank
lda #%10000000 ; Force VBlank by turning off the screen. sta $2100
SNES 以以下格式存储 16 位颜色
- 高字节:0bbbbbgg
- 低字节:gggrrrrr
我们将使用的颜色是00000000 11100000(0 蓝色,7 绿色,0 红色) - 深绿色。我们使用颜色数据寄存器 ($2122) 设置屏幕的背景颜色
lda #%11100000 ; Load the low byte of the green color. sta $2122 lda #%00000000 ; Load the high byte of the green color. sta $2122
我们通过再次使用屏幕显示寄存器 ($2100) 打开屏幕并将亮度设置为 15 来结束 VBlank。
lda #%00001111 ; End VBlank, setting brightness to 15 (100%). sta $2100
与许多计算机程序不同,SNES 程序并非真正设计为结束。SNES 游戏旨在一直运行,直到用户关闭系统或按下重置键。然而,在我们的例子中,SNES 已完成我们希望它执行的所有操作,现在我们希望它静止不动,不再改变任何东西。我们通过一个无限循环来实现这一点。
; Loop forever. Forever: jmp Forever
如果我们没有这个循环,SNES 将开始执行任何碰巧位于我们程序后面的代码或数据,这可能会使 SNES 做一些我们不想做的事情。
或者,我们也可以使用“STP”命令。此命令会使 SNES 的 CPU 停滞,直到控制台重置。但是,无限循环是一个很好的做法,因为我们最终会需要一个主程序循环,而这将变成主程序循环。
一旦我们在一个文件中获得了我们的程序 - 我们称之为“Greenspace.asm" -- 我们希望将其组装成一个 ROM 镜像,以便我们可以在模拟器中运行它。首先,我们执行 WLA 65816 汇编器将汇编文件转换为目标文件。
wla-65816 -o Greenspace.obj Greenspace.asm
这应该会创建目标文件 "Greenspace.obj".
然后,我们需要将目标文件链接到 ROM 中。WLA 链接器需要一个链接文件,其中列出了要链接的文件。我们将创建一个名为 "Greenspace.link" 的文件,其内容如下
[objects] Greenspace.obj
然后,我们只需要执行 WLA 链接器
wlalink Greenspace.link Greenspace.smc
这应该会创建 ROM 镜像 "Greenspace.smc", 然后我们可以在模拟器中运行它。
为了使编译和链接步骤更容易重复运行——就像我们在编辑和测试之间交替进行时可能想要做的那样——我们可以将命令放在 shell 脚本 中,"Greenspace.bat" 在 DOS/Windows 中,或者 "Greenspace.sh" 用于 UNIX。
wla-65816 -o Greenspace.obj Greenspace.asm wlalink Greenspace.link Greenspace.smc
如果你使用 UNIX,你需要在文件的首行添加#!/bin/bash。在 Windows 下,最好在首行添加@echo off。
或者,如果您在基于 UNIX 的平台上,您可以创建一个 makefile 并使用 make 工具。为此,创建一个名为 "makefile".
Greenspace.smc: Greenspace.asm Greenspace.link wla-65816 -o Greenspace.obj Greenspace.asm wlalink Greenspace.link Greenspace.smc
在创建此文件后,只需使用 "make" 命令,然后 "Greenspace.smc" 将被创建。
完整的源代码
[edit | edit source] ; SNES Initialization Tutorial code
; This code is in the public domain.
.include "Header.inc"
.include "Snes_Init.asm"
; Needed to satisfy interrupt definition in "Header.inc".
VBlank:
RTI
.bank 0
.section "MainCode"
Start:
; Initialize the SNES.
Snes_Init
; Set the background color to green.
sep #$20 ; Set the A register to 8-bit.
lda #%10000000 ; Force VBlank by turning off the screen.
sta $2100
lda #%11100000 ; Load the low byte of the green color.
sta $2122
lda #%00000000 ; Load the high byte of the green color.
sta $2122
lda #%00001111 ; End VBlank, setting brightness to 15 (100%).
sta $2100
; Loop forever.
Forever:
jmp Forever
.ends
有问题吗?看到默认黑色吗?在 讨论页面 上告诉我们。