19、更多的事情
随机数。
NES没有很好的方法来生成随机数。
neslib里面有rand8() 和 rand16(),但是他生成方式有问题。他在启动时使用常量,这就意味着每次重启后的随机数都会是相同的。
我编写了一个将帧数统计放入到随机数计算的方法。
seed_rng()
使用帧数作为随机数种子。所以启动的时候他而不是随机的,而是通过用户的输入指令触发他。
比如 “PRESS START”
https://github.com/nesdoug/23_Random/blob/master/Random.c
https://github.com/nesdoug/23_Random
注意:seed_rng() 仅设置种子的低字节,这样就有了256个结果。如果要设置两个种子字节,请使用1个用户输入来触发第一个seed_rng() ,然后调用rand8() 3-4次,然后获取用户输入以触发第二个seed_rng()
Mappers
到目前为止,我们一直在使用最基本的映射器NROM。我们在crt0.s文件中定义了ines header头信息。
在“HEADER”段中这是一个重要的配置信息在 .cfg文件中。如果想要改变Mapper我们只需要改变配置文件中的Mapper配置,NES_MAPPER,value =#。
为什么要修改Mapper呢?如果我们想要更多的PRG或者CHR或者更多的RAM,我们需要具有这些功能的特殊游戏卡带。
拥有了更大的ROM文件,将一部分重新映射到CPU的$8000地址来实现(8000是举例)
用C编程的话,使用Mapper功能很费劲。一个函数可能会调用另外一个函数,如果调用不到,就会导致游戏崩溃。
你可能需要将数据放到几个小的块中,并在游戏进行的过程中交换位置。你还可以做的是将音乐数据放到备用的库中。
这个有些高级,暂时先跳过了。
说些简单的。
CNROM,允许切换整个图形(下面有例子)
AxROM和UxROM没有CHR ROM。图形都位于PRG ROM中存放(PRG的体积也会比较大),使用的时候需要将他们加载到 CHR的RAM中才能使用。AxROM允许您更改整个$8000-$FFFF bank。UNROM固定了$C000-$FFFF,并允许您更改$8000-BFFF bank。比起AxROM我更喜欢UNROM,因为你可以将你的C代码放在固定的存储区中方便数据的使用,用C开发AxROM非常困难,很多地方只有ASM汇编才能实现。
在UNROM上有一个自制软件版本,mapper 30,UNROM 256,比任何商业游戏都要大得多。NESmaker使用它。用C开发的话会很有用。
Mojon twins 用标准的UNROM开发出了至少1个完整的游戏。
http://forums.nesdev.com/viewtopic.php?p=169438#p169438
对于任何Mapper,你都可以在头信息配置$6000-7fff是RAM地址。byte 10, bit 4
如果你在启动的时候读写此区域,很多模拟器都会认为游戏拥有PRG RAM芯片。
如果你希望你的游戏有记录功能(电池记录RAM),你需要在头信息配置 byte 6, bit 1
GNROM,Mapper编号66(或Wisdom Tree / Color Dreams,mapper 11)可以交换整个PRG和CHR。
当然这与AxROM一样的问题,一个数据块中的方法调用另一个数据块中的方法,而且还要确保整个CRT库一直可用。
更高级的Mapper,比如MMC1
cppchriscpp 在他的C项目中使用了MMC1 (SxROM)
https://github.com/cppchriscpp/nes-starter-kit
一些bank块转换的代码
https://github.com/cppchriscpp/nes-starter-kit/tree/master/source/library
您可以更改$8000-bfff区域。你可以改变tileset(ppu 0-fff或ppu 1000-1fff)。
并且您可以将镜像从H更改为V。这个功能非常牛X
更高级,MMC3(TxROM)。您可以更改$8000-9fff和/或$a000-bfff bank。
你可以更改部分CHR ROM。小到只有$800 大小。可以用在动画背景(瀑布)
您可以使用扫描线计数器IRQ进行多次背景分割。但是 IRQ需要ASM汇编写。
我做了一个简单的CNROM示例。有4个CHR文件,我只是在它们之间切换,并更改调色板。
CNROM有个技术问题,叫做总线冲突。Mapper通过写rom来工作