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 CpsRwInit();
INT32 CpsRwExit(); INT32 CpsRwExit();
INT32 CpsRwGetInp(); INT32 CpsRwGetInp();
void CpsWritePort(const UINT32 ia, UINT8 d);
UINT8 __fastcall CpsReadByte(UINT32 a); UINT8 __fastcall CpsReadByte(UINT32 a);
void __fastcall CpsWriteByte(UINT32 a, UINT8 d); void __fastcall CpsWriteByte(UINT32 a, UINT8 d);
UINT16 __fastcall CpsReadWord(UINT32 a); UINT16 __fastcall CpsReadWord(UINT32 a);
void __fastcall CpsWriteWord(UINT32 a, UINT16 d); void __fastcall CpsWriteWord(UINT32 a, UINT16 d);
typedef void (*CpsRWSoundCommandCallback)(UINT16);
extern CpsRWSoundCommandCallback CpsRWSoundCommandCallbackFunction;
// cps_draw.cpp // cps_draw.cpp
extern UINT8 CpsRecalcPal; // Flag - If it is 1, recalc the whole palette extern UINT8 CpsRecalcPal; // Flag - If it is 1, recalc the whole palette
extern INT32 nCpsLcReg; // Address of layer controller register extern INT32 nCpsLcReg; // Address of layer controller register
@ -423,9 +427,17 @@ void slammast_decode();
void cps2_decrypt_game_data(); void cps2_decrypt_game_data();
// fcrash_snd.cpp // fcrash_snd.cpp
void FrcashSoundCommand(UINT16 d); void FcrashSoundCommand(UINT16 d);
INT32 FcrashSoundInit(); INT32 FcrashSoundInit();
INT32 FcrashSoundReset(); INT32 FcrashSoundReset();
INT32 FcrashSoundExit(); INT32 FcrashSoundExit();
void FcrashSoundFrameStart(); void FcrashSoundFrameStart();
void FcrashSoundFrameEnd(); 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 Dinohunt = 0;
INT32 Port6SoundWrite = 0; INT32 Port6SoundWrite = 0;
CpsRWSoundCommandCallback CpsRWSoundCommandCallbackFunction = NULL;
static INT32 nCalc[2] = {0, 0}; static INT32 nCalc[2] = {0, 0};
static const bool nCPSExtraNVRAM = false; static const bool nCPSExtraNVRAM = false;
@ -281,7 +283,7 @@ static UINT8 CpsReadPort(const UINT32 ia)
} }
// Write output port 0x000-0x1ff // 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 ((Cps & 1) && Cps1Qs == 0) {
if (!Cps1DisablePSnd) { if (!Cps1DisablePSnd) {
@ -300,6 +302,12 @@ static void CpsWritePort(const UINT32 ia, UINT8 d)
PsndFade = d; PsndFade = d;
return; return;
} }
} else {
if (ia == 0x181 || (Port6SoundWrite && (ia == 0x006 || ia == 0x007))) {
if (CpsRWSoundCommandCallbackFunction) {
CpsRWSoundCommandCallbackFunction(d);
}
}
} }
if (ia == 0x041) { if (ia == 0x041) {
@ -487,6 +495,7 @@ INT32 CpsRwInit()
INT32 CpsRwExit() INT32 CpsRwExit()
{ {
InpBlank(); InpBlank();
CpsRWSoundCommandCallbackFunction = NULL;
return 0; return 0;
} }

View File

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

View File

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