Emulate sound in sf2mdt, captcommb2 and knightsb4, all use a Z80 to drive a YM2151 and 2 x MSM5205

This commit is contained in:
Barry Harris 2012-04-16 13:20:45 +00:00
parent 5381fc93d6
commit 7f964103c8
5 changed files with 268 additions and 11 deletions

View File

@ -238,11 +238,15 @@ extern UINT8* CpsEncZRom;
INT32 CpsRwInit();
INT32 CpsRwExit();
INT32 CpsRwGetInp();
void CpsWritePort(const UINT32 ia, UINT8 d);
UINT8 __fastcall CpsReadByte(UINT32 a);
void __fastcall CpsWriteByte(UINT32 a, UINT8 d);
UINT16 __fastcall CpsReadWord(UINT32 a);
void __fastcall CpsWriteWord(UINT32 a, UINT16 d);
typedef void (*CpsRWSoundCommandCallback)(UINT16);
extern CpsRWSoundCommandCallback CpsRWSoundCommandCallbackFunction;
// cps_draw.cpp
extern UINT8 CpsRecalcPal; // Flag - If it is 1, recalc the whole palette
extern INT32 nCpsLcReg; // Address of layer controller register
@ -423,9 +427,17 @@ void slammast_decode();
void cps2_decrypt_game_data();
// fcrash_snd.cpp
void FrcashSoundCommand(UINT16 d);
void FcrashSoundCommand(UINT16 d);
INT32 FcrashSoundInit();
INT32 FcrashSoundReset();
INT32 FcrashSoundExit();
void FcrashSoundFrameStart();
void FcrashSoundFrameEnd();
// sf2mdt_snd.cpp
void Sf2mdtSoundCommand(UINT16 d);
INT32 Sf2mdtSoundInit();
INT32 Sf2mdtSoundReset();
INT32 Sf2mdtSoundExit();
void Sf2mdtSoundFrameStart();
void Sf2mdtSoundFrameEnd();

View File

