
FinalBurn Alpha 2.9x
中CPS2游戏驱动程序的编写
作者:胡颖卓
FinalBurn Alpha是当今最好的CPS1/2模拟器之一,更可贵的是它是完全开放源码的。从FinalBurn Alpha 2.93开始,FinalBurn Alpha小组(以后简称FBA小组)便转向了多功能、多机种的支持,而不是像其它模拟器那样,出一个新游戏的破解就出一个新版,或是有一点儿改进就出一个新版。这样做利了开发者,而玩家却是觉得有些不便。
起初,我为大家写一些新版本的FBA,但这样会和FBA小组的版本对应不上。更是近来,我需要将主要精力放在网络游戏上,所以也没有太多的时间为大家写这些驱动。在这里,我针对FinalBurn Alpha 2.93的CPS2游戏19xx驱动为例,给大家做一下讲解,以便大家能自己写出新的驱动。
首先,要包含驱动头文件cps.h,语句如下:
#include"cps.h"
再者,是输入设备定义,也不用讲解,照例子抄就行了:
static struct BurnInputInfo DrvInputList[] =//19xx是两键游戏,如果是3键游戏,只需要按顺序加上就行了,例如
//{"P1 AutoFire", 0, CpsInp001+6, "p1 auto fire"},
{"P2 Coin" , 0, CpsInp020+5, "p2 coin" },
{"P2 Start" , 0, CpsInp020+1, "p2 start" },
{"P2 Up" , 0, CpsInp000+3, "p2 up" },
{"P2 Down" , 0, CpsInp000+2, "p2 down" },
{"P2 Left" , 0, CpsInp000+1, "p2 left" },
{"P2 Right" , 0, CpsInp000+0, "p2 right" },
{"P2 Shot" , 0, CpsInp000+4, "p2 fire 1"},
{"P2 Bomb" , 0, CpsInp000+5, "p2 fire 2"},
{"Reset" , 0, &CpsReset , "reset" },
{"Diagnostic" , 0, CpsInp021+1, "diag" },
{"Service" , 0, CpsInp021+2, "service" },
};
STDINPUTINFO(Drv);
也有一种特殊情况,由于CPS2下格斗游戏非常多,而且使用的按键定义方法也一样,比如《少年街霸3》,我们就可以使用以下方法来定义:
STDINPUTINFOSPEC(Drv, CpsFsi);按照Razoola的定义,ROM的编号方式按照芯片的排列来进行编号:

具体到文件名,扩展名编号方式如下:
01-02 QSound Z80数据 03-10 程序数据 11-12 QSound采样数据 13-20 图像数据ROM表的写法我们来看看19XX的写法:
static struct BurnRomInfo NinexxRomDesc[]=这里面Ninexx是我们自己可以定义的名称,改成_19xx也是可以的。
之后是驱动信息结构,19XX的写法如下:
运行标志,如果为纵版需要加上BDF_ROTATE_GRAPHICS_CCW
最大玩家数量
硬件类型
取zip名称特殊函数
Rom信息结构
Rom名称结构
输入配置信息表
DIP配置表
驱动初始化函数
驱动关闭函数
游戏帧处理函数
游戏刷新函数
游戏剪裁处理函数
游戏调色板空间
游戏画面宽度
游戏画面高度
游戏画面纵横比
BDF_GAME_WORKING | BDF_ROTATE_GRAPHICS_CCW,
2,
HARDWARE_CAPCOM_CPS2,
NULL,
NinexxRomInfo,
NinexxRomName,
DrvInputInfo,
NULL,
DrvInit,
DrvExit,
Cps2Frame,
CpsRedraw,
CpsAreaScan,
&CpsRecalcPal,
224,
384,
3,4
};
DrvExit函数我们不用去管它,直接照抄一个就行了,关键在于DrvInit函数。下面我们来看一下19XX的DrvInit函数,并为大家做详细的讲解:
static int DrvInit() nCpsRomLen = 5*0x080000; //程序数据长度 对应文件3-10
nCpsCodeLen= 4*0x080000; //需要XOR表解密的长度 对应文件3-10
nCpsGfxLen = 0x1000000; //图象数据长度 对应文件13-20
nCpsZRomLen= 1*0x020000; //QSoundDataZ80数据长度 对应文件1-2
nCpsQSamLen= 2*0x200000; //QSoundSample长度 对应文件11-12
nRet=CpsInit();
if(nRet!=0)return(1);
// 装载程序ROM,这里5为程序ROM数量,4为XOR表ROM数量
for(i=0;i<5;i++)
{nRet=BurnLoadRom(CpsRom+0x080000*i,4+i,1); if (nRet!=0) return 1; }
// 解密程序ROM,这里4为XOR表ROM数量
memcpy(CpsCode,CpsRom,nCpsCodeLen);
for (i=0;i<4;i++)
{ nRet=BurnXorRom(CpsCode+0x080000*i,0+i,1); if (nRet!=0) return 1; }
// 装载图像ROM
nRet=Cps2LoadTiles(CpsGfx , 9); //每次可以装载4个,后面的数字是ROM的起始编号
nRet=Cps2LoadTiles(CpsGfx+0x0800000,13); //0x0800000为前面4个ROM的总容量
// 装载Z80 ROM
nRet=BurnLoadRom(CpsZRom,17,1); //同上面的,17为起始编号,1为ROM数量,一次只能装载1个
// 装载QSound Samples ROM
pqs=(unsigned char *)CpsQSam;
nRet=BurnLoadRom(pqs ,18,1); //18为编号,ROM数量仅为1
nRet=BurnLoadRom(pqs+0x200000,19,1); //
BurnByteswap(pqs,nCpsQSamLen);
nRet=CpsRunInit(); if (nRet!=0) return 1;
return 0;
}
至此,以上的讲解已足够大家为新的游戏写出一个驱动了,希望下次Razoola放出新的CPS2游戏XOR表时,大家能够不至于等待谁写出新的驱动,而可以自己解决。
全文完