前言
多年以来,个人一直在关注DOS时代大宇游戏的一种专用配乐文件格式——RIX。当年给我留下深刻印象的《仙剑奇侠传》DOS版就采用了这种配乐文件格式。据分析,RIX是将DOS时代FM配乐标准之一的Adlib ROL格式做了数据转换,和INS音色定义文件数据打包。基本上,我们可以认为,除去一些细节变化之外,RIX是ROL+INS的变体。遗憾的是,进入Windows时代以后,大宇便弃用了FM配乐。在经历了短暂的MIDI文件和CD音轨配乐时代之后,大宇游戏也全面采用了音频文件配乐方案。很长一段时间内,由于缺少相应方案,RIX无法在现代Windows系统程序里播放。而随着AdLib标准逐渐退出历史舞台,在没有了FM合成芯片的新PC平台上,RIX配乐的播放更是完全成为了一个难题。
大约是从2003年开始,一群老仙剑Fans聚在一起,开始对RIX格式进行研究。以模拟器社区的软件FM合成芯片模拟代码为依托,这些Fans开发出了适应现代操作系统的RIX播放方案。经过多年的完善,软件版RIX播放器已经拥有了极其出色的效果,并在一些方面做出了强化。
不过,长期以来,因为年代久远,大家对当年硬件播放的准确效果已经没有那么深的印象了,而官方发行的原声配乐专辑《永恒回忆录》有音频效果后期调整,也和当年的硬件效果有较大差异。那么,和硬件版对比,到底软件模拟版本的播放有多么精确呢?
声卡选择
早些时候,我在本站看到了九十年代后期笔记本电脑收藏的介绍文章。其中,有些型号配备了FM音源。这让我大为羡慕。但是,毕竟尝试收藏此类产品需要不少预算,还得拼RP,这让我很是犹豫。
突然,我想到,我可以去淘二手的雅马哈724系列PCI声卡啊。
- 雅马哈724系列声卡芯片(包含YMF724、740、744、754)可算当年的中低档声卡的知名方案了,其优秀的XG MIDI效果尤为突出。但是,这个系列纯粹遵循AC'97标准,并没有44.1KHz输出能力,听CD标准的音乐需要经过重采样(后期的754声卡可以从数字接口录入44.1KHz的音频,播放依然强制使用48KHz规格),因此对音乐爱好者吸引力有限。
雅马哈724系列声卡芯片最让我关心的特点是:
1. AdLib,以及后来将声卡推广开来的创新Sound Blaster系列,其FM音源标准,使用的是雅马哈的OPL2/OPL3芯片。《仙剑奇侠传》DOS版配乐是使用OPL2芯片创作出来的。雅马哈724系列芯片具备雅马哈自己的“正宗”OPL3模块(向下兼容OPL2)。从这个角度看,它相较一些其他声卡芯片开发商自己实现的兼容OPL硬件方案,参考价值还更高一些。
2. 雅马哈724系列声卡芯片,除缩减版的740外,均原生支持SPDIF数字音频输出!
3. 经过了解,我得知,雅马哈724系列声卡芯片对较新平台的支持比较到位,兼容性较为出色。
就是它了!经过筛选,本人淘到了一块带有同轴SPDIF数字音频输出的DATALAND雅马哈724声卡。
- 注意,尽管芯片支持,并非所有的雅马哈724、744、754声卡都具有数字音频输出输入接口。有些声卡电路板上留有相应位置,但是并没有配备接口电子元件(电容、电阻、插座本身)。理论上,你可以直接将芯片相应引脚的接到主板用的SPDIF扩展卡上来获得符合规格的SPDIF接口。
声卡成色还可以,只是挡板和接口看起来很有年代感了。上机测试发现,Windows 7已经不再附带此系列声卡的驱动。换XP,直接识别声卡,有声音,初步确认声卡芯片工作正常。
那么,下面的工作,就是让它在DOS下发声了。
- 为什么是DOS下发声呢?首先,Windows XP下,应用程序想要向在DOS下那样直接访问声卡的FM音源有很大的难度,需要好多其它步骤,我不想在这里花费太多时间。其次,RIX播放插件AdPlug的Windows版编译有点麻烦,我暂时搞不定,而DOS下的播放工具是现成的,我可以较为方便地做改造以满足我的要求。第三,在DOS下实现RIX播放代码的强化也是我的一个设想。
我选择了Free DOS作为操作系统。这里我遇到了一些麻烦,好多启动U盘制作工具制作出来的U盘在我的Celeron 4 1.7GHz + 845GL 的PC上无法正常启动。最后,我使用了Disk Genius制作出来的工具盘,并对其做了一些配置,使其成为通用Free DOS启动盘。注意,这个启动盘启动PC后,其内容直接可以读写。
在DOS下播放RIX
在DOS下,让声卡的FM音源正常发声比较简单,但是涉及DMA的数字音频方面则较为复杂。就个人目的来说,我只需要FM音源能够正常工作即可,不需要数字音频播放,完全模拟Sound Blaster Pro没有必要。因此,我只需要运行雅马哈驱动程序里的SETUPDS.EXE,设置好FM音源部分即可,DMA数字音频部分的设置可以忽略(但是,每次启动系统必须要运行一次SETUPDS.EXE,可以加参数s跳过人工设置)。
经测试,运行SETUPDS.EXE并确认配置正确之后,DOS下的RIX播放程序PLAYRIX.EXE使雅马哈724的FM合成器正常发声。
YMF724这块PCI声卡在DOS下完全模拟Sound Blaster Pro(FM音源 + 数字音频)是较为复杂的。根据硬件平台不同,有三种解决方案:
- 使用Distributed DMA方案。这需要特定芯片组支持,例如Intel 430TX或440芯片组,或者ALI Alladin 4或Alladin 5[1][2]。
- 使用PC/PCI(SB Link)方案[2]。兼容性最佳,但是需要在声卡和主板之间额外接线。虽然这块声卡支持,但因为我并没有在我的主板上发现这个插座,此方案也不可行。
- 雅马哈自己的TSR程序DSDMA.EXE方案。此程序应该是包含在雅马哈后期的驱动光盘的打包文件里。最不挑主板,但比较“折腾”,也相对容易导致兼容出问题。
我的845GL主板只能使用第三种方案,用雅马哈的TSR。TSR程序包附带LOADTSR.BAT批处理文件,一般情况下推荐用这个BAT文件启动声卡DOS支持。这个文件会首先运行SETUPDS.EXE这个雅马哈的DOS4GW程序,若符合其设计预期,它会自动再运行依赖EMM386(或同类的内存管理程序)的TSR程序DSDMA.EXE。需要注意的问题是:
- 有些时候DSDMA.EXE没有自动运行,说明SETUPDS.EXE返回值不符合设计预期。但这时如果手动运行DSDMA.EXE也依然有机会可以正常工作。
- TSR加载之后,CWSDPMI不能再正常工作。如果需要使用CWSDPMI的程序,请在加载DSDMA.EXE以前运行。
- DSDMA.EXE不能支持太大的内存,比如1GB内存就会让系统在运行DSDMA.EXE时发生重启的现象。你可以使用一些办法缩小可用内存,我个人的方案是使用Free DOS的JEMMEX.EXE的MAXEXT参数做设置。
经测试,在我的平台上,使用TSR方案可以正常有声运行实模式的《轩辕剑外传 枫之舞》和保护模式的《DOOM1》(共享版)以及《魔兽争霸1》DEMO。实模式但必须使用XMS的《仙剑奇侠传》DOS版部分音效有问题。保护模式的《古墓丽影1》和《狮子王》则是在DOS4GW信息出现完毕后黑屏停止。
SPDIF数字音频输出
之前阅读资料时偶然发现,雅马哈提供的软件不能在纯DOS下启用芯片的SPDIF输出。针对这个问题,一众爱好者做出了讨论,最后由@RayeR制作出了可以在纯DOS下开关SPDIF输出的YMF7xx软件[3]。注意,此程序需要CWSDPMI支持,因此假如你需要用到数字音频功能,请记得它必须先于雅马哈的DSDMA.EXE运行。
强化RIX的播出效果
前面提到,RIX是基于AdLib ROL + INS格式的。AdLib ROL是一个面向OPL2芯片的音序格式。OPL2芯片只能输出单声道,RIX也自然只是单声道的。开源AdLib音乐播放项目AdPlug[4]有一个名叫SurroundOPL的立体声强化功能。SurroundOPL的基本实现思路是,让原OPL2输出到左声道,而右声道则由另一个OPL2模拟核心输出音高频率略有增加的声音(具体值是f + f * 1/offset,f为原频率,offset为偏移参数,默认128,使用384可正常播放所有已知音色)。这样,左右声道的声波相位就会有所不同,人听起来就会有立体感。
SurroundOPL使用了两个OPL2核心,一般的只有一个FM音源单元的声卡自然无法直接引入。但是,DOS时代中后期大部分的声卡采用的FM音源,其实是支持立体声且Operator数量多了一倍的OPL3音源。如果不进行特有的初始化设置,OPL3音源只会工作在OPL2兼容模式下。那么,我们其实可以启用OPL3音源模式,设置前一半Operator专门原样输出到左声道,设置新增的后一半Operator专门输出音高改变的声音到右声道,这样就可以在单OPL3上实现SurroundOPL了(当然,具体实现上还有一些需要注意的地方,例如OPL3音源依然只有一套打击乐鼓组,但鼓组没有立体声效果也不是大问题)。这个设计思路,由开源民间仙剑奇侠传跨平台移植项目SDLPal[5]的维护者之一@SuperMouse做出了具体的软件实现。我们是否可以将这个设计真正在OPL3硬件上实现呢?
我找到了民间版本的DOS版RIX播放程序DERIX的源代码。DERIX由首先实现RIX配乐现代系统下播放的@BSPAL编写,现阶段由SDLPal的维护者之一@palxex维护,对应Turbo C 2。
首先,是要修DERIX一直以来的一个导致滑音不正常的BUG。这个BUG在SDLPal和AdPlug下早已经被修正,但是在DERIX中同样的修正代码不能正常工作。这是为什么呢?经过跟踪测试,我发现,某个变量,在AdPlug和DERIX中值不一样。@SuperMouse指出,这是由于32位程序中INT变量则有四字节,而DERIX作为一个16位程序其INT变量是双字节的。把DERIX中相应变量的类型改为LONG后问题解决。
下一步就是将@SuperMouse版OPL3 SurroundOPL移植到DERIX上了。相对于SDLPal中的软件实现,面向硬件OPL3的程序处理还是有一些不同之处。例如,SDLPal中只需要制指定不同的寄存器号码就可以给模拟器的所有寄存器写数据,但是在硬件上,向OPL3上新增的一组寄存器写数据,就得使用不同的端口(例如,原FM音源端口是388H和389H,向新增的寄存器写数据就要写到38AH和38BH)。
- 操作OPL2/OPL3 FM音源的底层方法其实很简单,就是使用相应的函数向“寄存器编号端口”写数据来指定你要操作的寄存器,然后(对于OPL2芯片来说,需要显式地稍等片刻)向“寄存器数据端口”写具体寄存器的值。对于OPL2来讲,“寄存器编号端口”就是基准端口(388H),“寄存器数据端口”就是基准端口 + 1的端口(389H)。而OPL3新增的寄存器则安排在基准端口 + 2的端口(38AH)基准端口 + 3的端口(38BH)。寄存器编号和数据都是单字节的。这就会使得使用的新增寄存器编号数值0x1??H被减去0x100H,成为单字节的0x??H,因此需要用不同端口来区分目标是新老哪一组寄存器[6]。
解决写寄存器的问题之后,其余的工作就相对较为顺利了。至于Open Watcom适配,和@palxex做的DJGPP保护模式移植改造,则是后话。
测试结果
经过测试,我发现相较软件模拟方案的输出,声卡的模拟输出明显偏亮,中高频较为突出,而数字输出则没有这个特性。综合信息判断,我认为数字输出的结果更能体现OPL3原始设计。
- 声卡的Codec是SigmaTel的STAC9704,放大芯片是ST的TEA2025B。模拟输出的特性也许来自这部分。
- 雅马哈724系列芯片内置的FM音源其实是YMF289的改版,而不是最初的OPL3 YMF262。
- 条件所限,加上YMF724、740、744、754本来就有(据我所知是)无法绕开的MIXER,所以我也没有追求精确的原始OPL3数字输出信号。
到目前为止,我发现的游戏音乐里比较容易出现播放bug的点,都可以在《仙剑奇侠传》RIX配乐里找到。
- 曲目33《危机》,鼓点的二连镲声第二下,有些模拟核心默认状态下不能正常发出。SDLPal里有特殊的处理。
- 曲目69《灵山》,特殊打击音效对模拟核心的频率准确性方面的要求较高(SurroundOPL的偏移参数offset设为默认值128时,右声道特殊打击音效会因频率升高过多而失真)。《轩辕剑贰》的曲目RI003《黎民》也有此音效。
- 曲目71《凌云壮志》,同1。
就主观印象来说,对比雅马哈724硬件FM音源的数字输出,并参考《永恒回忆录》,SDLPal软件模拟版本和声卡硬件数字输出基本没有音乐意义上的区别,SDLPal的软件模拟FM音源已经实现了令人满意的准确性。本次测试获得的结果非常理想。SDLPal采用的软件模拟方案是成功的。
[1] https://www.vogons.org/viewtopic.php?t=18646
[2] https://www.vogons.org/viewtopic.php?t=48133
[3] https://www.vogons.org/viewtopic.php?t=49489
[4] https://github.com/adplug/adplug/
[5] https://github.com/sdlpal/sdlpal/
[6] http://www.fit.vutbr.cz/~arnost/opl/opl3.html