[原创] MAME架构、编译及配置浅析
[摘要] 众所周知,M.A.M.E是目前世界上支持驱动最多、模拟精确程度最高、开发团队实力最强及影响力最为广泛的通用街机模拟器。本文以Mame 0.105b为例,尝试从编译配置和源码结构角度出发,简要分析和描述了Mame的软件架构,并且详细论述了Mame的配置、编译及裁剪过程。作为一篇启蒙性质的文章,本文主要面向希望深入了解Mame的模拟新手,以及对Mame源码感兴趣、且具备一定技术水平的模拟老手。
1. Mame源码结构
Mame 0.105b源代码目录树结构如下:
makefile是一种用于自动编译的特殊脚本,里面记录了所有源码的编译步骤、规则及相互依赖关系,多用于跨平台的命令行编译场合。它可以类比于我们熟悉的Windows中VC++的"工程文件",但是与IDE自动生成的工程文件不同,makefile脚本一般由开发者手工编写。为简洁起见,在Mame的makefile中定义了大量模板规则(pattern rule),同时,其整套编译脚本也从功能性的角度被划分为如下6个文件:
其中,后5个mak脚本用来生成相应的功能模块,而作为主控脚本./makefile则负责调用(include)上述的5个mak脚本,实现5个功能模块的链接并生成最终的mame.exe文件。
2. Mame软件架构
2.1 总体架构
早期Mame的软件架构变动得非常频繁,只有Nicola Salmoria和Aaron Giles等少数几个教父级核心开发者才能把握其细节。随着Mame的逐步成熟及其支持驱动数量的日趋庞大,Mame Team已经充分意识到了架构稳定的重要性,并终于在2005年的上半年宣布Mame的结构基本定型,这同时也说明:从源码分析角度一窥其堂奥的机会终于成熟了。鉴于0.106u2版之后的Mame引入了全新的显示系统,该系统目前仍在测试中,因此在这里我们将主要以较新的0.105稳定版作为具体分析实例。
根据Mame的源码及makefile编译结构,我们可得出其目前的总体架构图如上。如图所示,整个Mame架构可划分为核心层和OSD层共2个层次;其中的核心层又引用了驱动、CPU核心及声音芯片核心等3个模块,它们都是平台无关的;而针对Windows的OSD层则为核心层集中提供了面向操作系统的具体实现接口,所有的Win32 API和DirectX实际调用均由OSD层来实现。可以看出,通过替换OSD层,可以很方便地将Mame移植到不同的操作系统中,并使用不同的底层多媒体控制机制,如MacOS-Linux/SDL等,但是反过来,这种具备良好移植性的分层结构恰恰也是导致Mame模拟效率低下的主要原因之一,对移植性的追求使得Mame不可能100%的充分利用平台相关的硬件加速能力。
2.2 谁需要关注Mame架构和源码?
作为一个在模拟界拥有绝对领导地位的庞大项目,参与Mame开发的人员自然形形色色,而各自期望了解Mame的目的也是多种多样的。从其软件结构上可以看得出来,关注Mame架构及源码的人主要包括核心框架开发者、模拟技术研究者和驱动开发者3类(当然,现实中并不一定划分得那么绝对,如Nicola、Aaron和Haze等大牛往往身兼数职):核心开发者主要负责Mame核心层及高层软件框架的研制工作;模拟技术研究者主要关注CPU及声音芯片等核心部件的模拟实现,出于为CPU等模拟部件提供标准复用接口的目的,他们对Mame架构也必须有所了解;而游戏驱动开发者做的工作则主要是利用Mame已有的流程、框架以及模拟部件,接合自己对真实主机运行细节的理解来实现具体的游戏驱动,如虚拟主机定义、定制视频/音频硬件模拟等;很显然,Mame核心框架和已有的核心部件是驱动开发的基础,它们是可共用的,它们让驱动开发者们能够集中精力解决被模拟主机所特有的细节问题,而不必去考虑如何重复实现那些模拟器通用的处理流程和部件——就好比Windows程序员们使用MFC一样(突然发觉这个比喻很贴切: CPU等核心部件可类比MFC标准类、Mame框架就好像MFC Framework、而游戏驱动则就是那使用了MFC消息映射等框架机制及类库的用户代码部分);由于Mame支持的游戏驱动数量极其庞大,驱动开发者的数量无疑也是最庞大的,同时他们往往也是早期Mame架构频繁变动的最大受害者,值得庆幸的是,他们并没有放弃Mame,Mame也没有放弃他们——目前Mame的结构终于定型了,而且0.106u2版本后所引入的显示系统新变动也主要集中在Mame核心层和部分OSD接口,对驱动模块及CPU、声音芯片模块的影响并不大,主要是一些显示相关配置方式上的改进,驱动开发者们终于可以安心了。
除上述3类直接参与的开发者之外,圈子里还存在着不少专用模拟器开发者对Mame的源码感兴趣(尽管他们不一定参与了Mame的研制),这是因为他们能够从Mame源码中获取到宝贵的主机信息;事实上,Mame的参考文献价值远远超越了它为给普通玩家所带来的游戏乐趣,这也正是Mame Team为什么会如此"孤高而又傲慢地"追求模拟精确性的根本原因。在真正模拟器开发者的眼中,Mame并不仅仅等同于一个慢吞吞的模拟器,它更像是一本百科全书,而关于Mame的框架常识则是这本Bible的目录和索引。另一方面,也有不少热爱DIY、期望精简Mame的驱动并在自己的机器上对其进行优化编译的模拟爱好者对阅读Mame源码感兴趣,如果你正好是其中一员,那么你将非常幸运:这篇文章几乎就是为你写的;当然,你也会发现这篇文章的内容并不仅限于此。
不管怎样,我希望此文的读者能够首先明确自己的理想和目标——这将是你征服Mame悬崖般陡峭的学习曲线的唯一希望所在。Okay,扯远了,下面让我们回到技术话题上来:具体看看Mame架构中各个组成部分所实现的功能。
2.3 OSD平台依赖层
Mame源码中仅自带了针对Windows的OSD层代码,其全部位于src/windows目录中。考察其中的windows.mak可以发现,该OSD层代码分为针对Win32和针对DirectX两个部分,前者包括Windows相关的MinGW_GCC/Link编译选项、Win32窗体及其UI显示代码、内存分配调试代码(接管标准C运行库中的内存分配函数,以便于检测内存泄漏)、虚拟机调试窗口代码和Win32资源文件编译等;后者则包括DInput、DSound、DDraw等DirectX函数调用接口的编译。说得简单点,就是一半代码负责Win32系统调用及窗口管理,而另一半负责DirectX媒体访问控制。
2.4 Mame核心层
核心层是完全与平台无关的,在src/core.mak中详细给出了核心层的编译选项及过程。作为Mame的最高层框架,核心层定义了一系列与平台实现无关的抽象数据结构及其处理流程,如抽象位图、抽象色板和抽象音频流等,其具体表述及功能的实现均依赖于OSD底层;所有高层抽象结构在具体执行过程中均将被映射成为OSD层中的对应实体,如DDraw里面的Off-Screen Surface、DSound中的SecondaryBuffer等;而针对位图、音频等抽象实体的实际操作则均通过调用底层OSD层接口来间接完成。同时,核心层还为所有的CPU核心、声音芯片和游戏驱动(Romset、虚拟机器、内存映射、I/O映射、虚拟视频硬件和虚拟音频硬件等)定义了统一的数据及操作/回调接口,可以说,核心层构成了Mame最重要的宏观架构,同时也是分析Mame代码的最佳入手点。
2.5 CPU核心及声音芯片
考察src/cpu/cpu.mak和src/sound/sound.mak可以发现,在Mame的配置中,其按照不同类型、不同厂家的规则对CPU模拟核心和声音芯片进行了分组,这使得我们可以很方便地从mak文件中抽取出生成任一特定CPU核心或声音芯片的编译步骤。在CPU核心编译过程中,以68000核心的编译过程最为复杂(用到了重编译代码生成器技术,生成m68k核心的步骤与利用lex/yacc生成编译器类似),而在声音芯片代码中则Yamaha家族的较繁琐点。
CPU核心与声音芯片模块均是可以跨平台的,因此,其99%的代码均使用C语言编写,只有极少部分采用了汇编(现在你应该知道Mame模拟效率低下的另一个理由了),同时考虑到不同汇编语法的复杂性,代码中很少采用C语言的嵌入式汇编,而是将汇编部分单独分离出来,额外地组织成相应的asm文件(采用Intel语法),使用可跨平台的Nasm进行编译。
完全理解CPU核心、声音芯片模拟的代码需要具备扎实的编译器研发技能和较为全面的数字/模拟信号处理及电路常识,这些过于专业的要求显然令人望而生畏。但不必紧张,对于绝大多数的人而言,仅需知道如何通过Mame核心层提供的标准接口使用这些核心部件便足够了,至于如何实现它们就交给牛人们去操心吧。
2.6 游戏驱动部分
2.6.1 Mame驱动概述
游戏驱动是Mame中较为关键的一个组成部分,其代码是与平台无关的,多采用C语言编写。游戏驱动包括了Mame中某个游戏正常模拟运行所需的一切信息,下面我简要罗列一下这些信息,希望能给各位好奇的读者们一个"华丽的"的第一印象:
![](/images/cnblogs_com/neoragex2002/MameCompile/4.png)
Hmmm…我知道在你看过了上述信息之后的感受一定很复杂… Mame驱动相关的信息是非常细致而又庞大的,我相信你已经体会到了;但这里我想强调的是: 这些信息实际上并不像你想象的那么混乱,其实它们之间的联系非常紧密。仔细看看上面的那个表,我们可以将其驱动信息划分成CPU、Romset、I/O与输入设备、视频设备和音频设备等5类,其中,CPU部分包括了正确模拟CPU运行行为所需的全部信息,如内存映射、I/O端口映射和中断管理等;而Romset代表着游戏的程序正文和数据;输入设备告诉我们这个游戏用的是摇杆、光电枪还是跟踪球,音、视频设备的作用不用多说了吧?不难发现上述分类跟我们所了解的基板硬件结构是一一对应的,事实上,街机作为一种游戏专用的嵌入式系统,恰恰也就是由上述5个部分构成。
另一方面,我们还可以发现,在Mame驱动体系中,存在着"游戏驱动"(DRIVER)和"虚拟机"(MACHINE)的逻辑层次划分:为降低研发成本,不少游戏使用了相同的基板,因此其硬件配置是基本一致的,比方说Neo.Geo MVS系列和CPS1/2系列,既然如此,它们完全可以重用同一份"虚拟机"驱动定义;但是,在实际模拟它们的时候,还需考虑每个游戏自身的具体情况,比如MVS中存在着的Rom加密现象——某些较新的游戏roms加载后需要解密,而多数早期游戏则不需要,为了让这些新游戏能够正常运行,我们有必要在Mame驱动架构中为它们添加一些额外的驱动信息及其驱动行为。简而言之,"虚拟机"定义记录的是多个游戏可共用的驱动信息及操作,而"游戏驱动"定义则记录的是某一游戏所特有的驱动信息及行为,这实际上是一种对象继承关系的体现。(熟悉OOP的朋友将很快会发现,在Mame的C源码中大量采用了宏定义来模仿C++的面向对象特征,甚至是多态性实现,这令源码分析难度进一步提高了,但与此同时它也带来了相对简洁、方便的架构设计及编码,前提是你要能看得懂——这几句话是写给技术水平较高的读者看的)
只要有足够的耐心,我们可以在Mame驱动源码中找到关于某个特定游戏的任一上述信息,而知道在何处找到这些信息则是我们应当关注的重点。从源码结构角度来说,一般而言,一个游戏的完整驱动主要包括驱动注册、驱动定义及实现、定制视频硬件、定制音频硬件和周边器件等5个代码模块,它们分别对应着src/mamedriv.c、src/drivers/$(zip_name).c、src/vidhrdw/$(zip_name).c、src/sndhrdw/$(zip_name).c和src/machine中的某些文件,这里的$(zip_name)指的是游戏Romset的zip名,如ddragon、ddragon2等。其中,除了前二者之外,其他3部分是可选的,因为前面已经说过了:某些模块和信息是可以多个游戏共用的。在这些代码模块中包含了所有的驱动信息,因此,为Mame添加一个新游戏驱动的过程通常包括了添加或修改上述一系列文件的过程。为了提高可读性,这些不同的代码模块通常使用相同的文件名,即$(zip_name)(如双截龙Double Dragon,其主Romset名为ddragon,则其驱动模块文件名均为ddragon.c),但分别存放在src/drivers、src/vidhrdw、src/sndhrdw和src/machine等4个不同的子目录中。
在这5个驱动文件中,src/mamedriv.c作为一个全局共用模块,负责实现所有游戏驱动在Mame框架中的注册,所谓驱动注册就是让Mame知道自己支持模拟哪些游戏,以便提供相应的命令行及驱动载入接口,如果驱动不注册的话,即使它已被编入了Mame中,用户也无法启动其模拟过程;位于src/drivers中的文件则给出了被模拟游戏的虚拟硬件定义,如Romset、内存映射、I/O映射、使用的CPU/声音芯片和视频布局等绝大多数驱动信息;位于src/vidhrdw中的文件封装了该游戏所定制的视频模拟例程,相当于实现了该游戏所需要的虚拟视频硬件,多数游戏都有对应的视频硬件模拟实现,当然,如果新游戏使用的视频硬件和另一个已有游戏是完全一样的,它完全可以重用已有游戏的对应文件;与vidhrdw类似的,位于src/sndhrdw中的文件封装了游戏所定制采用的音频模拟函数,相当于实现该游戏所需要的虚拟音频硬件,如离散音频系统等,定制专用音频硬件的情况大多存在于早期游戏中,它远不及定制视频硬件那么普遍,为达到成本、效果及灵活性的折衷,后期游戏多采用音频解码/控制CPU配合标准声音芯片的集成方式,因此很多游戏并不存在对应的sndhrdw实现;最后,在src/machine中则保存了游戏模拟所需的其他周边硬件的虚拟实现,如NVRAM、EEPROM、记忆卡和实时时钟等,它们在多数游戏基板中使用得非常普遍,我们可以将src/machine这一目录中的文件看成由多个游戏驱动所共享的"周边硬件"代码库。
2.6.2 驱动文件查找范例
位于src/目录下的mame.mak配置文件是与驱动编译直接相关的,其内部结构组织得非常具有启发性,无形中为我们提供了非常多的"隐含"信息,使得我们能够非常方便地找到某特定游戏所对应的驱动代码文件。下面我专门给出一个Step by Step实例:查找ddragon和ddragon2(双截龙1、2代)两个游戏所对应的驱动文件。
- 首先获取Mame支持的所有游戏的详细信息,命令行下,运行"mame -listxml | xml2info > mame.lst",得到mame.lst,里面存放了所有游戏的详细驱动信息,包括游戏名、Romset、对应驱动文件、所使用的CPU和声音芯片及其DIP信息
- 用编辑器打开mame.lst,查找字符串"ddragon"和"ddragon2",发现两者的sourcefile字段均为ddragon.c,这说明ddragon和ddragon2的驱动均为同一文件:src/drivers/ddragon.c
- 仔细看看这两个游戏的其他信息,在chip字段中发现ddragon的CPU为HD6309和HD63701,声音芯片为YM2151和MSM5205,而ddragon2的CPU则为HD6309和Z80,声音芯片为YM2151和OKI6295(不用恐惧,几乎90%以上的街机都是多CPU架构)
- 再来,打开src/mame.mak文件,根据src/drivers驱动文件名ddragon.c查找对应obj的字符串"ddragon.o",发现了如下信息:
$(OBJ)/technos.a: \ $(OBJ)/drivers/battlane.o $(OBJ)/vidhrdw/battlane.o \ $(OBJ)/drivers/blockout.o $(OBJ)/vidhrdw/blockout.o \ $(OBJ)/drivers/bogeyman.o $(OBJ)/vidhrdw/bogeyman.o \ $(OBJ)/drivers/chinagat.o \ $(OBJ)/drivers/ddragon.o $(OBJ)/vidhrdw/ddragon.o \ $(OBJ)/drivers/ddragon3.o $(OBJ)/vidhrdw/ddragon3.o \ $(OBJ)/drivers/dogfgt.o $(OBJ)/vidhrdw/dogfgt.o \ $(OBJ)/drivers/matmania.o $(OBJ)/machine/maniach.o $(OBJ)/vidhrdw/matmania.o \ $(OBJ)/drivers/mystston.o $(OBJ)/vidhrdw/mystston.o \ $(OBJ)/drivers/renegade.o $(OBJ)/vidhrdw/renegade.o \ ...... |
- 上述信息中的"technos.a"字样告诉我们,在编译Mame时,MinGW GCC将会把所有Technos公司出品的街机驱动编译所得的obj统统打包到同一个.a包中,用于link;另一方面,请特别注意其中每一行的分行方式,这是因为——这里的每一行都给出了与src/drivers/中的驱动代码所对应的其他驱动模块,例如,对于ddragon/ddragon2的驱动文件src/drivers/ddragon.c,它所对应的其他驱动模块为src/vidhrdw/中的ddragon.c文件,而matmania驱动则对应着两个其他驱动模块,src/machine/maniach.c和src/vidhrdw/ matmania.c。mame.mak中给出的这些信息对于Mame的裁剪编译是非常有价值的,这将在下文中进一步提到
- 最后说说如何查找ddragon/ddragon2所涉及的src/machine中的周边设备驱动文件,有两种做法,一种是干脆不去找,直接将src/machine中的所有文件均编译/打包成shared.a(请参见mame.mak中关于shared.a的编译过程定义一节),统统链接进最终的可执行文件,但是这将导致编译所得执行文件长度的膨胀;另一种做法是打开src/drivers/ddragon.c,简要查看一下其引用的头文件,这里,我们在ddragon.c中并没有发现任何src/machine头文件的引用,因此这两个游戏均未显式使用src/machine中特殊的周边硬件
- 综上,我们可以得出结论了:ddragon和ddragon2所对应的驱动文件主要包括src/drivers/ddragon.c、src/vidhrdw/ddragon.c;此外,为驱动这两个游戏,还必须包括3个CPU核心:HD6309、HD63701和Z80,以及3个声音芯片模拟核心:YM2151、MSM5205、OKI6295
3. 编译及配置
Mame的编译过程相对简单。以Mame 0.105b为例,其在Win32下的标准编译环境主要包括:编译器MinGW 5.0、DirectX 8库及头文件(for MinGW)、汇编器Nasm 0.98.39(for Win32)。详细编译步骤如下:
- 下载Mame 0.105b的源码mame0105s.exe
- 下载mingw-mame-20060210.exe、dx80_mgw.zip和nasm-0.98.39-win32.zip
- 将Mame 0.105b源码解压缩到c:\mame105
- 解压mingw-mame-20060210.exe到c:\mingw,并将dx80_mgw.zip直接解压至c:\mingw
- 将nasm-0.98.39-win32.zip解压至c:\mingw\bin中
- 设置Windows环境变量,在PATH中添入c:\mingw\bin
- 将c:\mingw\bin\mingw32_make.exe改名为make.exe,至此,编译环境配置完毕
- 用编辑器打开c:\mame105\makefile,配置其中的编译选项
- 命令行下,在c:\mame105目录中运行make,开始正式编译
整个Mame编译过程包括Maketree、工具库编译、模拟器编译、可执行工具生成4个步骤。Maketree用来创建存放临时obj的目录树,工具库编译主要包括expat库(用于解析XML)和zlib库(用于直接zip压缩/解压缩)2部分工作,而可执行工具生成则包括romcmp、chdman和xml2info等3个工具软件的编译工作,它们的具体功能请参考Mame随机文档。
如第8步所述,我们可以通过修改makefile中的配置选项来指导make的编译行为,下面给出了几个常用编译选项的说明:
![](/images/cnblogs_com/neoragex2002/MameCompile/5.png)
也可以使用VC7/VC8对Mame进行编译,使用微软的IDE调试起来非常方便,但其缺点则在于编译配置不够灵活,不便裁剪,不及makefile好用,详细步骤请参考VCMame.net。VC8下的试验表明:在最大可能优化的场合下,VC编译的Release版本较GCC在速度方面仅有一定程度的提高,并不十分显著,但是在缩短可执行文件长度方面的效果却非常惊人:VC的编译尺寸一般只有GCC版本的一半。
4. 裁剪编译及范例
在粗略了解了Mame的软件架构、源码结构及其编译配置之后,我们便可以对其进行裁剪和定制编译了。通过精简不必要的CPU核心、声音芯片模块及游戏驱动,而仅保留若干个我们需要的游戏驱动,可以令Mame文件长度更小、运行时占用的内存资源更少。同时,对Mame进行裁剪编译还有一个重要目的:它有助于我们深入了解Mame本身的源码结构,从而为添加全新驱动提供坚实的实践基础。
对Mame编译过程的裁剪工作主要集中在对mame.mak内部编译配置的修改。如上文所述,在src/mame.mak中保存了全部编译相关的驱动配置,同时,通过查看mame.mak内容我们还可以发现,其内部定义的$(CPUS)和$(SOUND)两个make脚本变量将直接影响src/cpu/cpu.mak和src/sound/sound.mak的编译行为,决定着某一特定的CPU核心及声音芯片是否被编译,因此,仅需修改mame.mak文件即可完成全部的裁剪工作。事实上,在Mame 0.105b源码中已经为我们提供了一个专供裁剪编译配置参考的简化版mame.mak模板——src/tiny.mak。我们可以通过重定义或修改./makefile中的TARGET脚本变量来指定make编译时使用mame.mak还是tiny.mak。
下面仍以两个ddragon为例,举个实际例子来说明裁剪配置的全过程,编译一份ddragon/ddragon2专用的Mame:
- 动手之前,我们假定你已经获得了一份完整编译的Mame 0.105b可执行文件(mame.exe)
- 根据2.6.2节中范例的分析,ddragon和ddragon2所对应的驱动文件包括src/drivers/ddragon.c、src/vidhrdw/ddragon.c;所需CPU核心包括HD6309、HD63701和Z80,声音芯片核心包括YM2151、MSM5205、OKI6295
- 用编辑器打开src/tiny.mak文件,初步修改如下:
# 这里两个宏定义只用在tiny.c中,用于驱动注册,照葫芦画瓢即可。是的是的,如果需要支持100个游戏,那么你就得在这里手工写100个"driver_xxx",这确实很烦;其实tiny.c实际上就是mamedriv.c的简化版,因此你也可以直接用后者来进行编译,但需要修改mamedriv.c和编译脚本,限于篇幅,我就不多写了 # 友情提示: 注意mamedriv.c中采用的一些C语言惯用技巧——重复宏定义和递归宏展开 COREDEFS += -DTINY_NAME="driver_ddragon,driver_ddragon2" COREDEFS += -DTINY_POINTER="&driver_ddragon,&driver_ddragon2" # CPU配置,将所有用到的CPU都添加进$(CPUS)中 CPUS += Z80 CPUS += HD6309 CPUS += HD63701 # 声音芯片配置,将所有用到的声音芯片都添加进$(SOUNDS)中 SOUNDS += YM2151 SOUNDS += OKIM6295 SOUNDS += MSM5205 # 驱动文件配置,这里应把我们当前所发现的所有驱动文件及相关的驱动模块全部添入 DRVLIBS = $(OBJ)/vidhrdw/ddragon.o $(OBJ)/drivers/ddragon.o # tiny.o绝不可删除,因为src/tiny.c中包括了驱动注册的相关代码,事实上tiny.c就是src/mamedriv.c的精简版 # 如果不想使用作弊功能,可以将cheat.o删除 COREOBJS += $(OBJ)/tiny.o $(OBJ)/cheat.o |
- 命令行下,在c:\mame105目录中运行"make TARGET=tiny clean"
- 同一目录的命令行下,再次运行"make TARGET=tiny",开始正式编译
- 你将会很郁闷地发现编译中途出错,提示缺少M6800和M6803 CPU核心相关的obj文件...不会吧?!没有用到M680x系列的CPU啊??
- 查阅一下src/cpu/cpu.mak中M680x系列CPU核心的编译配置,你会很惊讶地发现HD63701与M680x居然使用的是同一份代码...
- 没啥好说的,直接将M6800/M6803添加至$(CPUS)完事,但记住不能删除HD63701,因为它将作为一个标志被记录在游戏相关的驱动注册信息中,用于Mame启动时配置验证;再次修改的tiny.mak内容如下:
COREDEFS += -DTINY_NAME="driver_ddragon,driver_ddragon2" COREDEFS += -DTINY_POINTER="&driver_ddragon,&driver_ddragon2" # 注意这里不能将HD63701删除,否则将在第12步验证时发现ddragon的CPU配置为空,导致Mame无法启动,提示"ddragon uses non-present CPU" CPUS += Z80 CPUS += HD6309 CPUS += HD63701 CPUS += M6800 #新添加的!! CPUS += M6803 #新添加的!! SOUNDS += YM2151 SOUNDS += OKIM6295 SOUNDS += MSM5205 DRVLIBS = $(OBJ)/vidhrdw/ddragon.o $(OBJ)/drivers/ddragon.o COREOBJS += $(OBJ)/tiny.o $(OBJ)/cheat.o |
- 你一定会问,如何确保写入tiny.mak中CPU核心和声音芯片的宏标识符(如OKIM6295等)是正确的?这很容易,根据6309、63701、6800、2151、6295等特征字串在mame.mak或者是cpu.mak、sound.mak中查找确认一下即可
- OK,再次"make TARGET=tiny",编译成功,并最终获得一个名为tiny.exe的裁剪版可执行程序(1.8MB),不妨将其和完整编译的mame.exe(40MB)比比哪个大? 呵呵
- 下面来验证一下编译结果,首先运行"tiny -listfull"打印游戏列表,确认一下是否仅支持ddragon和ddragon2两个游戏
- 然后再次运行"tiny -listxml",打印ddragon/ddragon2的全部驱动信息,仔细检查一下ddragon和ddragon2的CPU核心与声音芯片配置是否与我们需要的相符,注意,驱动信息中的任一个CPU、声音芯片字段均不能为空,否则说明驱动添加失败,Mame将提示"xxx uses non-present CPU/Sound chips",导致无法启动
- 如果上述两步检查均通过,那么恭喜你,赶紧输入"tiny ddragon"或"tiny ddragon2"开打吧!对了,记得别忘了将ddragon.zip和ddragon2.zip这两个roms文件放在c:\mame105\roms里面哦....
5. 我们能够做点什么?
好了,终于可以收尾了。如果你能坚持看到这里,那么你一定不仅仅只是一名模拟器的玩家,而更有可能是一位真正关注模拟界发展、并有志为其作出贡献的技术人员(这也是为什么我要写这么长的目的....^^)那么最后说点大家都感兴趣的话题吧,深入了解并熟悉Mame源码之后,我们能够做点什么。
如果你还只是个刚接触Mame源码的新手,但具备相当的意志和实力,那么你可以帮Mame做做驱动方面的优化工作,因为正如你在上文所看到的,Mame确实不是很关注效率的问题,无论架构还是实现,Mame Team的Guru们心里想得更多的是如何精确精确再精确、前进前进再前进,而通常不倾向于理会fans们的种种要求,如果你是真心怜悯那帮啥都不懂却成天抱怨这个速度太慢那个效果不好的可怜fans,你完全可以抛开Mame已有的架构,仅将Mame源码当作一个无价的资料库,全靠一己之力来实现一套全新的、与平台绑定的优化模拟架构,就像曾经写过Final Burn的David、开发Kawaks的Mr. K和星云大师Elsemi一样,很多牛人都是这么一路走过来的,这是让自己逐渐成熟起来并最终走向创新的必由之路,同时也能帮助你在圈子里面迅速地赢得超强人气,获得仅次于Mame Team的专用模拟器开发者所拥有的名誉和尊重;或者你也可以考虑考虑为Mame中的众多游戏添加状态保存功能、做做测试并提交驱动补丁,这些都是很受Mame开发者欢迎的非常有意义的事情,尽管不够酷。或许你已经是个Guru了,那么很抱歉....也许这篇启蒙性质的文章对你而言并没有太多价值,也许你更情愿不受打搅地完成更多该做的事情,比方说加入Mame Team、让Capcom CPS3保护加密去见鬼、编写200%高效模拟且支持动态重编译的64/128bit CPU核心、为Sammy AtomisWave和Sega Lindbergh提交梦幻般的完美驱动、把Mame当作VMWare并为其添加一个可以启动Linux的驱动等等... 总之,奇迹仅限于实力和想象力。
不管怎么说,我希望能够通过这篇长文来激发目前国内对Mame更深层次的技术思考,尽管它本身非常粗浅。如果你看过此文之后发现自己对待Mame的态度变得比以前更为严肃,我将非常欣慰,因为我达到了我的目的。
更新记录:
2006-06-17 应约稿请求,修订稿成文
2006-06-12 授权《模拟地带》发表
2006-06-05 初稿成文