From 7f964103c842b88e68c23b292361fb63e944b475 Mon Sep 17 00:00:00 2001 From: Barry Harris <44396066+barry65536@users.noreply.github.com> Date: Mon, 16 Apr 2012 13:20:45 +0000 Subject: [PATCH] Emulate sound in sf2mdt, captcommb2 and knightsb4, all use a Z80 to drive a YM2151 and 2 x MSM5205 --- src/burn/drv/capcom/cps.h | 14 +- src/burn/drv/capcom/cps_rw.cpp | 11 +- src/burn/drv/capcom/d_cps1.cpp | 35 +++-- src/burn/drv/capcom/fcrash_snd.cpp | 2 +- src/burn/drv/capcom/sf2mdt_snd.cpp | 217 +++++++++++++++++++++++++++++ 5 files changed, 268 insertions(+), 11 deletions(-) create mode 100644 src/burn/drv/capcom/sf2mdt_snd.cpp diff --git a/src/burn/drv/capcom/cps.h b/src/burn/drv/capcom/cps.h index ca9b41d97..8001058f2 100644 --- a/src/burn/drv/capcom/cps.h +++ b/src/burn/drv/capcom/cps.h @@ -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(); diff --git a/src/burn/drv/capcom/cps_rw.cpp b/src/burn/drv/capcom/cps_rw.cpp index abcc3e4bd..fa20879ce 100644 --- a/src/burn/drv/capcom/cps_rw.cpp +++ b/src/burn/drv/capcom/cps_rw.cpp @@ -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; } diff --git a/src/burn/drv/capcom/d_cps1.cpp b/src/burn/drv/capcom/d_cps1.cpp index 741e7fe83..a5e83040d 100644 --- a/src/burn/drv/capcom/d_cps1.cpp +++ b/src/burn/drv/capcom/d_cps1.cpp @@ -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, diff --git a/src/burn/drv/capcom/fcrash_snd.cpp b/src/burn/drv/capcom/fcrash_snd.cpp index 2c10205c6..76f44cf1e 100644 --- a/src/burn/drv/capcom/fcrash_snd.cpp +++ b/src/burn/drv/capcom/fcrash_snd.cpp @@ -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(); diff --git a/src/burn/drv/capcom/sf2mdt_snd.cpp b/src/burn/drv/capcom/sf2mdt_snd.cpp new file mode 100644 index 000000000..f3f82b85b --- /dev/null +++ b/src/burn/drv/capcom/sf2mdt_snd.cpp @@ -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(); +}