存档在 ‘FinalBurn Alpha’ 分类

FinalBurnAlpha中NEO-GEO游戏驱动程序的编写

2009年11月5日

作者:胡颖卓


二年前我写了《FinalBurn AlphaCPS-2游戏驱动程序的编写》一文,现由于模拟器界的三年原则惯例,所以很久都没有新的CPS-2游戏XOR表出现了。而现今由于SNK的复活,NEO-GEO游戏又慢慢的多了几个出来,所以我特地再为大家撰写这篇文章。

FinalBurn Alpha中,NEO-GEO驱动相比CPS-2驱动写起来较为简易,下面我以SNK PLAYMORE的大作《侍魂 零》为例,告诉各位如何编写它的驱动程序。

打开src\burn\neogeo\d_neogeo.cpp文件。

首先是书写游戏的ROM描述表:

static struct BurnRomInfo samsho5RomDesc[] =
{//    文件名        长度      CRC校验码   类型

{“270-p1.bin”, 0x800000, 0x611A6687, 0x10}, // 0 68K 代码

{“270-s1.bin”, 0x020000, 0x33227D62, 1},    // 1 文字层图片数据

{“270-c1.bin”, 0x800000, 0x4E7BDEA1, 1},    // 2 图片数据
{“270-c2.bin”, 0x800000, 0x7B444985, 1},    // 3
{“270-c3.bin”, 0x800000, 0x8C709A9B, 1},    // 4
{“270-c4.bin”, 0x800000, 0xCFD53F5C, 1},    // 5
{“270-c5.bin”, 0x800000, 0xC026D318, 1},    // 6
{“270-c6.bin”, 0x800000, 0xB3D9D204, 1},    // 7
{“270-c7.bin”, 0x800000, 0xFE03A025, 1},    // 8
{“270-c8.bin”, 0x800000, 0x89DB2D34, 1},    // 9

{“270-m1.bin”, 0x020000, 0x18114FB1, 0x10}, // 10 Z80 代码

{“270-v1.bin”, 0x400000, 0x6849136C, 2},    // 11 声音数据
{“270-v2.bin”, 0x400000, 0x222E1774, 2},    // 12
{“270-v3.bin”, 0x400000, 0xCD9E7ADC, 2},    // 13
{“270-v4.bin”, 0x400000, 0x8B305CAC, 2},    // 14

};

接下来是驱动的描述:

STDROMPICKEXT(samsho5, samsho5, neogeo);
STD_ROM_FN(samsho5);

struct BurnDriver BurnDrvSamSho5 =
{

{

“samsho5”,                //ROM文件名称
“Samurai Shodown V”,      //游戏名称
“”,                       //其它信息
“SNK Playmore”,           //游戏开发商
“Neo Geo”,                //游戏机型说明
“2003”,                   //游戏发行年代
NULL,                     //游戏主ROM名称
“neogeo”                  //游戏BIOS

},

BDF_GAME_WORKING,
2,                             //游戏人数
HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP | HARDWARE_SNK_SWAPC | HARDWARE_SNK_SRAM,
NULL,
samsho5RomInfo,                //ROM信息
samsho5RomName,                //ROM名称
neogeoInputInfo,
neogeoDIPInfo,
NeoInit,
NeoExit,
NeoFrame,
NeoRender,
NeoScan,
&NeoRecalcPalette,
nNeoScreenWidth,
224,
4,3

};

最后我们只需要在src\generated\driverlist.h中加入相应的项就可以了,祝大家玩的愉快!


FinalBurn Alpha 0.2.9x 中CPS2游戏驱动程序的编写

2009年11月5日

作者:胡颖卓


FinalBurn Alpha是当今最好的CPS1/2模拟器之一,更可贵的是它是完全开放源码的。从FinalBurn Alpha 2.93开始,FinalBurn Alpha小组(以后简称FBA小组)便转向了多功能、多机种的支持,而不是像其它模拟器那样,出一个新游戏的破解就出一个新版,或是有一点儿改进就出一个新版。这样做利了开发者,而玩家却是觉得有些不便。

起初,我为大家写一些新版本的FBA,但这样会和FBA小组的版本对应不上。更是近来,我需要将主要精力放在网络游戏上,所以也没有太多的时间为大家写这些驱动。在这里,我针对FinalBurn Alpha 2.93CPS2游戏19xx驱动为例,给大家做一下讲解,以便大家能自己写出新的驱动。