@ -34,6 +34,8 @@ INT32 Ssf2tb = 0;
INT32 Dinohunt = 0;
INT32 Port6SoundWrite = 0;
CpsRWSoundCommandCallback CpsRWSoundCommandCallbackFunction = NULL;
static INT32 nCalc[2] = {0, 0};
static const bool nCPSExtraNVRAM = false;
@ -281,7 +283,7 @@ static UINT8 CpsReadPort(const UINT32 ia)
}
// Write output port 0x000-0x1ff
static void CpsWritePort(const UINT32 ia, UINT8 d)
void CpsWritePort(const UINT32 ia, UINT8 d)
{
if ((Cps & 1) && Cps1Qs == 0) {
if (!Cps1DisablePSnd) {
@ -300,6 +302,12 @@ static void CpsWritePort(const UINT32 ia, UINT8 d)
PsndFade = d;
return;
}
} else {
if (ia == 0x181 || (Port6SoundWrite && (ia == 0x006 || ia == 0x007))) {
if (CpsRWSoundCommandCallbackFunction) {
CpsRWSoundCommandCallbackFunction(d);
}
}
}
if (ia == 0x041) {
@ -487,6 +495,7 @@ INT32 CpsRwInit()
INT32 CpsRwExit()
{
InpBlank();
CpsRWSoundCommandCallbackFunction = NULL;
return 0;
}

View File

@ -10883,6 +10883,12 @@ static INT32 CaptcommbInit()
static INT32 Captcommb2Init()
{
Cps1DisablePSnd = 1;
CpsRunInitCallbackFunction = Sf2mdtSoundInit;
CpsRunResetCallbackFunction = Sf2mdtSoundReset;
CpsRunExitCallbackFunction = Sf2mdtSoundExit;
CpsRunFrameStartCallbackFunction = Sf2mdtSoundFrameStart;
CpsRunFrameEndCallbackFunction = Sf2mdtSoundFrameEnd;
CpsRWSoundCommandCallbackFunction = Sf2mdtSoundCommand;
return DrvInit();
}
@ -10926,7 +10932,7 @@ void __fastcall CawingblInputWrite(UINT32 a, UINT8 d)
{
switch (a) {
case 0x882006: {
FrcashSoundCommand(d);
FcrashSoundCommand(d);
return;
}
@ -11194,7 +11200,7 @@ void __fastcall FcrashInputWriteWord(UINT32 a, UINT16 d)
{
switch (a) {
case 0x880006: {
FrcashSoundCommand(d);
FcrashSoundCommand(d);
return;
}
@ -11539,9 +11545,16 @@ static INT32 Knightsb4Init()
Cps1DisablePSnd = 1;
bCpsUpdatePalEveryFrame = 1;
Cps1OverrideLayers = 1;
Port6SoundWrite = 1;
Cps1ObjGetCallbackFunction = DinopicObjGet;
Cps1ObjDrawCallbackFunction = FcrashObjDraw;
CpsRunInitCallbackFunction = Sf2mdtSoundInit;
CpsRunResetCallbackFunction = Sf2mdtSoundReset;
CpsRunExitCallbackFunction = Sf2mdtSoundExit;
CpsRunFrameStartCallbackFunction = Sf2mdtSoundFrameStart;
CpsRunFrameEndCallbackFunction = Sf2mdtSoundFrameEnd;
CpsRWSoundCommandCallbackFunction = Sf2mdtSoundCommand;
INT32 nRet = DrvInit();
@ -11998,15 +12011,15 @@ UINT8 __fastcall Sf2mdtReadByte(UINT32 a)
{
switch (a) {
case 0x70c01a: {
return 0xff;
return ~Cpi01A;
}
case 0x70c01c: {
return 0xff;
return ~Cpi01C;
}
case 0x70c01e: {
return 0xff;
return ~Cpi01E;
}
default: {
@ -12033,6 +12046,12 @@ static INT32 Sf2mdtInit()
Cps1GfxLoadCallbackFunction = CpsLoadTilesSf2mdt;
Cps1DisablePSnd = 1;
CpsRunInitCallbackFunction = Sf2mdtSoundInit;
CpsRunResetCallbackFunction = Sf2mdtSoundReset;
CpsRunExitCallbackFunction = Sf2mdtSoundExit;
CpsRunFrameStartCallbackFunction = Sf2mdtSoundFrameStart;
CpsRunFrameEndCallbackFunction = Sf2mdtSoundFrameEnd;
CpsRWSoundCommandCallbackFunction = Sf2mdtSoundCommand;
INT32 nRet = Sf2ceInit();
@ -13109,7 +13128,7 @@ struct BurnDriver BurnDrvCpsCaptcommb = {
struct BurnDriver BurnDrvCpsCaptcommb2 = {
"captcommb2", "captcomm", NULL, NULL, "1991",
"Captain Commando (bootleg, set 2)\0", "No sound", "bootleg", "CPS1",
"Captain Commando (bootleg, set 2)\0", NULL, "bootleg", "CPS1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0,
NULL, Captcommb2RomInfo, Captcommb2RomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo,
@ -13619,7 +13638,7 @@ struct BurnDriver BurnDrvCpsKnightsb3 = {
struct BurnDriver BurnDrvCpsKnightsb4 = {
"knightsb4", "knights", NULL, NULL, "1991",
"Knights of the Round (911127 etc bootleg set 4)\0", "No sound", "bootleg", "CPS1",
"Knights of the Round (911127 etc bootleg set 4)\0", NULL, "bootleg", "CPS1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0,
NULL, Knightsb4RomInfo, Knightsb4RomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo,
@ -14459,7 +14478,7 @@ struct BurnDriver BurnDrvCpsSf2koryu2 = {
struct BurnDriverD BurnDrvCpsSf2mdt = {
"sf2mdt", "sf2ce", NULL, NULL, "1992",
"Street Fighter II' - Magic Delta Turbo (bootleg)\0", "No sound, incorrect graphics", "Capcom", "CPS1",
"Street Fighter II' - Magic Delta Turbo (bootleg)\0", "Incorrect graphics", "Capcom", "CPS1",
NULL, NULL, NULL, NULL,
BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF,
NULL, Sf2mdtRomInfo, Sf2mdtRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo,

View File

@ -17,7 +17,7 @@ static INT32 FcrashSampleSelect2 = 0;
static INT32 FcrashSoundPos = 0;
static INT32 FcrashCyclesPerSegment = 0;
void FrcashSoundCommand(UINT16 d)
void FcrashSoundCommand(UINT16 d)
{
if (d & 0xff) {
INT32 nCyclesToDo = ((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles) - ZetTotalCycles();

View File

@ -0,0 +1,217 @@
#include "cps.h"
#include "burn_ym2151.h"
#include "msm5205.h"
// sf2mdt_snd.cpp
// Sound support for games using similar sound to Street Fighter 2: Magic Delta Turbo
// 1 x YM2151 and 2 x MSM5205
static UINT8 *Sf2mdtZ80Ram = NULL;
static INT32 Sf2mdtZ80BankAddress = 0;
static INT32 Sf2mdtSoundLatch = 0;
static INT32 Sf2mdtMSM5205Interleave = 0;
static INT32 Sf2mdtSampleBuffer1 = 0;
static INT32 Sf2mdtSampleBuffer2 = 0;
static INT32 Sf2mdtSampleSelect1 = 0;
static INT32 Sf2mdtSampleSelect2 = 0;
static INT32 Sf2mdtSoundPos = 0;
static INT32 Sf2mdtCyclesPerSegment = 0;
static INT32 Sf2NumZ80Banks = 0;
void Sf2mdtSoundCommand(UINT16 d)
{
if (d & 0xff) {
INT32 nCyclesToDo = ((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles) - ZetTotalCycles();
INT32 nEnd = Sf2mdtSoundPos + (INT64)Sf2mdtMSM5205Interleave * nCyclesToDo / nCpsZ80Cycles;
for (INT32 i = Sf2mdtSoundPos; i < nEnd; i++) {
ZetRun(Sf2mdtCyclesPerSegment);
MSM5205Update();
Sf2mdtSoundPos = i;
}
Sf2mdtSoundLatch = d & 0xff;
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
}
}
UINT8 __fastcall Sf2mdtZ80Read(UINT16 a)
{
switch (a) {
case 0xd801: {
return BurnYM2151ReadStatus();
}
case 0xdc00: {
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
return Sf2mdtSoundLatch;
}
default: {
bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a);
}
}
return 0;
}
void __fastcall Sf2mdtZ80Write(UINT16 a, UINT8 d)
{
switch (a) {
case 0xd800: {
BurnYM2151SelectRegister(d);
return;
}
case 0xd801: {
BurnYM2151WriteRegister(d);
return;
}
case 0xe000: {
MSM5205SetVolume(0, (d & 0x20) ? 0 : 20);
MSM5205SetVolume(1, (d & 0x10) ? 0 : 20);
Sf2mdtZ80BankAddress = (d & Sf2NumZ80Banks) * 0x4000;
ZetMapArea(0x8000, 0xbfff, 0, CpsZRom + Sf2mdtZ80BankAddress);
ZetMapArea(0x8000, 0xbfff, 2, CpsZRom + Sf2mdtZ80BankAddress);
return;
}
case 0xe400: {
Sf2mdtSampleBuffer1 = d;
return;
}
case 0xe800: {
Sf2mdtSampleBuffer2 = d;
return;
}
default: {
bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d);
}
}
}
inline static INT32 Sf2mdtSynchroniseStream(INT32 nSoundRate)
{
return (INT64)(ZetTotalCycles() * nSoundRate / 3579540);
}
static void Sf2mdtMSM5205Vck0()
{
MSM5205DataWrite(0, Sf2mdtSampleBuffer1 & 0x0f);
Sf2mdtSampleBuffer1 >>= 4;
Sf2mdtSampleSelect1 ^= 1;
if (Sf2mdtSampleSelect1 == 0) {
ZetNmi();
}
}
static void Sf2mdtMSM5205Vck1()
{
MSM5205DataWrite(1, Sf2mdtSampleBuffer2 & 0x0f);
Sf2mdtSampleBuffer2 >>= 4;
Sf2mdtSampleSelect2 ^= 1;
}
INT32 Sf2mdtSoundInit()
{
Sf2mdtZ80Ram = (UINT8*)BurnMalloc(0x800);
ZetInit(0);
ZetOpen(0);
ZetSetReadHandler(Sf2mdtZ80Read);
ZetSetWriteHandler(Sf2mdtZ80Write);
ZetMapArea(0x0000, 0x7fff, 0, CpsZRom + 0x00000);
ZetMapArea(0x0000, 0x7fff, 2, CpsZRom + 0x00000);
ZetMapArea(0x8000, 0xbfff, 0, CpsZRom + 0x08000);
ZetMapArea(0x8000, 0xbfff, 2, CpsZRom + 0x08000);
ZetMapArea(0xd000, 0xd7ff, 0, Sf2mdtZ80Ram );
ZetMapArea(0xd000, 0xd7ff, 1, Sf2mdtZ80Ram );
ZetMapArea(0xd000, 0xd7ff, 2, Sf2mdtZ80Ram );
ZetMemEnd();
ZetClose();
BurnYM2151Init(3579540, 50.0);
MSM5205Init(0, Sf2mdtSynchroniseStream, 24000000 / 64, Sf2mdtMSM5205Vck0, MSM5205_S96_4B, 20, 1);
MSM5205Init(1, Sf2mdtSynchroniseStream, 24000000 / 64, Sf2mdtMSM5205Vck1, MSM5205_S96_4B, 20, 1);
nCpsZ80Cycles = 3579540 * 100 / nBurnFPS;
Sf2NumZ80Banks = (nCpsZRomLen / 0x4000) - 1;
return 0;
}
INT32 Sf2mdtSoundReset()
{
ZetOpen(0);
ZetReset();
BurnYM2151Reset();
MSM5205Reset();
Sf2mdtZ80BankAddress = 2;
ZetMapArea(0x8000, 0xbfff, 0, CpsZRom + Sf2mdtZ80BankAddress);
ZetMapArea(0x8000, 0xbfff, 2, CpsZRom + Sf2mdtZ80BankAddress);
ZetClose();
Sf2mdtSoundLatch = 0;
Sf2mdtSampleBuffer1 = 0;
Sf2mdtSampleBuffer2 = 0;
Sf2mdtSampleSelect1 = 0;
Sf2mdtSampleSelect2 = 0;
return 0;
}
INT32 Sf2mdtSoundExit()
{
ZetExit();
BurnYM2151Exit();
MSM5205Exit();
BurnFree(Sf2mdtZ80Ram);
Sf2mdtZ80BankAddress = 0;
Sf2mdtSoundLatch = 0;
Sf2mdtMSM5205Interleave = 0;
Sf2mdtSampleBuffer1 = 0;
Sf2mdtSampleBuffer2 = 0;
Sf2mdtSampleSelect1 = 0;
Sf2mdtSampleSelect2 = 0;
Sf2mdtCyclesPerSegment = 0;
Sf2NumZ80Banks = 0;
nCpsZ80Cycles = 0;
return 0;
}
void Sf2mdtSoundFrameStart()
{
Sf2mdtMSM5205Interleave = MSM5205CalcInterleave(0, 3579540);
Sf2mdtSoundPos = 0;
Sf2mdtCyclesPerSegment = (INT64)nCpsZ80Cycles / Sf2mdtMSM5205Interleave;
ZetNewFrame();
ZetOpen(0);
}
void Sf2mdtSoundFrameEnd()
{
for (INT32 i = Sf2mdtSoundPos; i < Sf2mdtMSM5205Interleave; i++) {
ZetRun(Sf2mdtCyclesPerSegment);
MSM5205Update();
Sf2mdtSoundPos = i;
}
ZetRun(nCpsZ80Cycles - ZetTotalCycles());
if (pBurnSoundOut) {
BurnYM2151Render(pBurnSoundOut, nBurnSoundLen);
MSM5205Render(0, pBurnSoundOut, nBurnSoundLen);
MSM5205Render(1, pBurnSoundOut, nBurnSoundLen);
}
ZetClose();
}