【原创】NES第八波:怎么写一个HelloWorld
这里我用的编辑工具还是6502Sim。
第一步是确定容量:我写一个极短的汇编代码,16K容量就远远足够了。所以程序从$C000开始存放。图库大小也是最小就可以(即8K)。
第二步是分派背景所在页和精灵所在页。不防定:背景=0页,精灵=1页。
第三步是准备一个4K的背景用chr,和一个精灵用的chr。
因为这次用不着显示精灵,所以精灵chr纯属是打酱油。不过也要用于填充,哪怕是4K的空白文件(字节要精确=4096)。
背景用chr,要我们去制作了。可以从nes游戏里面分离出来(用yychr),也可以用我的字模工具制作。为了方便编程,大小字母和数字按放的位置可以依ascii的号码对应。也可以只做HeloWrd这几个字母。为了简化代码,本例只做8*8的字模。制作的方法,见《NES第五波》。
注:YYCHR默认新建的文件有好几页。如果只想做一页,用我的字模工具,生成一个4K的就可以了。再用YYCHR打开,清空。另外再打开一个YYCHR,打开你想要chr。两个YYCHR可以互相粘贴。右键拉一个选框,就可以复制了。
第四步是新建NES的文件头,用到我的工具NESInfo,见《NES第一波》。
本例:mapper=0,PRG rom=1x16K,CHR rom=1x8K,镜像=水平,S-RAM=no,4屏=no,Trainer=no
mapper:就是卡带的电路板分类号码。0代表最原始的电路板,即没有切页功能,也没有扩展功能。
PRG rom:就是指程序空间的容量,匹配mapper0的容量就是1x16K和2x16K。有一个定律就是程序末尾必然在地址$FFFF。所以1X16K就是程序从$C000开始存放,2x16K就是程序从$8000开始存放。
CHR rom:就是指图库空间的容量,匹配mapper0的容量就是1x8K。对应的地址是ppu$0000到ppu$1FFF
镜像:指PPU的背景页,机内只有2页容量,但有4页地址,那么就会形成镜像。PPU的A10和A11连到卡带,由卡带对这两线的接线方式,决定镜像方式(水平或垂直)。
水平镜像,指0页(ppu$2000)与1页(ppu$2400)镜像,那么可以进行2屏的垂直滚屏(即0页与2页(ppu$2800)都是可编辑的,可以连起来。)。2页与3页镜像,同理。
垂直镜像,指0页与2页镜像,那么可以进行2屏的水平滚屏(即0页与1页(ppu$2400)都是可编辑的,可以连起来。)。1页与3页镜像,同理。
PPU的背景页分布应该是这样的:
【0页ppu$2000】【1页ppu$2400】 【2页ppu$2800】【3页ppu$2B00】
(不是说镜像页就不能编辑,而是没必要编辑,因为无论改哪面都是两面一起变的。)
S-RAM:指卡带上是否增加一块电池维持的内存(地址在$6000到$7FFF)。模拟器会因为它而生成一个nes扩展文件。
4屏:指卡带上是否增加ppu的两个背景页,那就不存要镜像了,前面“镜像”选项就无效。
Trainer:原意教练,这里指卡带上是否增加一块512字节的ROM(地址在$5E00到$5FFF),选这个项的话,连接时要在文件头与PRG rom之间加一块512字节的Bin文件。有点麻烦,还是选no就好了。
NESInfo,可以生成bin文件,也可以对bin文件直接编辑。所以修改还是很方便的。我们用NESInfo,生成一个Head.bin。即nes文件头bin。
第五步写代码。因为代码的编幅太长,讲解代码我放在最后讲。编译工具,我用6502Sim。我选一个汉化版的,有高亮语法显示,有没有写错指令,一眼就知道。
写好代码之后按“仿真”-“汇编F7”。如果没有报错,窗框一闪就关了,说明Pass。可以输出bin。
按菜单“文件”-“保存代码Ctrl+K”;保存类型选"二进制映像.65b";然后一定要点“选项”;在代码地址栏的“开始于”=0xC000,这一项必须确认,这就是第一步选定的地址;确定;编辑文件名,保存。
本例保存到代码的上一层文件夹,与head.bin、xx.chr等放一起,文件名:main.65b
第六步连接。用DOS指令copy /b 将多个文件首尾连成一个新文件。批文件bat是文本文件,可以由记事本打开。学着写就行。
必须注意的是,不能写错文件名。
保存编辑好的批文件。双击批文件,我加了一句暂停指令,你要看清显示的结果,凡是写错文件名的,都没有显示出来,也就没有连接到nes文件里,但是没有报警的。所以必须看清楚了。
6502源代码:
1 ;开始地址:$c000 2 ;结束地址:$ffff 3 ;文件长度:$4000 4 ; prg rom = 16K 5 6 ;.start reset 7 .ORG $C000 8 reset: 9 ; 默认启动代码 10 SEI ; 禁用中断 11 CLD 12 LDX #$ff ; 初始化栈顶指针到$FF 13 TXS 14 15 ; 初始化内存 16 INX ; x=0了 17 _loop_1: ; 清理全部内存 18 STA $00,x 19 STA $0100,x 20 STA $0200,x 21 STA $0300,x 22 STA $0400,x 23 STA $0500,x 24 STA $0600,x 25 STA $0700,x 26 INX 27 BNE _loop_1 28 29 ; PPU热机,大约要2帧的时间 30 _vb1: ; 1帧 31 BIT $2002 32 BPL _vb1 33 _vb2: ; 2帧 34 BIT $2002 35 BPL _vb2 36 ; 以下可以对PPU操作了。 37 38 ; 初始化PPU 39 LDA #$00 ; 关屏 40 STA $2001 41 42 LDA #$3F ; 写入配色盘(从0号盘开始) 43 STA $2006 44 LDA #$00 45 STA $2006 46 LDA #$0F ;0#=黑色 47 STA $2007 48 LDA #$30 ;1#=白色 49 STA $2007 50 LDA #$2B ;2#=浅蓝色 51 STA $2007 52 LDA #$15 ;3#=红色 53 STA $2007 54 ;...可以继续写入1号2号和3号盘。各4个字节。 55 56 LDA #$20 ; 清除背景2000-23FF即0页背景。 57 STA $2006 58 LDA #$00 59 STA $2006 60 LDY #$04 61 _loop_ppu_1: 62 LDX #$00 63 LDA #$00 64 _loop_ppu_2: 65 STA $2007 66 DEX 67 BNE _loop_ppu_2 68 DEY 69 BNE _loop_ppu_1 70 71 _vb3: ; 凑足够一帧 72 BIT $2002 73 BPL _vb3 74 75 ; 设置PPU的工作方式 76 LDA #$08 ; (D7=0)禁nmi中断, 77 ; (D5=0)精灵=8*8,(D6=x) 78 ; (D4=0)图库:背景用0页, 79 ; (D3=1)图库:精灵用1页, 80 ; (D2=0)PPU写入自动+1, 81 ; (D1D0=00)命名表=2000 82 STA $2000 83 ; 开屏,也是正式设置PPU的显示方式 84 LDA #$08 ; (D7D6D5=000)底色=黑 85 ; (D4=0)不显示精灵 86 ; (D3=1)显示背景(开屏) 87 ; (D2=0)左8列像素不显示精灵,可以将精灵藏在其中 88 ; (D1=0)左8列像素不显示背景,可用来做滚屏 89 ; (D0=0)显示模式=彩色 90 STA $2001 91 92 main: 93 ; 黑屏,这样写入才不会花屏。如果动态写入要用中断。 94 LDA #$00 95 STA $2001 96 97 ; 确定位置在$2021(即第2行的第2列);注,从$2000开始,每行32个图块 98 LDA #$20 99 STA $2006 100 LDA #$21 101 STA $2006 102 103 ; 写入显示的内容 104 ; 本例chr的字母是ascii的序号排的,所以这小字与ascii相符。 105 LDA #$48 ; H 106 STA $2007 107 LDA #$65 ; e 108 STA $2007 109 LDA #$6c ; l 110 STA $2007 111 LDA #$6c ; l 112 STA $2007 113 LDA #$6F ; o 114 STA $2007 115 LDA #$57 ; W 116 STA $2007 117 LDA #$6F ; o 118 STA $2007 119 LDA #$72 ; r 120 sta $2007 121 LDA #$6c ; l 122 STA $2007 123 LDA #$64 ; d 124 STA $2007 125 126 LDA #$00 ; 复位PPU的显示位置(对应0页($2000)背景就是(0,0)) 127 STA $2005 128 STA $2005 129 130 LDA #$08 131 STA $2001 132 end: 133 JMP end 134 135 136 nmi: 137 RTI 138 139 irq: 140 RTI 141 142 143 .ORG $fffa 144 .DW nmi,reset,irq
工程到我的网盘找。维京的梦 (ys168.com)
续。。找个时间再续写代码的解析。
源代码和工程下载:地址 http://fogota.ysepan.com/
找到 NES Tool Kit文件夹,各章节的相关下载都是在一起。(注:网盘原地址也是可用。)