首先,要包含驱动头文件cps.h,语句如下:

#include”cps.h”

再者,是输入设备定义,也不用讲解,照例子抄就行了:

static struct BurnInputInfo DrvInputList[] =
{
{“P1 Coin”  , 0, CpsInp020+4, “p1 coin”  },
{“P1 Start” , 0, CpsInp020+0, “p1 start” },
{“P1 Up”    , 0, CpsInp001+3, “p1 up”    },
{“P1 Down”  , 0, CpsInp001+2, “p1 down”  },
{“P1 Left”  , 0, CpsInp001+1, “p1 left”  },
{“P1 Right” , 0, CpsInp001+0, “p1 right” },
{“P1 Shot”  , 0, CpsInp001+4, “p1 fire 1”},
{“P1 Bomb”  , 0, CpsInp001+5, “p1 fire 2”},
//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);

ROM表的写法我们来看看19XX的写法:

static struct BurnRomInfo NinexxRomDesc[]=
{
//文件名     ,文件长度,CRC校验码 ,类型
{“19xux.03” ,0x80000,0x239a08ae, 0x10}, //  0  XOR 表
{“19xux.04” ,0x80000,0xc13a1072, 0x10}, //  1
{“19xux.05” ,0x80000,0x8c066ec3, 0x10}, //  2
{“19xux.06” ,0x80000,0x4b1caeb9, 0x10}, //  3

{“19xu.03” ,0x80000,0x05955268, 0x10},  //  4  68000 代码 需要上面的进行解密
{“19xu.04” ,0x80000,0x3111ab7f, 0x10},  //  5
{“19xu.05” ,0x80000,0x38df4a63, 0x10},  //  6
{“19xu.06” ,0x80000,0x5c7e60d3, 0x10},  //  7
{“19x.07”  ,0x80000,0x61c0296c, 0x10},  //  8

{“19x.13” ,0x080000,0x427aeb18, 1},     //  9  图像数据,此处要按3,5,7,9,4,6,8,0此类顺序排列
{“19x.15” ,0x080000,0x63bdbf54, 1},     //  10
{“19x.17” ,0x080000,0x2dfe18b5, 1},     //  11
{“19x.19” ,0x080000,0xcbef9579, 1},     //  12
{“19x.14” ,0x200000,0xe916967c, 1},     //  13
{“19x.16” ,0x200000,0x6e75f3db, 1},     //  14
{“19x.18” ,0x200000,0x2213e798, 1},     //  15
{“19x.20” ,0x200000,0xab9d5b96, 1},     //  16

{“19x.01” ,0x020000,0xef55195e, 2},     //  17 QSound数据 z80声音数据

{“19x.11” ,0x200000,0xd38beef3, 2},     //  18 QSound声音采样
{“19x.12” ,0x200000,0xd47c96e2, 2},     //  19
};

STD_ROM_PICK(Ninexx) STD_ROM_FN(Ninexx)

这里面Ninexx是我们自己可以定义的名称,改成_19xx也是可以的。

之后是驱动信息结构,19XX的写法如下:

游戏ROM文件名称,为19xx的话,那对应19xx.zip
游戏名称
注释或其它信息
生产商
机型
出品年代
主ROM名称,例如19xx的西班牙版就需要在这里打上”19xx”
主板BIOS,不使用的话定义为NULL

运行标志,如果为纵版需要加上BDF_ROTATE_GRAPHICS_CCW
最大玩家数量
硬件类型
取zip名称特殊函数
Rom信息结构
Rom名称结构
输入配置信息表
DIP配置表

驱动初始化函数
驱动关闭函数
游戏帧处理函数
游戏刷新函数
游戏剪裁处理函数
游戏调色板空间
游戏画面宽度
游戏画面高度
游戏画面纵横比

struct BurnDriver BurnDrvCps19xx=
{
{“19xx”,
“19XX: The War Against Destiny (US 951207)”,
“”,
“Capcom”,
“CPS2”,
“1995”,
NULL,
NULL},
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函数。下面我们来看一下19XXDrvInit函数,并为大家做详细的讲解:

static int DrvInit()
{
int nRet=0;
int i=0;
unsigned char *pqs=NULL;

Cps=2;                   //CPS1型游戏为1,CPS2型游戏为2

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表时,大家能够不至于等待谁写出新的驱动,而可以自己解决。